Commit 0eed16d6 authored by Jody Goldberg's avatar Jody Goldberg Committed by Jody Goldberg

patch logic.

2007-03-04  Jody Goldberg <jody@gnome.org>

	* src/func-builtin.c (gnumeric_table) : patch logic.

2007-03-04  Jody Goldberg <jody@gnome.org>

	* src/parse-util.c (gnm_expr_conventions_new_full) : Start
	  homogenizing the structure so that parsing and formating use shared
	  gunichar, rather than a semi-random collection of booleans on
	  import and char * on export.
	  - ::name_parser renamed ::input.name
	  - ::unknown_function_handler replaced by ::input.func which is
	      called for all functions not just unknown.
	  - ::function_rewriter_hash deleted.  This was not 64bit clean
	  - ::output_sheet_name_sep => a gunichar and renamed ::sheet_name_sep.
	  - ::cell_ref_handler => ::output.cell_ref
	  - ::range_ref_handler => ::output.range_ref
	  - ::sheet_name_quote => ::output.sheet_name_quote

	(cellref_as_string) : ditto.
	(std_expr_name_handler) : ditto.
	(std_func_map) : new.

	* src/xml-sax-write.c (xml_io_conventions) : adapt to changes.
	* src/xml-io.c (xml_io_conventions) : ditto.
	* src/value.c (value_get_as_gstring) : ditto.
	* src/expr.c (do_expr_as_string) : ditto.

	* src/parser.y : s/SEPARATOR/ARG_SEP/
	Remove the ARRAY_START_COMMA and ARRAY_START_BSLASH tokens
	Remove the duplicate comma/bslash productions for arrays.
	Use an 'in_array' flag in the state to allow the lexer to
	differentiate an ARG_SEP from an ARRAY_COL_SEP and an ARRAY_ROW_SEP.

	* src/sheet-object-graph.c (gnm_sog_get_object_target_list) : compiler
	  warnings.

	* src/func.c (gnm_func_placeholder_factory) : delete.

2007-03-05  Jody Goldberg <jody@gnome.org>

	* xlsx-utils.c (xlsx_cellref_as_string) : no need to use the
	  convention for the sheet_sep, hard code it.
	(xlsx_rangeref_as_string) : ditto.
	(xlsx_expr_conv_new) : adapt to changes.

2007-01-11  Jody Goldberg <jody@gnome.org>

	* ms-escher.c (ms_escher_read_OPT_bools) : improve debug stream.
	(ms_escher_read_OPT) : add a few more properties based on the results
	  of the test file that fills in as many properties as I could find
	  samples/excel/objs.xls.
	(ms_escher_sp_new) : new. unused as yet.
	(ms_escher_sp_free) : ditto.
	(ms_escher_sp_len) : ditto.
	(ms_escher_sp_add_OPT) : ditto.
	(ms_escher_sp_set_anchor) : ditto.
	(ms_escher_sp_write) : ditto.

	* ms-obj.c (ms_obj_read_biff8_obj) : do not generate a warning for
	  combos with no link, or the special autofilter combos.
	(ms_obj_read_biff8_obj) : include the id in the debug spew.
	(ms_obj_read_biff8_obj) : Do not warn about unknown flags that we know
	  are unknown :-)
	(ms_objv8_write_note) : new basic stub.

	* ms-excel-write.c (excel_write_textbox_v8) : cheap hack to handle
	  comments somewhat at an invented anchor.
	(cb_NOTE_v8) : new.
	(excel_write_objs_v8) : keep track of the number of comments too.
	(excel_sheet_new) : count comments too.  General tidyup in prep for
	  moving to generated escher.

2007-03-05  Jody Goldberg <jody@gnome.org>

	* sc.c (sc_func_map_in) : adapt to change in ExprConv

2007-03-04  Jody Goldberg <jody@gnome.org>

	* openoffice-read.c (odf_func_map_in) : adapt to the new mechanism of
	  function renaming.
	(oo_conventions) : handle inline arrays.

