[gnumeric] XLS: start cleaning up writing of objects.
- From: Morten Welinder <mortenw src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnumeric] XLS: start cleaning up writing of objects.
- Date: Sun, 4 Oct 2009 23:21:18 +0000 (UTC)
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]