[gnumeric] XLS: start cleaning up writing of objects.



commit a9f11fbe51b633d8d8a8f092b350355443b62021
Author: Morten Welinder <terra gnome org>
Date:   Sun Oct 4 19:20:35 2009 -0400

    XLS: start cleaning up writing of objects.

 NEWS                           |    1 +
 plugins/excel/ChangeLog        |   11 ++
 plugins/excel/ms-biff.c        |    7 +-
 plugins/excel/ms-escher.c      |  209 ++++++++++++++++------------------------
 plugins/excel/ms-escher.h      |   30 ++++--
 plugins/excel/ms-excel-write.c |   74 ++++++++-------
 6 files changed, 160 insertions(+), 172 deletions(-)
---
diff --git a/NEWS b/NEWS
index 1c3e7b9..5909723 100644
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,7 @@ Morten:
 	* Fix sheet object/clipboard related critical on exit.  [#596509]
 	* Fix Excel-crashing export problem with objects.  [#596886]
 	* Add name property to sheet objects.
+	* Start cleaning up xls sheet object writing.
 
 --------------------------------------------------------------------------
 Gnumeric 1.9.13
diff --git a/plugins/excel/ChangeLog b/plugins/excel/ChangeLog
index 1518097..d3ddc1f 100644
--- a/plugins/excel/ChangeLog
+++ b/plugins/excel/ChangeLog
@@ -1,3 +1,14 @@
+2009-10-04  Morten Welinder  <terra gnome org>
+
+	* ms-escher.c (ms_escher_get_inst, ms_escher_set_inst,
+	ms_escher_spcontainer_start, ms_escher_spcontainer_end,
+	ms_escher_sp, ms_escher_opt_start, ms_escher_opt_end,
+	ms_escher_opt_add_simple, ms_escher_clientanchor,
+	ms_escher_clientdata): New functions.
+
+	* ms-excel-write.c (excel_write_textbox_v8): Use new Escher output
+	utilities.
+
 2009-10-02  Morten Welinder  <terra gnome org>
 
 	* ms-excel-write.c (excel_sheet_new): Display name of sheet
diff --git a/plugins/excel/ms-biff.c b/plugins/excel/ms-biff.c
index 1dce3b2..1a5961e 100644
--- a/plugins/excel/ms-biff.c
+++ b/plugins/excel/ms-biff.c
@@ -651,7 +651,7 @@ ms_biff_max_record_len (BiffPut const *bp)
 }
 
 void
-ms_biff_put_var_write  (BiffPut *bp, guint8 const *data, guint32 len)
+ms_biff_put_var_write (BiffPut *bp, guint8 const *data, guint32 len)
 {
 	g_return_if_fail (bp != NULL);
 	g_return_if_fail (data != NULL);
@@ -693,7 +693,7 @@ ms_biff_put_var_seekto (BiffPut *bp, int pos)
 static void
 ms_biff_put_var_commit (BiffPut *bp)
 {
-	guint8   tmp [4];
+	guint8 tmp [4];
 	int endpos;
 
 	g_return_if_fail (bp != NULL);
@@ -713,10 +713,11 @@ ms_biff_put_var_commit (BiffPut *bp)
 	bp->streamPos  = endpos;
 	bp->curpos     = 0;
 }
+
 static void
 ms_biff_put_len_commit (BiffPut *bp)
 {
-	guint8  tmp[4];
+	guint8 tmp[4];
 
 	g_return_if_fail (bp != NULL);
 	g_return_if_fail (bp->output != NULL);
diff --git a/plugins/excel/ms-escher.c b/plugins/excel/ms-escher.c
index 6771b68..704a0d2 100644
--- a/plugins/excel/ms-escher.c
+++ b/plugins/excel/ms-escher.c
@@ -1301,7 +1301,7 @@ ms_escher_read_OPT (MSEscherState *state, MSEscherHeader *h)
 	char const *name;
 	int i;
 
-	/* lets be really careful */
+	/* let's be really careful */
 	g_return_val_if_fail (6*num_properties + COMMON_HEADER_LEN <= h->len, TRUE);
 	g_return_val_if_fail (data != NULL, TRUE);
 
@@ -2181,151 +2181,112 @@ ms_escher_parse (BiffQuery *q, MSContainer *container, gboolean return_attrs)
 
 /*********************************************************************/
 
-static guint8 const Sp_header[] = {
-/* SpContainer */
-	0xf,   0,	/* ver = f, inst = 0 */
-	0x04, 0xf0,	/* type = SpContainer */
-	0, 0, 0, 0,	/*	store total len */
-
-/* Sp */
-	0, 0,		/*	store (shape type << 4) | 2 */
-	0x0a, 0xf0,	/* type = Sp */
-	8, 0, 0, 0,	/* len = 8 */
-	0, 0, 0, 0,	/*	store spid */
-	0, 0xa, 0, 0,
-
-/* OPT */
-	0, 0,		/*	store (count << 4) | 0x3) */
-	0x0b, 0xf0,	/* type = OPT */
-	0, 0, 0, 0,	/*	store (count * 6) + complex sizes */
-};
-
-static guint8 const Sp_footer[] = {
-/* ClientAnchor */
-	0, 0,		/* ver = inst = 0 */
-	0x10, 0xf0,	/* type = ClientAnchor */
-	0x12, 0, 0, 0,	/* len = 0x12 */
-	0, 0,		/*  anchor flags */
-	0,0,  0,0,	0,0,  0,0,	0,0,  0,0,	0,0,  0,0,
-
-/* ClientData */
-	0, 0,		/* ver = inst = 0 */
-	0x11, 0xf0,	/* type = ClientAnchor */
-	0, 0, 0, 0
-};
+guint
+ms_escher_get_inst (GString *buf, gsize marker)
+{
+	guint16 iv = GSF_LE_GET_GUINT16 (buf->str + marker);
+	return (iv >> 4);
+}
 
-typedef struct {
-	guint16	 id;
-	guint32	 val;
-	gpointer complex_val;
-} MSEscherSpOPT;
-
-struct _MSEscherSp {
-	GArray	*opts;
-	int	 opt_size;
-	guint8	 anchor[9 * 2];
-};
+void
+ms_escher_set_inst (GString *buf, gsize marker, guint inst)
+{
+	guint16 iv = GSF_LE_GET_GUINT16 (buf->str + marker);
+	GSF_LE_SET_GUINT16 (buf->str + marker,
+			    (iv & 15) | (inst << 4));
+}
 
-MSEscherSp *
-ms_escher_sp_new (void)
+gsize
+ms_escher_spcontainer_start (GString *buf)
 {
-	MSEscherSp *sp = g_new0 (MSEscherSp, 1);
-	sp->opts    = g_array_new (FALSE, FALSE, sizeof (MSEscherSpOPT));
-	return sp;
+	gsize res = buf->len;
+	guint8 tmp[8] = { 0xf, 0, 4, 0xf0, 0xde, 0xad, 0xbe, 0xef };
+	g_string_append_len (buf, tmp, sizeof tmp);
+	return res;
 }
 
 void
-ms_escher_sp_free (MSEscherSp *sp)
+ms_escher_spcontainer_end (GString *buf, gsize marker)
 {
-	g_array_free (sp->opts, TRUE);
-	g_free (sp);
+	/* Length includes header.  */
+	gsize len = buf->len - marker;
+	GSF_LE_SET_GUINT32 (buf->str + marker + 4, len);
 }
 
-unsigned int
-ms_escher_sp_len (MSEscherSp const *sp)
+void
+ms_escher_sp (GString *buf, guint32 spid, guint32 flags)
 {
-	return sizeof Sp_header + sp->opt_size + sizeof Sp_footer;
+	guint8 tmp[16] = {
+		0xa2,  0xc, 0xa, 0xf0, 0xde, 0xad, 0xbe, 0xef,
+		0, 0, 0, 0, 0, 0, 0, 0
+	};
+	GSF_LE_SET_GUINT32 (tmp + 4, sizeof (tmp) - 8);
+	GSF_LE_SET_GUINT32 (tmp + 8, spid);
+	GSF_LE_SET_GUINT32 (tmp + 12, flags);
+	g_string_append_len (buf, tmp, sizeof tmp);
 }
 
-void
-ms_escher_sp_add_OPT (MSEscherSp *sp, guint16 id, guint32 val,
-		      gpointer complex_val)
+gsize
+ms_escher_opt_start (GString *buf)
 {
-	MSEscherSpOPT opt = { id, val, complex_val };
-	g_array_append_val (sp->opts, opt);
+	gsize res = buf->len;
+	guint8 tmp[8] = { 0x03,   0, 0xb, 0xf0, 0xde, 0xad, 0xbe, 0xef };
+	g_string_append_len (buf, tmp, sizeof tmp);
+	return res;
 }
 
-#include <sheet-object.h>
 void
-ms_escher_sp_set_anchor (MSEscherSp *sp,
-			 SheetObjectAnchor const *anchor,
-			 guint16 anchor_flags)
+ms_escher_opt_end (GString *buf, gsize marker)
 {
-	GSF_LE_SET_GUINT16 (sp->anchor +  0, anchor_flags);
-	GSF_LE_SET_GUINT16 (sp->anchor +  2, anchor->cell_bound.start.col);
-	GSF_LE_SET_GUINT16 (sp->anchor +  4, (guint16)(anchor->offset[0]*1024. + .5));
-	GSF_LE_SET_GUINT16 (sp->anchor +  6, anchor->cell_bound.start.row);
-	GSF_LE_SET_GUINT16 (sp->anchor +  8, (guint16)(anchor->offset[1]*256. + .5));
-	GSF_LE_SET_GUINT16 (sp->anchor + 10, anchor->cell_bound.end.col);
-	GSF_LE_SET_GUINT16 (sp->anchor + 12, (guint16)(anchor->offset[2]*1024. + .5));
-	GSF_LE_SET_GUINT16 (sp->anchor + 14, anchor->cell_bound.end.row);
-	GSF_LE_SET_GUINT16 (sp->anchor + 16, (guint16)(anchor->offset[3]*256. + .5));
+	/* Length does not include header.  */
+	gsize len = buf->len - marker - 8;
+	GSF_LE_SET_GUINT32 (buf->str + marker + 4, len);
 }
 
 void
-ms_escher_sp_write (MSEscherSp *sp, BiffPut *bp,
-		    guint16 shape, guint32 spid)
+ms_escher_opt_add_simple (GString *buf, gsize marker, guint16 pid, gint32 val)
 {
-	guint8 buf[sizeof Sp_header + sizeof Sp_footer];
-	MSEscherSpOPT const *opt;
-	guint32 len;
-	unsigned int i;
-
-	len = ms_escher_sp_len (sp);
-	memcpy (buf, Sp_header, sizeof Sp_header);
-/* SpContainer */
-	/* 0xf,   0,					 * ver = f, inst = 0 */
-	/* 0x04, 0xf0,					 * type = SpContainer */
-	GSF_LE_SET_GUINT32 (buf + 4, len);		/* total len */
-/* Sp */
-	GSF_LE_SET_GUINT16 (buf + 8, (shape << 4) | 2);
-	/* 0x0a, 0xf0,					 * type = Sp */
-	/* 8, 0, 0, 0,					 * len = 8 */
-	GSF_LE_SET_GUINT32 (buf + 16, spid);		/* store spid */
-	/* 0, 0xa, 0, 0,				   */
-
-/* OPT */
-	GSF_LE_SET_GUINT16 (buf + 20, (sp->opts->len << 4) | 3);
-	/* 0x0b, 0xf0,					 * type = OPT */
-	GSF_LE_SET_GUINT32 (buf + 24, sp->opt_size);
-	ms_biff_put_var_write (bp, buf, sizeof Sp_header);
-
-	/* write the basic values */
-	for (i = 0 ; i < sp->opts->len ; i++) {
-		opt = &g_array_index (sp->opts, MSEscherSpOPT, i);
-		GSF_LE_SET_GUINT16 (buf + 0, opt->id);
-		GSF_LE_SET_GUINT32 (buf + 2, opt->val);
-		ms_biff_put_var_write (bp, buf, 6);
-	}
+	guint8 tmp[6];
 
-	/* write the complex content */
-	for (i = 0 ; i < sp->opts->len ; i++) {
-		opt = &g_array_index (sp->opts, MSEscherSpOPT, i);
-		if (opt->complex_val != NULL)
-			ms_biff_put_var_write (bp, opt->complex_val, opt->val);
-	}
+	GSF_LE_SET_GUINT16 (tmp, pid);
+	GSF_LE_SET_GINT32 (tmp + 2, val);
+	g_string_append_len (buf, tmp, sizeof tmp);
+
+	ms_escher_set_inst (buf, marker,
+			    ms_escher_get_inst (buf, marker) + 1);
+}
 
-	memcpy (buf, Sp_footer, sizeof Sp_footer);
-/* ClientAnchor */
-	/* 0, 0,	 * ver = inst = 0 */
-	/* 0x10, 0xf0,	 * type = ClientAnchor */
-	/* 0x12, 0, 0, 0 * len = 0x12 */
-	memcpy (buf+8, sp->anchor, 9*2);
-
-/* ClientData */
-	/* 0, 0,	 * ver = inst = 0 */
-	/* 0x11, 0xf0,	 * type = ClientAnchor */
-	/* 0, 0, 0, 0 */
-	ms_biff_put_var_write (bp, buf, sizeof Sp_footer);
+void
+ms_escher_clientanchor (GString *buf, SheetObjectAnchor const *anchor)
+{
+	guint8 tmp[26] = {
+		0, 0, 0x10, 0xf0, 0xde, 0xad, 0xbe, 0xef,
+		0, 0,
+		0,0, 0,0,
+		0,0, 0,0,
+		0,0, 0,0,
+		0,0, 0,0
+	};
+	guint8 *p = tmp + 10;
+	GSF_LE_SET_GUINT32 (tmp + 4, sizeof (tmp) - 8);
+
+	GSF_LE_SET_GUINT16 (p +  0, anchor->cell_bound.start.col);
+	GSF_LE_SET_GUINT16 (p +  2, (guint16)(anchor->offset[0]*1024. + .5));
+	GSF_LE_SET_GUINT16 (p +  4, anchor->cell_bound.start.row);
+	GSF_LE_SET_GUINT16 (p +  6, (guint16)(anchor->offset[1]*256. + .5));
+	GSF_LE_SET_GUINT16 (p +  8, anchor->cell_bound.end.col);
+	GSF_LE_SET_GUINT16 (p + 10, (guint16)(anchor->offset[2]*1024. + .5));
+	GSF_LE_SET_GUINT16 (p + 12, anchor->cell_bound.end.row);
+	GSF_LE_SET_GUINT16 (p + 14, (guint16)(anchor->offset[3]*256. + .5));
+	g_string_append_len (buf, tmp, sizeof tmp);
 }
 
+void
+ms_escher_clientdata (GString *buf, gpointer data, gsize len)
+{
+	guint8 tmp[8] = { 0, 0, 0x11, 0xf0, 0xde, 0xad, 0xbe, 0xef };
+	GSF_LE_SET_GUINT32 (tmp + 4, len);
+	g_string_append_len (buf, tmp, sizeof tmp);
+	if (len > 0)
+		g_string_append_len (buf, data, len);
+}
diff --git a/plugins/excel/ms-escher.h b/plugins/excel/ms-escher.h
index ecfaebf..c7d938f 100644
--- a/plugins/excel/ms-escher.h
+++ b/plugins/excel/ms-escher.h
@@ -15,6 +15,7 @@
 #include "ms-excel-read.h"
 #include "ms-container.h"
 #include "ms-obj.h"
+#include <sheet-object.h>
 
 struct _MSEscherBlip {
 	char const   *type;
@@ -30,16 +31,23 @@ void ms_escher_blip_free (MSEscherBlip *blip);
 
 /******************************************************/
 
-typedef struct _MSEscherSp MSEscherSp;
-MSEscherSp *ms_escher_sp_new        (void);
-void	    ms_escher_sp_free	    (MSEscherSp *sp);
-guint32	    ms_escher_sp_len        (MSEscherSp const *sp);
-void	    ms_escher_sp_add_OPT    (MSEscherSp *sp, guint16 id, guint32 val,
-				     gpointer complex_val);
-void	    ms_escher_sp_set_anchor (MSEscherSp *sp,
-				     SheetObjectAnchor const *anchor,
-				     guint16 anchor_flags);
-void	    ms_escher_sp_write      (MSEscherSp *sp, BiffPut *bp,
-				     guint16 shape, guint32 spid);
+guint ms_escher_get_inst (GString *buf, gsize marker);
+void ms_escher_set_inst (GString *buf, gsize marker, guint inst);
+
+gsize ms_escher_spcontainer_start (GString *buf);
+void ms_escher_spcontainer_end (GString *buf, gsize marker);
+
+void ms_escher_sp (GString *buf, guint32 spid, guint32 flags);
+
+gsize ms_escher_opt_start (GString *buf);
+void ms_escher_opt_add_simple (GString *buf, gsize marker,
+			       guint16 pid, gint32 val);
+void ms_escher_opt_end (GString *buf, gsize marker);
+
+void ms_escher_clientanchor (GString *buf, SheetObjectAnchor const *anchor);
+
+void ms_escher_clientdata (GString *buf, gpointer data, gsize len);
+
+/******************************************************/
 
 #endif /* GNM_MS_OFFICE_ESCHER_H */
diff --git a/plugins/excel/ms-excel-write.c b/plugins/excel/ms-excel-write.c
index d38c9d6..c40a624 100644
--- a/plugins/excel/ms-excel-write.c
+++ b/plugins/excel/ms-excel-write.c
@@ -34,6 +34,7 @@
 
 #include <sheet-filter-combo.h>
 #include <gnm-format.h>
+#include <gutils.h>
 #include <position.h>
 #include <style-color.h>
 #include <cell.h>
@@ -4214,36 +4215,16 @@ excel_write_ClientTextbox (ExcelWriteState *ewb, SheetObject *so)
 static void
 excel_write_textbox_v8 (ExcelWriteSheet *esheet, SheetObject *so)
 {
-	static guint8 const obj_v8[] = {
-/* SpContainer */   0xf,   0,   4, 0xf0,    0x6c, 0, 0, 0,
-/* Sp */	   0xa2,  0xc, 0xa, 0xf0,      8, 0, 0, 0,
-			0,   0, 0, 0,	/* fill in spid */
-			0, 0xa, 0, 0,
-
-/* OPT */	   0x73,   0, 0xb, 0xf0,   0x2a, 0, 0, 0,
-                        0x80,    0, 0xa0,    0, 0xc6, 0, /* Txid */
-                        0x85,    0,    1,    0,    0, 0, /* wrap_text_at_margin */
-
-                        0xbf,    0,    8,    0,  0xa, 0, /* fFitTextToShape */
-                        0x81,    1, 0x41,    0,    0, 8, /* fillColor */
-                        0xbf,    1,    0,    0,    1, 0, /* fNoFillHitTest */
-                        0xc0,    1, 0x40,    0,    0, 8, /* lineColor */
-                        0xbf,    3,    0,    0,    8, 0, /* fPrint */
-
-/* ClientAnchor */    0, 0, 0x10, 0xf0,   0x12, 0, 0, 0, 0,0,
-			0,0,  0,0,	0,0,  0,0,	0,0,  0,0,	0,0,  0,0,
-/* ClientData */      0, 0, 0x11, 0xf0,  0, 0, 0, 0
-	};
-
-	guint8 buf [sizeof obj_v8];
-
+	GString *escher = g_string_new (NULL);
 	ExcelWriteState *ewb = esheet->ewb;
 	BiffPut *bp = ewb->bp;
 	guint32 id = excel_write_start_drawing (esheet);
-	guint16 flags;
-	int type;
 	SheetObjectAnchor anchor;
 	SheetObjectAnchor const *real_anchor = sheet_object_get_anchor (so);
+	guint8 zero[4] = { 0, 0, 0, 0 };
+	gsize spmark, optmark;
+	guint16 flags;
+	int type;
 
 	if (IS_CELL_COMMENT (so)) {
 		static float const offset [4] = { .5, .5, .5, .5 };
@@ -4255,7 +4236,7 @@ excel_write_textbox_v8 (ExcelWriteSheet *esheet, SheetObject *so)
 		r.end.col = r.start.col + 2;
 		r.end.row = r.start.row + 4;
 		sheet_object_anchor_init (&anchor, &r, offset,
-			GOD_ANCHOR_DIR_DOWN_RIGHT);
+					  GOD_ANCHOR_DIR_DOWN_RIGHT);
 		type = 0x19;
 		flags = 0x4011; /* not autofilled */
 		g_hash_table_insert (esheet->commentshash,
@@ -4266,23 +4247,48 @@ excel_write_textbox_v8 (ExcelWriteSheet *esheet, SheetObject *so)
 		flags = 0x6011; /* autofilled */
 	}
 
-	memcpy (buf, obj_v8, sizeof obj_v8);
-	GSF_LE_SET_GUINT32 (buf + 16, id);
-	GSF_LE_SET_GUINT32 (buf + 4, sizeof obj_v8);
-	excel_write_anchor (buf + 0x54, &anchor);
-	ms_biff_put_var_write (bp, buf, sizeof obj_v8);
+	spmark = ms_escher_spcontainer_start (escher);
+
+	ms_escher_sp (escher, id, 0x00000a00);  /* fHaveAnchor+fHaveSpt */
+	
+	optmark = ms_escher_opt_start (escher);
+	ms_escher_opt_add_simple (escher, optmark,
+				  0x0080, 0x00c600a0); /* Txid */
+	ms_escher_opt_add_simple (escher, optmark,
+				  0x0085, 1); /* wrap_text_at_margin */
+	ms_escher_opt_add_simple (escher, optmark,
+				  0x00bf, 0x000a0008); /* wrap_text_at_margin */
+	ms_escher_opt_add_simple (escher, optmark,
+				  0x0181, 0x08000041); /* fillColor */
+	ms_escher_opt_add_simple (escher, optmark,
+				  0x01bf, 0x00010000); /* fNoFillHitTest */
+	ms_escher_opt_add_simple (escher, optmark,
+				  0x01c0, 0x08000040); /* lineColor */
+	ms_escher_opt_add_simple (escher, optmark,
+				  0x03bf, 0x00080000); /* fPrint */
+	ms_escher_opt_end (escher, optmark);
+
+	ms_escher_clientanchor (escher, &anchor);
+
+	ms_escher_clientdata (escher, NULL, 0);
+
+	ms_escher_spcontainer_end (escher, spmark);
+
+	ms_biff_put_var_write (bp, escher->str, escher->len);
+	gsf_mem_dump (escher->str, escher->len);
 	ms_biff_put_commit (bp);
 
+	g_string_free (escher, TRUE);
+
 	ms_biff_put_var_next (bp, BIFF_OBJ);
 	ms_objv8_write_common (bp, esheet->cur_obj, type, flags);
 	if (IS_CELL_COMMENT (so))
 		ms_objv8_write_note (bp);
-	GSF_LE_SET_GUINT32 (buf, 0); /* end */
-	ms_biff_put_var_write (bp, buf, 4);
+	ms_biff_put_var_write (bp, zero, 4);
 
 	ms_biff_put_commit (bp);
 
-	excel_write_ClientTextbox(ewb, so);
+	excel_write_ClientTextbox (ewb, so);
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]