Commit 5a51687e authored by Jody Goldberg's avatar Jody Goldberg

Implement rudimentary object handling in the escher code.

Enable buttons, and checkboxes.  Placement is a bit off.
parent 81cbeb1e
1999-09-19 Jody Goldberg <jgoldberg@home.com>
* src/value.c (value_release) : Releasing value_terminate should not
generate an error.
* src/sheet-object-container.h : Add include
<bonobo/gnome-client-site.h>.
1999-09-18 Jody Goldberg <jgoldberg@home.com>
* src/sheet-object.h : Make SheetObjectType names
constistant with SheetModeType names, and add
GRAPHIC, BUTTON, and CHECKBOX.
* plugins/html/epsf.c (epsf_write_wb) : RECTANGLE -> BOX.
ELLIPSE -> OVAL.
* src/sheet-object.c (create_object) : Ditto.
* src/xml-io.c (xml_read_sheet_object) : Ditto.
1999-09-18 Miguel de Icaza <miguel@gnu.org> 1999-09-18 Miguel de Icaza <miguel@gnu.org>
* src/dialogs/dialog-simple-input.c (dialog_get_sheet_name): use * src/dialogs/dialog-simple-input.c (dialog_get_sheet_name): use
...@@ -16,7 +35,7 @@ ...@@ -16,7 +35,7 @@
terminate. terminate.
* src/workbook-cmd-format.c (do_apply_style_to_selection): set * src/workbook-cmd-format.c (do_apply_style_to_selection): set
shett dirty. sheet dirty.
(workbook_cmd_format_column_auto_fit): ditto. (workbook_cmd_format_column_auto_fit): ditto.
(workbook_cmd_format_column_width): ditto. (workbook_cmd_format_column_width): ditto.
(workbook_cmd_format_row_auto_fit): ditto. (workbook_cmd_format_row_auto_fit): ditto.
......
1999-09-19 Jody Goldberg <jgoldberg@home.com>
* src/value.c (value_release) : Releasing value_terminate should not
generate an error.
* src/sheet-object-container.h : Add include
<bonobo/gnome-client-site.h>.
1999-09-18 Jody Goldberg <jgoldberg@home.com>
* src/sheet-object.h : Make SheetObjectType names
constistant with SheetModeType names, and add
GRAPHIC, BUTTON, and CHECKBOX.
* plugins/html/epsf.c (epsf_write_wb) : RECTANGLE -> BOX.
ELLIPSE -> OVAL.
* src/sheet-object.c (create_object) : Ditto.
* src/xml-io.c (xml_read_sheet_object) : Ditto.
1999-09-18 Miguel de Icaza <miguel@gnu.org> 1999-09-18 Miguel de Icaza <miguel@gnu.org>
* src/dialogs/dialog-simple-input.c (dialog_get_sheet_name): use * src/dialogs/dialog-simple-input.c (dialog_get_sheet_name): use
...@@ -16,7 +35,7 @@ ...@@ -16,7 +35,7 @@
terminate. terminate.
* src/workbook-cmd-format.c (do_apply_style_to_selection): set * src/workbook-cmd-format.c (do_apply_style_to_selection): set
shett dirty. sheet dirty.
(workbook_cmd_format_column_auto_fit): ditto. (workbook_cmd_format_column_auto_fit): ditto.
(workbook_cmd_format_column_width): ditto. (workbook_cmd_format_column_width): ditto.
(workbook_cmd_format_row_auto_fit): ditto. (workbook_cmd_format_row_auto_fit): ditto.
......
1999-09-19 Jody Goldberg <jgoldberg@home.com>
* ms-summary.c (set_summary_item) : Made static.
* ms-obj.c (ms_obj_realize) : New function.
(ms_parse_object_anchor) : Ditto.
* ms-excel-read.c (ms_excel_read_workbook) : Use
ms_obj_realize.
(ms_excel_read_sheet) : Ditto.
(ms_excel_read_formula) : Make reading a string more
robust, and support length = 0 as a valid string.
1999-09-19 Michael Meeks <michael@nuclecu.unam.mx> 1999-09-19 Michael Meeks <michael@nuclecu.unam.mx>
* Makefile.am: comment out ole. * Makefile.am: comment out ole.
...@@ -30,8 +43,10 @@ ...@@ -30,8 +43,10 @@
* ms-escher.c : More radical changes to support just in time * ms-escher.c : More radical changes to support just in time
merging. This seems to solve the last of the problems of which merging. This seems to solve the last of the problems of which
records to merge and which not. Everything seems to add up. records to merge and which not. Everything seems to add up.
(ms_escher_parse) : Enable by default.
* ms-escher.c (ms_escher_parse) : Enable by default. * ms-excel-read.c (ms_excel_workbook_destroy) : Release blips on
exit.
1999-09-17 Jody Goldberg <jgoldberg@home.com> 1999-09-17 Jody Goldberg <jgoldberg@home.com>
......
...@@ -2015,7 +2015,7 @@ ms_excel_chart (BiffQuery *q, ExcelWorkbook *wb, BIFF_BOF_DATA *bof) ...@@ -2015,7 +2015,7 @@ ms_excel_chart (BiffQuery *q, ExcelWorkbook *wb, BIFF_BOF_DATA *bof)
} }
void void
ms_excel_read_chart (BiffQuery *q, ExcelWorkbook *wb, int obj_id) ms_excel_read_chart (BiffQuery *q, ExcelWorkbook *wb)
{ {
BIFF_BOF_DATA *bof; BIFF_BOF_DATA *bof;
......
...@@ -15,7 +15,7 @@ extern void ms_excel_chart (BiffQuery *q, ExcelWorkbook *wb, ...@@ -15,7 +15,7 @@ extern void ms_excel_chart (BiffQuery *q, ExcelWorkbook *wb,
BIFF_BOF_DATA *bof); BIFF_BOF_DATA *bof);
/* A wrapper which reads and checks the BOF record then calls ms_excel_chart */ /* A wrapper which reads and checks the BOF record then calls ms_excel_chart */
extern void ms_excel_read_chart (BiffQuery *q, ExcelWorkbook *wb, int id); extern void ms_excel_read_chart (BiffQuery *q, ExcelWorkbook *wb);
extern void ms_excel_biff_dimensions (BiffQuery *q, ExcelWorkbook *wb); extern void ms_excel_biff_dimensions (BiffQuery *q, ExcelWorkbook *wb);
......
This diff is collapsed.
...@@ -9,8 +9,19 @@ ...@@ -9,8 +9,19 @@
**/ **/
#include "ms-excel-read.h" #include "ms-excel-read.h"
typedef struct {
char const * reproid;
#ifdef ENABLE_BONOBO
GnomeStream * stream;
#else
guint8 * raw_data;
#endif
} EscherBlip;
extern void ms_escher_parse (BiffQuery *q, extern void ms_escher_parse (BiffQuery *q,
ExcelWorkbook *wb, ExcelWorkbook *wb,
ExcelSheet *sheet); ExcelSheet *sheet);
extern void ms_escher_blip_destroy(EscherBlip * blip);
#endif /* GNUMERIC_MS_OFFICE_ESCHER_H */ #endif /* GNUMERIC_MS_OFFICE_ESCHER_H */
...@@ -1592,18 +1592,22 @@ ms_excel_read_formula (BiffQuery *q, ExcelSheet *sheet) ...@@ -1592,18 +1592,22 @@ ms_excel_read_formula (BiffQuery *q, ExcelSheet *sheet)
if (is_string) { if (is_string) {
guint16 code; guint16 code;
if (ms_biff_query_peek_next(q, &code) && code == BIFF_STRING) { if (ms_biff_query_peek_next(q, &code) && code == BIFF_STRING) {
char *v; char *v = NULL;
ms_biff_query_next (q); if (ms_biff_query_next (q)) {
/* /*
* NOTE : the Excel developers kit docs are * NOTE : the Excel developers kit docs are
* WRONG. There is an article that * WRONG. There is an article that
* clarifies the behaviour to be the std * clarifies the behaviour to be the std
* unicode format rather than the pure * unicode format rather than the pure
* length version the docs describe. * length version the docs describe.
*/ */
v = biff_get_text (q->data + 2, guint16 const len = MS_OLE_GET_GUINT16(q->data);
MS_OLE_GET_GUINT16(q->data),
NULL); if (len > 0)
v = biff_get_text (q->data + 2, len, NULL);
else
v = g_strdup(""); /* Pre-Biff8 seems to use len=0 */
}
if (v) { if (v) {
val = value_new_string (v); val = value_new_string (v);
g_free (v); g_free (v);
...@@ -1739,12 +1743,12 @@ ms_excel_workbook_new (eBiff_version ver) ...@@ -1739,12 +1743,12 @@ ms_excel_workbook_new (eBiff_version ver)
ans->excel_sheets = g_ptr_array_new (); ans->excel_sheets = g_ptr_array_new ();
ans->XF_cell_records = g_ptr_array_new (); ans->XF_cell_records = g_ptr_array_new ();
ans->name_data = g_ptr_array_new (); ans->name_data = g_ptr_array_new ();
ans->charts = NULL; /* Init if/when its needed */ ans->blips = g_ptr_array_new ();
ans->charts = g_ptr_array_new ();
ans->format_data = g_hash_table_new ((GHashFunc)biff_guint16_hash, ans->format_data = g_hash_table_new ((GHashFunc)biff_guint16_hash,
(GCompareFunc)biff_guint16_equal); (GCompareFunc)biff_guint16_equal);
ans->palette = ms_excel_default_palette (); ans->palette = ms_excel_default_palette ();
ans->ver = ver; ans->ver = ver;
ans->eschers = NULL;
ans->global_strings = NULL; ans->global_strings = NULL;
ans->global_string_max = 0; ans->global_string_max = 0;
ans->read_drawing_group = 0; ans->read_drawing_group = 0;
...@@ -1809,13 +1813,15 @@ ms_excel_workbook_destroy (ExcelWorkbook *wb) ...@@ -1809,13 +1813,15 @@ ms_excel_workbook_destroy (ExcelWorkbook *wb)
biff_name_data_destroy (g_ptr_array_index (wb->name_data, lp)); biff_name_data_destroy (g_ptr_array_index (wb->name_data, lp));
g_ptr_array_free (wb->name_data, TRUE); g_ptr_array_free (wb->name_data, TRUE);
if (wb->charts != NULL) for (lp=0;lp<wb->blips->len;lp++)
{ ms_escher_blip_destroy (g_ptr_array_index(wb->blips, lp));
for (lp=0;lp<wb->charts->len;lp++) g_ptr_array_free (wb->blips, TRUE);
gnumeric_chart_destroy (g_ptr_array_index(wb->charts, lp)); wb->blips = NULL;
g_ptr_array_free (wb->charts, TRUE);
wb->charts = NULL; for (lp=0;lp<wb->charts->len;lp++)
} gnumeric_chart_destroy (g_ptr_array_index(wb->charts, lp));
g_ptr_array_free (wb->charts, TRUE);
wb->charts = NULL;
g_hash_table_foreach_remove (wb->font_data, g_hash_table_foreach_remove (wb->font_data,
(GHRFunc)biff_font_data_destroy, (GHRFunc)biff_font_data_destroy,
...@@ -2424,7 +2430,8 @@ ms_excel_read_sheet (ExcelSheet *sheet, BiffQuery *q, ExcelWorkbook *wb) ...@@ -2424,7 +2430,8 @@ ms_excel_read_sheet (ExcelSheet *sheet, BiffQuery *q, ExcelWorkbook *wb)
break; break;
case BIFF_OBJ: /* See: ms-obj.c and S59DAD.HTM */ case BIFF_OBJ: /* See: ms-obj.c and S59DAD.HTM */
ms_read_OBJ (q, wb); ms_obj_realize(ms_read_OBJ (q, wb, sheet->gnum_sheet),
wb, sheet);
break; break;
case BIFF_SELECTION: case BIFF_SELECTION:
...@@ -3179,7 +3186,10 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file) ...@@ -3179,7 +3186,10 @@ ms_excel_read_workbook (Workbook *workbook, MsOle *file)
break; break;
case BIFF_OBJ: /* See: ms-obj.c and S59DAD.HTM */ case BIFF_OBJ: /* See: ms-obj.c and S59DAD.HTM */
ms_read_OBJ (q, wb); /* FIXME : What does it mean to have an object
* outside a sheet ???? */
ms_obj_realize(ms_read_OBJ (q, wb, NULL),
wb, NULL);
break; break;
case BIFF_SCL : case BIFF_SCL :
......
...@@ -94,7 +94,9 @@ typedef struct _ExcelWorkbook ...@@ -94,7 +94,9 @@ typedef struct _ExcelWorkbook
char **global_strings; char **global_strings;
int global_string_max; int global_string_max;
eBiff_version ver; eBiff_version ver;
GList *eschers;
/* Indexed in the order they are read */
GPtrArray *blips;
GPtrArray *charts; GPtrArray *charts;
/** /**
......
...@@ -679,10 +679,17 @@ make_function (ParseList **stack, int fn_idx, int numargs) ...@@ -679,10 +679,17 @@ make_function (ParseList **stack, int fn_idx, int numargs)
/* FIXME FIXME FIXME : How to handle missing trailing args ?? */ /* FIXME FIXME FIXME : How to handle missing trailing args ?? */
ParseList *args = parse_list_last_n (stack, numargs-1); ParseList *args = parse_list_last_n (stack, numargs-1);
ExprTree *tmp = parse_list_pop (stack) ; ExprTree *tmp = parse_list_pop (stack) ;
char const *f_name; char const *f_name = NULL;
if (!tmp ||
tmp->oper != OPER_CONSTANT || if (tmp != NULL) {
tmp->u.constant->type != VALUE_STRING) { if (tmp->oper == OPER_CONSTANT &&
tmp->u.constant->type == VALUE_STRING)
f_name = tmp->u.constant->v.str->str;
else if (tmp->oper == OPER_NAME)
f_name = tmp->u.name->name->str;
}
if (f_name == NULL) {
if (tmp) expr_tree_unref (tmp); if (tmp) expr_tree_unref (tmp);
parse_list_free (&args); parse_list_free (&args);
parse_list_push_raw (stack, parse_list_push_raw (stack,
...@@ -691,7 +698,6 @@ make_function (ParseList **stack, int fn_idx, int numargs) ...@@ -691,7 +698,6 @@ make_function (ParseList **stack, int fn_idx, int numargs)
printf ("So much for that theory.\n"); printf ("So much for that theory.\n");
return FALSE; return FALSE;
} }
f_name = tmp->u.constant->v.str->str;
name = symbol_lookup (global_symbol_table, f_name); name = symbol_lookup (global_symbol_table, f_name);
if (!name) if (!name)
......
...@@ -33,41 +33,108 @@ extern int ms_excel_read_debug; ...@@ -33,41 +33,108 @@ extern int ms_excel_read_debug;
#define GR_CHECKBOX_FORMULA 0x14 #define GR_CHECKBOX_FORMULA 0x14
#define GR_COMMON_OBJ_DATA 0x15 #define GR_COMMON_OBJ_DATA 0x15
static char * /*
object_type_names[] = * Attempt to install ab object in supplied work book.
* NOTE : The MSObj is freed by this routine
*/
gboolean
ms_obj_realize(MSObj * obj, ExcelWorkbook *wb, ExcelSheet * sheet)
{ {
"Group", /* 0x00 */ int * anchor = NULL;
"Line", /* 0x01 */ if (obj == NULL)
"Rectangle", /* 0x02 */ return TRUE;
"Oval", /* 0x03 */
"Arc", /* 0x04 */ anchor = obj->anchor;
"Chart", /* 0x05 */
"TextBox", /* 0x06 */ switch (obj->gnumeric_type) {
"Button", /* 0x07 */ case SHEET_OBJECT_BUTTON :
"Picture", /* 0x08 */ sheet_object_create_button (sheet->gnum_sheet,
"Polygon", /* 0x09 */ anchor[0], anchor[1],
NULL, /* 0x0A */ anchor[2], anchor[3]);
"CheckBox", /* 0x0B */ break;
"Option", /* 0x0C */
"Edit", /* 0x0D */ case SHEET_OBJECT_CHECKBOX :
"Label", /* 0x0E */ sheet_object_create_checkbox (sheet->gnum_sheet,
"Dialog", /* 0x0F */ anchor[0], anchor[1],
"Spinner", /* 0x10 */ anchor[2], anchor[3]);
"Scroll", /* 0x11 */ break;
"List", /* 0x12 */
"Group", /* 0x13 */ case SHEET_OBJECT_GRAPHIC : /* If this was a picture */
"Combo", /* 0x14 */ {
NULL, /* 0x15 */ int blip_id;
NULL, /* 0x16 */ GPtrArray const * blips = wb->blips;
NULL, /* 0x17 */ EscherBlip *blip = NULL;
NULL, /* 0x18 */ #ifdef ENABLE_BONOBO
"Comment", /* 0x19 */ SheetObject *so;
NULL, /* 0x1A */ #endif
NULL, /* 0x1B */
NULL, /* 0x1C */ blip_id = obj->v.picture.blip_id;
NULL, /* 0x1D */
"MS Drawing" /* 0x1E */ g_return_val_if_fail (blip_id >= 0, FALSE);
}; g_return_val_if_fail (blip_id < blips->len, FALSE);
blip = g_ptr_array_index (blips, blip_id);
g_return_val_if_fail (blip != NULL, FALSE);
#ifdef ENABLE_BONOBO
g_return_val_if_fail (blip->stream != NULL, FALSE);
g_return_val_if_fail (blip->reproid != NULL, FALSE);
so = sheet_object_container_new (sheet->gnum_sheet,
anchor[0], anchor[1],
anchor[2], anchor[3],
blip->reproid);
if (!sheet_object_container_load (so, blip->stream, TRUE))
g_warning ("Failed to load '%s' from stream",
blip->reproid);
#endif
}
break;
default :
break;
};
g_free (obj);
return FALSE;
}
gboolean
ms_parse_object_anchor (int anchor[4],
Sheet const * sheet, guint8 const * data)
{
/* Words 0, 4, 8, 12 : The row/col of the corners */
/* Words 2, 6, 10, 14 : distance from cell edge measured in 1/1024 of an inch */
float zoom;
int i;
/* FIXME : How to handle objects not in sheets ?? */
g_return_val_if_fail (sheet != NULL, TRUE);
zoom = sheet->last_zoom_factor_used;
for (i = 0; i < 4; ++i) {
guint16 const pos = MS_OLE_GET_GUINT16(data + 4*i);
float margin = (MS_OLE_GET_GUINT16(data + 4*i + 2) / (1024./72.));
/* FIXME : we are slightly off. What about margins ? */
float const tmp = (i&1) /* odds are rows */
? sheet_row_get_unit_distance (sheet, 0, pos)
: sheet_col_get_unit_distance (sheet, 0, pos);
margin += tmp;
margin *= zoom;
anchor[i] = (int)margin;
}
#ifndef NO_DEBUG_EXCEL
if (ms_excel_read_debug > 0)
printf ("In pixels left = %d, top = %d, right = %d, bottom =d %d;\n",
anchor[0], anchor[1], anchor[2], anchor[3]);
#endif
return FALSE;
}
void void
ms_read_TXO (BiffQuery *q, ExcelWorkbook * wb) ms_read_TXO (BiffQuery *q, ExcelWorkbook * wb)
...@@ -157,63 +224,31 @@ ms_obj_dump (guint8 const * const data, int const len, char const * const name) ...@@ -157,63 +224,31 @@ ms_obj_dump (guint8 const * const data, int const len, char const * const name)
printf ("}; /* %s */\n", name); printf ("}; /* %s */\n", name);
} }
static gboolean
static void ms_obj_read_pre_biff8_obj (BiffQuery *q, ExcelWorkbook * wb,
ms_obj_read_pre_biff8_obj (BiffQuery *q, ExcelWorkbook * wb) Sheet * sheet, MSObj * obj)
{ {
static char const * const obj_types[] = { /* TODO : Lots of docs for these things. Write the parser. */
"Group", "Line", "Rectangle", "Oval", "Arc", "Chart", "Text",
"Button", "Picture", "Polygon", "Checkbox", "OptionButton",
"Edit box", "Label", "Dialog frame", "Spinner", "Listbox",
"Group box", "Dropdown"
};
#if 0 #if 0
guint32 const numObjects = MS_OLE_GET_GUINT32(q->data); guint32 const numObjects = MS_OLE_GET_GUINT16(q->data);
guint16 const flags = MS_OLE_GET_GUINT32(q->data+8); guint16 const flags = MS_OLE_GET_GUINT16(q->data+8);
#endif #endif
guint16 tmp = MS_OLE_GET_GUINT32(q->data+4); obj->excel_type = MS_OLE_GET_GUINT16(q->data+4);
guint16 const obj_id = MS_OLE_GET_GUINT32(q->data+6); obj->id = MS_OLE_GET_GUINT32(q->data+6);
guint16 const left_col = MS_OLE_GET_GUINT32(q->data+10);
guint16 const top_row = MS_OLE_GET_GUINT32(q->data+14);
guint16 const right_col = MS_OLE_GET_GUINT32(q->data+18);
guint16 const bottom_row = MS_OLE_GET_GUINT32(q->data+22);
/* As 1/1024 of cell width */
guint16 const left_offset = MS_OLE_GET_GUINT32(q->data+12);
guint16 const top_offset = MS_OLE_GET_GUINT32(q->data+16);
guint16 const right_offset = MS_OLE_GET_GUINT32(q->data+20);
guint16 const bottom_offset = MS_OLE_GET_GUINT32(q->data+24);
if (tmp >= (sizeof(obj_types)/sizeof(char const * const))) {
printf ("EXCEL : invalid object type %d\n", tmp);
return;
}
if (ms_excel_read_debug > 0) { return ms_parse_object_anchor (obj->anchor, sheet, q->data+10);
printf ("EXCEL : Found %s @ (%s%d + %f %%, %f %%):(%s%d + %f %%, %f %%)\n",
obj_types[tmp],
col_name(left_col), top_row+1,
left_offset/1024., top_offset/1024.,
col_name(right_col), bottom_row+1,
right_offset/1024., bottom_offset/1024.);
}
if (tmp == 0x5)
ms_excel_read_chart (q, wb, obj_id);
} }
static void static gboolean
ms_obj_read_biff8_obj (BiffQuery *q, ExcelWorkbook * wb) ms_obj_read_biff8_obj (BiffQuery *q, ExcelWorkbook * wb, Sheet * sheet, MSObj * obj)
{ {
guint8 *data; guint8 *data;
gint32 data_len_left; gint32 data_len_left;
int obj_type = -1; /* Set to undefined */
int obj_id = -1;
gboolean hit_end = FALSE; gboolean hit_end = FALSE;
g_return_if_fail (q); g_return_val_if_fail (q, TRUE);
g_return_if_fail (q->ls_op == BIFF_OBJ); g_return_val_if_fail (q->ls_op == BIFF_OBJ, TRUE);
data = q->data; data = q->data;
data_len_left = q->length; data_len_left = q->length;
...@@ -226,12 +261,13 @@ ms_obj_read_biff8_obj (BiffQuery *q, ExcelWorkbook * wb) ...@@ -226,12 +261,13 @@ ms_obj_read_biff8_obj (BiffQuery *q, ExcelWorkbook * wb)
guint16 const len = MS_OLE_GET_GUINT16(data+2); guint16 const len = MS_OLE_GET_GUINT16(data+2);
/* 1st record must be COMMON_OBJ*/ /* 1st record must be COMMON_OBJ*/
g_return_if_fail (obj_type >= 0 || g_return_val_if_fail (obj->excel_type >= 0 ||
record_type == GR_COMMON_OBJ_DATA); record_type == GR_COMMON_OBJ_DATA,
TRUE);
switch (record_type) { switch (record_type) {
case GR_END: case GR_END:
g_return_if_fail (len == 0); g_return_val_if_fail (len == 0, TRUE);
hit_end = TRUE; hit_end = TRUE;
break; break;
...@@ -311,33 +347,26 @@ ms_obj_read_biff8_obj (BiffQuery *q, ExcelWorkbook * wb) ...@@ -311,33 +347,26 @@ ms_obj_read_biff8_obj (BiffQuery *q, ExcelWorkbook * wb)
case GR_COMMON_OBJ_DATA: case GR_COMMON_OBJ_DATA:
{ {
char const *type_name = NULL;
guint16 const options =MS_OLE_GET_GUINT16(data+8); guint16 const options =MS_OLE_GET_GUINT16(data+8);
/* Multiple objects in 1 record ?? */ /* Multiple objects in 1 record ?? */
g_return_if_fail (obj_type == -1); g_return_val_if_fail (obj->excel_type == -1, -1);
obj_type = MS_OLE_GET_GUINT16(data+4); obj->excel_type = MS_OLE_GET_GUINT16(data+4);
obj_id = MS_OLE_GET_GUINT16(data+6); obj->id = MS_OLE_GET_GUINT16(data+6);
if (obj_type<sizeof(object_type_names)/sizeof(char*))