2007-03-04  Jody Goldberg <jody@gnome.org>

	* oleo.c (oleo_conventions) : adapt to new conventions.

svn path=/trunk/; revision=15444
parent a6917af5
2007-03-04 Jody Goldberg <jody@gnome.org>
* src/func-builtin.c (gnumeric_table) : patch logic.
2007-03-04 Jody Goldberg <jody@gnome.org>
* src/parse-util.c (gnm_expr_conventions_new_full) : Start
homogenizing the structure so that parsing and formating use shared
gunichar, rather than a semi-random collection of booleans on
import and char * on export.
- ::name_parser renamed ::input.name
- ::unknown_function_handler replaced by ::input.func which is
called for all functions not just unknown.
- ::function_rewriter_hash deleted. This was not 64bit clean
- ::output_sheet_name_sep => a gunichar and renamed ::sheet_name_sep.
- ::cell_ref_handler => ::output.cell_ref
- ::range_ref_handler => ::output.range_ref
- ::sheet_name_quote => ::output.sheet_name_quote
(cellref_as_string) : ditto.
(std_expr_name_handler) : ditto.
(std_func_map) : new.
* src/xml-sax-write.c (xml_io_conventions) : adapt to changes.
* src/xml-io.c (xml_io_conventions) : ditto.
* src/value.c (value_get_as_gstring) : ditto.
* src/expr.c (do_expr_as_string) : ditto.
* src/parser.y : s/SEPARATOR/ARG_SEP/
Remove the ARRAY_START_COMMA and ARRAY_START_BSLASH tokens
Remove the duplicate comma/bslash productions for arrays.
Use an 'in_array' flag in the state to allow the lexer to
differentiate an ARG_SEP from an ARRAY_COL_SEP and an ARRAY_ROW_SEP.
* src/sheet-object-graph.c (gnm_sog_get_object_target_list) : compiler
warnings.
* src/func.c (gnm_func_placeholder_factory) : delete.
2007-03-04 Morten Welinder <terra@gnome.org>
* configure.in: Post-release bump.
......
Gnumeric 1.7.9
Jody:
* Import and Export for inline arrays in ODF. (now patched in OOo)
* Export cell comments to xls.
--------------------------------------------------------------------------
Gnumeric 1.7.8
......@@ -22,6 +26,8 @@ Jody:
* Fix AutoFormat loading.
* Add support for the standard builtin formats in xlsx.
* Fix col/row grouping deletion. [#388505]
* Basic ODF AutoFilter partial import/export.
* Some property dialogs for combos and lists.
Morten:
* Unify layout and string value formatting.
......
2007-03-04 Jody Goldberg <jody@gnome.org>
* applix-read.c (applix_func_map_in) : Adapt to the new func_map
approach to renaming.
2007-03-04 Morten Welinder <terra@gnome.org>
* Release 1.7.8
......
......@@ -55,6 +55,7 @@
#include <goffice/app/io-context.h>
#include <goffice/app/error-info.h>
#include <goffice/utils/go-glib-extras.h>
#include <gsf/gsf-input-textline.h>
#include <string.h>
#include <stdlib.h>
......@@ -1544,57 +1545,55 @@ cb_remove_style (gpointer key, gpointer value, gpointer user_data)
return TRUE;
}
static struct {
char const *applixname;
char const *gnumericname;
} const simple_renames[] = {
static GnmExpr const *
applix_func_map_in (GnmExprConventions const *conv, Workbook *scope,
char const *name, GnmExprList *args)
{
static struct {
char const *applix_name;
char const *gnm_name;
} const sc_func_renames[] = {
{ "IPAYMT", "IPMT" },
{ "PAYMT", "PMT" },
{ "PPAYMT", "PPMT" },
{ NULL, NULL }
};
};
static GHashTable *namemap = NULL;
static GnmExpr const *
function_renamer (char const *name,
GnmExprList *args,
GnmExprConventions *convs)
{
Workbook *wb = NULL;
int i;
GnmFunc *f;
char const *new_name;
int i;
for (i = 0; simple_renames[i].applixname; i++)
if (strcmp (name, simple_renames[i].applixname) == 0) {
name = simple_renames[i].gnumericname;
break;
if (NULL == namemap) {
namemap = g_hash_table_new (go_ascii_strcase_hash,
go_ascii_strcase_equal);
for (i = 0; sc_func_renames[i].applix_name; i++)
g_hash_table_insert (namemap,
(gchar *) sc_func_renames[i].applix_name,
(gchar *) sc_func_renames[i].gnm_name);
}
f = gnm_func_lookup (name, wb);
if (f)
if (NULL != namemap &&
NULL != (new_name = g_hash_table_lookup (namemap, name)))
name = new_name;
if (NULL == (f = gnm_func_lookup (name, scope)))
f = gnm_func_add_placeholder (scope, name, "", TRUE);
return gnm_expr_new_funcall (f, args);
return gnm_func_placeholder_factory (name, args, convs);
}
static GnmExprConventions *
applix_conventions (void)
{
GnmExprConventions *res = gnm_expr_conventions_new ();
res->intersection_char = 0;
res->accept_hash_logicals = TRUE;
res->allow_absolute_sheet_references = TRUE;
res->range_sep_dotdot = TRUE;
res->unknown_function_handler = gnm_func_placeholder_factory;
res->ref_parser = applix_rangeref_parse;
res->function_rewriter_hash =
g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_insert (res->function_rewriter_hash,
(gchar *)"IPAYMT",
function_renamer);
return res;
GnmExprConventions *conv = gnm_expr_conventions_new ();
conv->intersection_char = 0;
conv->accept_hash_logicals = TRUE;
conv->allow_absolute_sheet_references = TRUE;
conv->range_sep_dotdot = TRUE;
conv->input.range_ref = applix_rangeref_parse;
conv->input.func = applix_func_map_in;
return conv;
}
void
......
2007-03-05 Jody Goldberg <jody@gnome.org>
* xlsx-utils.c (xlsx_cellref_as_string) : no need to use the
convention for the sheet_sep, hard code it.
(xlsx_rangeref_as_string) : ditto.
(xlsx_expr_conv_new) : adapt to changes.
2007-01-11 Jody Goldberg <jody@gnome.org>
* ms-escher.c (ms_escher_read_OPT_bools) : improve debug stream.
(ms_escher_read_OPT) : add a few more properties based on the results
of the test file that fills in as many properties as I could find
samples/excel/objs.xls.
(ms_escher_sp_new) : new. unused as yet.
(ms_escher_sp_free) : ditto.
(ms_escher_sp_len) : ditto.
(ms_escher_sp_add_OPT) : ditto.
(ms_escher_sp_set_anchor) : ditto.
(ms_escher_sp_write) : ditto.
* ms-obj.c (ms_obj_read_biff8_obj) : do not generate a warning for
combos with no link, or the special autofilter combos.
(ms_obj_read_biff8_obj) : include the id in the debug spew.
(ms_obj_read_biff8_obj) : Do not warn about unknown flags that we know
are unknown :-)
(ms_objv8_write_note) : new basic stub.
* ms-excel-write.c (excel_write_textbox_v8) : cheap hack to handle
comments somewhat at an invented anchor.
(cb_NOTE_v8) : new.
(excel_write_objs_v8) : keep track of the number of comments too.
(excel_sheet_new) : count comments too. General tidyup in prep for
moving to generated escher.
2007-03-04 Morten Welinder <terra@gnome.org>
* Release 1.7.8
......
......@@ -1259,22 +1259,26 @@ ms_escher_read_OPT_bools (MSEscherHeader *h,
g_return_if_fail (n_bools > 0);
g_return_if_fail (bools[n_bools-1].pid == pid);
d (2, printf ("BOOLS %s(%d) = 0x%08x;\n",
d (2, printf ("Set of Bools %s(%d) = 0x%08x;\n{\n",
bools[n_bools-1].name, bools[n_bools-1].pid, val););
for (; i-- > 0 ; mask <<= 1, bit <<= 1) {
if (!(val & mask)) /* the value is set */
continue;
/* If the value is not the default, and we give a damn */
if ((((val & bit) == bit) ^ bools[i].default_val) && bools[i].id != 0) {
/* If the value is not the default */
if ((((val & bit) == bit) ^ bools[i].default_val)) {
d (0, printf ("bool %s = %s; /* gnm attr id = %d */\n",
bools[i].name,
/* only exported if they != default_val */
bools[i].default_val ? "false" : "true",
bools[i].id););
if (bools[i].id != 0)
ms_escher_header_add_attr (h,
ms_obj_attr_new_flag (bools[i].id));
d (0, printf ("bool %s(%d) ==%s;\n",
bools[i].name, bools[i].id,
/* only exported if they != default_val */
bools[i].default_val ? "false" : "true"););
}
}
d (2, printf ("};\n"););
}
static gboolean
......@@ -1843,7 +1847,10 @@ ms_escher_read_OPT (MSEscherState *state, MSEscherHeader *h)
name = "wchar* wzName";
break;
/* NULL : alternate text */
case 897 : name = "wchar* wzDescription"; break;
case 897 : id = MS_OBJ_ATTR_OBJ_ALT_TEXT;
name = "wchar* wzDescription";
break;
/* NULL : The hyperlink in the shape. */
case 898 : name = "IHlink* pihlShape"; break;
/* NULL : The polygon that text will be wrapped around (Word) */
......@@ -1866,12 +1873,15 @@ ms_escher_read_OPT (MSEscherState *state, MSEscherHeader *h)
pid, val);
break;
default : name = "";
default : name = "UnknownID";
}
d (0, printf ("%s %d = 0x%08x (=%d) %s%s;\n", name, pid, val, val,
d (0, {
if (NULL != name)
printf ("%s %d = 0x%08x (=%d) %s%s;\n", name, pid, val, val,
is_blip ? " is blip" : "",
is_complex ? " is complex" : ""););
is_complex ? " is complex" : "");
});
/* TODO : use this for something */
if (is_complex) {
......@@ -1879,7 +1889,7 @@ ms_escher_read_OPT (MSEscherState *state, MSEscherHeader *h)
g_return_val_if_fail (extra + val - data + COMMON_HEADER_LEN <= h->len, TRUE);
d (5, gsf_mem_dump (extra, val););
d (7, {
d (11, {
static int count = 0;
char *name = g_strdup_printf ("gnumeric-complex-opt-[%d]-%d", pid, count++);
FILE *f = g_fopen (name, "w");
......@@ -2154,3 +2164,154 @@ ms_escher_parse (BiffQuery *q, MSContainer *container, gboolean return_attrs)
ms_escher_header_release (&fake_header);
return res;
}
/*********************************************************************/
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
};
typedef struct {
guint16 id;
guint32 val;
gpointer complex_val;
} MSEscherSpOPT;
struct _MSEscherSp {
GArray *opts;
int opt_size;
guint8 anchor[9 * 2];
};
MSEscherSp *
ms_escher_sp_new (void)
{
MSEscherSp *sp = g_new0 (MSEscherSp, 1);
sp->opts = g_array_new (FALSE, FALSE, sizeof (MSEscherSpOPT));
return sp;
}
void
ms_escher_sp_free (MSEscherSp *sp)
{
g_array_free (sp->opts, TRUE);
g_free (sp);
}
unsigned int
ms_escher_sp_len (MSEscherSp const *sp)
{
return sizeof Sp_header + sp->opt_size + sizeof Sp_footer;
}
void
ms_escher_sp_add_OPT (MSEscherSp *sp, guint16 id, guint32 val,
gpointer complex_val)
{
MSEscherSpOPT opt = { id, val, complex_val };
g_array_append_val (sp->opts, opt);
}
#include <sheet-object.h>
void
ms_escher_sp_set_anchor (MSEscherSp *sp,
SheetObjectAnchor const *anchor,
guint16 anchor_flags)
{
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));
}
void
ms_escher_sp_write (MSEscherSp *sp, BiffPut *bp,
guint16 shape, guint32 spid)
{
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);
}
/* 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);
}
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);
}
......@@ -28,10 +28,18 @@ MSObjAttrBag *ms_escher_parse (BiffQuery *q, MSContainer *container,
void ms_escher_blip_free (MSEscherBlip *blip);
#if 0
typedef struct _MSEscherWriter MSEscherWriter;
MSEscherWriter *ms_escher_writer_new (BiffPut *bp);
void ms_escher_writer_commit (MSEscherWriter *ew);
#endif
/******************************************************/
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);
#endif /* GNM_MS_OFFICE_ESCHER_H */
......@@ -328,7 +328,11 @@ ms_sheet_obj_anchor_to_pos (Sheet const * sheet, MsBiffVersion const ver,
*/
int i;
d (0, fprintf (stderr,"%s\n", sheet->name_unquoted););
d (0,
{
fprintf (stderr,"anchored to %s\n", sheet->name_unquoted);
gsf_mem_dump (raw_anchor, 18);
});
/* Ignore the first 2 bytes. What are they ? */
/* Dec/1/2000 JEG: I have not researched it, but this may have some
......
......@@ -7,7 +7,7 @@
* Jon K Hellan (hellan@acm.org)
* Jody Goldberg (jody@gnome.org)
*
* (C) 1998-2005 Michael Meeks, Jon K Hellan, Jody Goldberg
* (C) 1998-2006 Michael Meeks, Jon K Hellan, Jody Goldberg
**/
/*
......@@ -3671,20 +3671,21 @@ excel_write_autofilter_objs (ExcelWriteSheet *esheet)
};
static guint8 const obj_v8[] = {
/* SpContainer */ 0x0f, 0, 4, 0xf0, 0x52, 0, 0, 0,
/* SpContainer */ 0xf, 0, 4, 0xf0, 0x52, 0, 0, 0,
/* Sp */ 0x92, 0xc, 0xa, 0xf0, 8, 0, 0, 0,
0, 0, 0, 0, /* fill in spid */
0, 0xa, 0, 0,
/* OPT */ 0x43, 0, 0xb, 0xf0, 0x18, 0, 0, 0,
0x7f, 0, 4, 1, 4, 1, /* bool LockAgainstGrouping 127 = 0x1040104; */
0xbf, 0, 8, 0, 8, 0, /* bool fFitTextToShape 191 = 0x80008; */
0xff, 1, 0, 0, 8, 0, /* bool fNoLineDrawDash 511 = 0x80000; */
0xbf, 3, 0, 0, 2, 0, /* bool fPrint 959 = 0x20000; */
/* ClientAnchor */ 0, 0, 0x10, 0xf0, 0x12, 0, 0, 0, 1,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
};
static float offsets[] = { 0., 0., 0., 0. };
guint8 *data, buf [sizeof obj_v8];
GnmFilter const *filter;
......@@ -3704,7 +3705,7 @@ excel_write_autofilter_objs (ExcelWriteSheet *esheet)
cond = gnm_filter_get_condition (filter, i);
r.end.col = 1 + (r.start.col = filter->r.start.col + i);
sheet_object_anchor_init (&anchor, &r, offsets,
sheet_object_anchor_init (&anchor, &r, NULL,
GOD_ANCHOR_DIR_DOWN_RIGHT);
if (bp->version >= MS_BIFF_V8) {
guint32 id = excel_write_start_drawing (esheet);
......@@ -3745,6 +3746,7 @@ excel_write_chart_v8 (ExcelWriteSheet *esheet, SheetObject *so)
/* Sp */ 0x92, 0xc, 0xa, 0xf0, 8, 0, 0, 0,
0, 0, 0, 0, /* fill in spid */
0, 0xa, 0, 0,
/* OPT */ 0x83, 0, 0xb, 0xf0, 0x30, 0, 0, 0,
0x7f, 0, 4, 1, 4, 1, /* bool LockAgainstGrouping 127 = 0x1040104; */
0xbf, 0, 8, 0, 8, 0, /* bool fFitTextToShape 191 = 0x0080008; */
......@@ -3754,6 +3756,7 @@ excel_write_chart_v8 (ExcelWriteSheet *esheet, SheetObject *so)
0xc0, 1, 0x4d, 0, 0, 8, /* Colour lineColor 448 = 0x800004d; */
0xff, 1, 8, 0, 8, 0, /* bool fNoLineDrawDash 511 = 0x0080008; */
0x3f, 2, 0, 0, 2, 0, /* bool fshadowObscured 575 = 0x0020000; */
/* 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
......@@ -3882,10 +3885,12 @@ excel_write_image_v8 (ExcelWriteSheet *esheet, BlipInf *bi)
/* Sp */ 0xb2, 4, 0xa, 0xf0, 8, 0, 0, 0,
0, 0, 0, 0, /* fill in spid */
0, 0xa, 0, 0,
/* OPT */ 0x33, 0, 0xb, 0xf0, 0x12, 0, 0, 0,
0x7f, 0, 0x80, 0, 0x80, 0, /* bool LockAgainstGrouping 127 = 0x800080; */
4, 0x41, 1, 0, 0, 0, /* blip x is blip (fill in); */
0x80, 1, 3, 0, 0, 0, /* FillType fillType 384 = 0x3; */
/* 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
......@@ -3988,6 +3993,7 @@ excel_write_textbox_v8 (ExcelWriteSheet *esheet, SheetObject *so)
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
......@@ -3998,16 +4004,44 @@ excel_write_textbox_v8 (ExcelWriteSheet *esheet, SheetObject *so)
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);
if (IS_CELL_COMMENT (so)) {
static float const offset [4] = { .5, .5, .5, .5 };
GnmRange r;
r.start = real_anchor->cell_bound.start;
r.start.col++;
r.start.row--;
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);
type = 0x19;
flags = 0x4011; /* not autofilled */
if (NULL == esheet->comments)
esheet->comments = g_hash_table_new (g_direct_hash, g_direct_equal);
g_hash_table_insert (esheet->comments, so, GINT_TO_POINTER (esheet->cur_obj));
} else {
anchor = *real_anchor;
type = 6;
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, sheet_object_get_anchor (so));
excel_write_anchor (buf + 0x54, &anchor);
ms_biff_put_var_write (bp, buf, sizeof obj_v8);
ms_biff_put_commit (bp);
ms_biff_put_var_next (bp, BIFF_OBJ);
ms_objv8_write_common (bp, esheet->cur_obj, 6, 0x6011);
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);
......@@ -4458,6 +4492,25 @@ excel_write_CODENAME (ExcelWriteState *ewb, GObject *src)
}
}
static void
cb_NOTE_v8 (SheetObject const *so, gconstpointer id, BiffPut *bp)
{
SheetObjectAnchor const *anchor = sheet_object_get_anchor (so);
char const *author = cell_comment_author_get (CELL_COMMENT (so));
guint8 buf [4 * 2];
ms_biff_put_var_next (bp, BIFF_NOTE);
GSF_LE_SET_GUINT16 (buf + 0, anchor->cell_bound.start.row);
GSF_LE_SET_GUINT16 (buf + 2, anchor->cell_bound.start.col);
GSF_LE_SET_GUINT16 (buf + 4, 0);
GSF_LE_SET_GUINT16 (buf + 6, GPOINTER_TO_INT (id));
ms_biff_put_var_write (bp, buf, sizeof buf);
excel_write_string (bp, STR_TWO_BYTE_LENGTH, author);
GSF_LE_SET_GUINT8 (buf, 0);
ms_biff_put_var_write (bp, buf, 1); /* XL adds a trailing 0 */
ms_biff_put_commit (bp);
}
static void
excel_write_objs_v8 (ExcelWriteSheet *esheet)
{
......@@ -4483,6 +4536,7 @@ excel_write_objs_v8 (ExcelWriteSheet *esheet)
guint8 buf [sizeof header_obj_v8];
unsigned last_id, num_filters = 0;
unsigned num_charts = g_slist_length (charts);
unsigned num_blips = g_slist_length (esheet->blips);
unsigned num_texts = g_slist_length (esheet->textboxes);
if (esheet->gnum_sheet->filters != NULL) {
......@@ -4499,7 +4553,9 @@ excel_write_objs_v8 (ExcelWriteSheet *esheet)
ms_biff_put_var_next (bp, BIFF_MS_O_DRAWING);
memcpy (buf, header_obj_v8, sizeof header_obj_v8);
len = 90*num_filters + 114*num_charts+ 84*esheet->num_blips;
len = 90*num_filters;
len += 114*num_charts;
len += 84*num_blips;
len += 116*num_texts;
GSF_LE_SET_GUINT32 (buf + 4, 72 + len);
GSF_LE_SET_GUINT32 (buf + 16, esheet->num_objs + 1);
......@@ -4514,13 +4570,18 @@ excel_write_objs_v8 (ExcelWriteSheet *esheet)
g_slist_free (charts);
for (ptr = esheet->blips; ptr != NULL ; ptr = ptr->next)
if (ptr->data)
excel_write_image_v8 (esheet, ptr->data);
for (ptr = esheet->textboxes; ptr != NULL ; ptr = ptr->next)
excel_write_textbox_v8 (esheet, ptr->data);
excel_write_autofilter_objs (esheet);
if (NULL != esheet->comments) {
g_hash_table_foreach (esheet->comments,
(GHFunc) cb_NOTE_v8, bp);
g_hash_table_destroy (esheet->comments);
}
}
static void
......@@ -4658,32 +4719,34 @@ excel_sheet_new (ExcelWriteState *ewb, Sheet *sheet,
esheet->max_row = maxrows;
/* we only export charts & images for now */
esheet->cur_obj = esheet->num_objs = esheet->num_blips = 0;
esheet->blips = NULL;
esheet->cur_obj = esheet->num_objs = 0;
objs = sheet_objects_get (sheet, NULL, SHEET_OBJECT_GRAPH_TYPE);
esheet->num_objs += g_slist_length (objs);
g_slist_free (objs);
esheet->blips = NULL;
objs = sheet_objects_get (sheet, NULL, SHEET_OBJECT_IMAGE_TYPE);
for (img = objs ; img != NULL ; img = img->next) {
SheetObjectImage *soi = SHEET_OBJECT_IMAGE (img->data);
BlipInf *bi = blipinf_new (soi);
/* Images we can't export have a NULL BlipInf */
if (bi)
esheet->num_blips++;
if (NULL!= bi)
esheet->blips = g_slist_prepend (esheet->blips, bi);
}
esheet->blips = g_slist_reverse (esheet->blips);
esheet->num_objs += esheet->num_blips;
/* Text boxes */
esheet->textboxes = sheet_objects_get (sheet, NULL, GNM_SO_FILLED_TYPE);
#warning TODO TODO FIXME FIXME FIXME : filter for boxes with text
esheet->num_objs += g_slist_length (objs);
esheet->num_objs += g_slist_length (esheet->blips);
g_slist_free (objs);
/* And the autofilters */
/* Text boxes & comments */
objs = sheet_objects_get (sheet, NULL, CELL_COMMENT_TYPE);
esheet->textboxes = g_slist_concat (objs,
sheet_objects_get (sheet, NULL, GNM_SO_FILLED_TYPE));
esheet->comments = NULL; /* gets populated with obj_ids later */
esheet->num_objs += g_slist_length (esheet->textboxes);
/* And the autofilters (only 1 per sheet in XL) */
if (sheet->filters != NULL) {
GnmFilter const *filter = sheet->filters->data;
esheet->num_objs += filter->fields->len;