[gnumeric] oo_expr_rangeref_parse should also consider possible external workbooks
- From: Andreas J. Guelzow <guelzow src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] oo_expr_rangeref_parse should also consider possible external workbooks
- Date: Fri, 27 May 2011 19:09:50 +0000 (UTC)
commit 9bd752a56f577b4a5794140702f896d1ed9ba2c7
Author: Andreas J Guelzow <aguelzow pyrshep ca>
Date: Fri May 27 13:08:09 2011 -0600
oo_expr_rangeref_parse should also consider possible external workbooks
2011-05-27 Andreas J. Guelzow <aguelzow pyrshep ca>
* openoffice-read.c (oo_cellref_parse): add argument, change
all callers, don't create sheets that are in foreign workbooks
(odf_parse_external): new
(oo_rangeref_parse): add argument, change all callers, consider
foreign workbooks
(oo_conventions_new): add arguments and create augmented conventions
(oo_load_convention): add argument, change all callers
(oo_col_start): use oo_warning rather than g_warning
(odf_clear_conventions): new, use whenever xin changes
(opendoc_content_dtd): add table:table-source
plugins/openoffice/ChangeLog | 13 +++
plugins/openoffice/openoffice-read.c | 184 +++++++++++++++++++++++++--------
2 files changed, 152 insertions(+), 45 deletions(-)
---
diff --git a/plugins/openoffice/ChangeLog b/plugins/openoffice/ChangeLog
index 7d59d6e..365f709 100644
--- a/plugins/openoffice/ChangeLog
+++ b/plugins/openoffice/ChangeLog
@@ -1,3 +1,16 @@
+2011-05-27 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * openoffice-read.c (oo_cellref_parse): add argument, change
+ all callers, don't create sheets that are in foreign workbooks
+ (odf_parse_external): new
+ (oo_rangeref_parse): add argument, change all callers, consider
+ foreign workbooks
+ (oo_conventions_new): add arguments and create augmented conventions
+ (oo_load_convention): add argument, change all callers
+ (oo_col_start): use oo_warning rather than g_warning
+ (odf_clear_conventions): new, use whenever xin changes
+ (opendoc_content_dtd): add table:table-source
+
2011-05-22 Morten Welinder <terra gnome org>
* openoffice-write.c (odf_write_ooo_settings): Plug leak.
diff --git a/plugins/openoffice/openoffice-read.c b/plugins/openoffice/openoffice-read.c
index f4f2692..acb7340 100644
--- a/plugins/openoffice/openoffice-read.c
+++ b/plugins/openoffice/openoffice-read.c
@@ -372,6 +372,12 @@ typedef struct {
} OOParseState;
typedef struct {
+ GnmConventions base;
+ OOParseState *state;
+ GsfXMLIn *xin;
+} ODFConventions;
+
+typedef struct {
GOColor from;
GOColor to;
gnm_float brightness;
@@ -384,6 +390,9 @@ static GsfXMLInNode const * get_dtd (void);
static GsfXMLInNode const * get_styles_dtd (void);
static void oo_chart_style_free (OOChartStyle *pointer);
static OOFormula odf_get_formula_type (GsfXMLIn *xin, char const **str);
+static char const *odf_strunescape (char const *string, GString *target,
+ G_GNUC_UNUSED GnmConventions const *convs);
+
/* Implementations */
static void
@@ -1068,7 +1077,8 @@ oo_cellref_check_for_err (GnmCellRef *ref, char const **start)
}
static char const *
-oo_cellref_parse (GnmCellRef *ref, char const *start, GnmParsePos const *pp)
+oo_cellref_parse (GnmCellRef *ref, char const *start, GnmParsePos const *pp,
+ gchar **foreign_sheet)
{
char const *tmp, *ptr = start;
GnmSheetSize const *ss;
@@ -1120,18 +1130,24 @@ two_quotes :
if (name[0] == 0)
return start;
- /* OpenCalc does not pre-declare its sheets, but it does have a
- * nice unambiguous format. So if we find a name that has not
- * been added yet add it. Reorder below. */
- ref->sheet = workbook_sheet_by_name (pp->wb, name);
- if (ref->sheet == NULL) {
- if (strcmp (name, "#REF!") == 0) {
- ref->sheet = invalid_sheet;
- } else {
- /* We can't add it yet since this whole ref */
- /* may be invalid */
- new_sheet_name = g_strdup (name);
- ref->sheet = NULL;
+ if (foreign_sheet != NULL) {
+ /* This is a reference to a foreign workbook */
+ *foreign_sheet = g_strdup (name);
+ ref->sheet = NULL;
+ } else {
+ /* OpenCalc does not pre-declare its sheets, but it does have a
+ * nice unambiguous format. So if we find a name that has not
+ * been added yet add it. Reorder below. */
+ ref->sheet = workbook_sheet_by_name (pp->wb, name);
+ if (ref->sheet == NULL) {
+ if (strcmp (name, "#REF!") == 0) {
+ ref->sheet = invalid_sheet;
+ } else {
+ /* We can't add it yet since this whole ref */
+ /* may be invalid */
+ new_sheet_name = g_strdup (name);
+ ref->sheet = NULL;
+ }
}
}
} else {
@@ -1167,7 +1183,7 @@ two_quotes :
sheet = eval_sheet (ref->sheet, pp->sheet);
ss = gnm_sheet_get_size (sheet);
- if (ss->max_cols <= ref->col || ss->max_rows <= ref->row) {
+ if (foreign_sheet == NULL && (ss->max_cols <= ref->col || ss->max_rows <= ref->row)) {
int new_cols = ref->col + 1, new_rows = ref->row + 1;
GOUndo * goundo;
gboolean err;
@@ -1190,21 +1206,69 @@ two_quotes :
}
static char const *
-oo_rangeref_parse (GnmRangeRef *ref, char const *start, GnmParsePos const *pp)
+odf_parse_external (char const *start, gchar **external,
+ GnmConventions const *convs)
+{
+ char const *ptr;
+ GString *str;
+
+ /* Source ::= "'" IRI "'" "#" */
+ if (*start != '\'')
+ return start;
+ str = g_string_new (NULL);
+ ptr = odf_strunescape (start, str, convs);
+
+ if (ptr == NULL || *ptr != '#') {
+ g_string_free (str, TRUE);
+ return start;
+ }
+
+ *external = g_string_free (str, FALSE);
+ return (ptr + 1);
+}
+
+static char const *
+oo_rangeref_parse (GnmRangeRef *ref, char const *start, GnmParsePos const *pp,
+ GnmConventions const *convs)
{
- char const *ptr = oo_cellref_parse (&ref->a, start, pp);
+ char const *ptr;
+ char *external = NULL;
+ char *external_sheet_1 = NULL;
+ char *external_sheet_2 = NULL;
+ ODFConventions *oconv = (ODFConventions *)convs;
+
+ ptr = odf_parse_external (start, &external, convs);
+
+ ptr = oo_cellref_parse (&ref->a, ptr, pp,
+ external == NULL ? NULL : &external_sheet_1);
if (*ptr == ':')
- ptr = oo_cellref_parse (&ref->b, ptr+1, pp);
+ ptr = oo_cellref_parse (&ref->b, ptr+1, pp,
+ external == NULL ? NULL : &external_sheet_2);
else
ref->b = ref->a;
if (ref->b.sheet == invalid_sheet)
ref->a.sheet = invalid_sheet;
+ if (external != NULL) {
+ ref->a.sheet = invalid_sheet;
+ if (oconv != NULL)
+ oo_warning (oconv->xin,
+ _("Ignoring reference to external "
+ "workbook '%s'"),
+ external);
+ else
+ g_warning (_("Ignoring reference to external "
+ "workbook '%s'"),
+ external);
+ g_free (external);
+ g_free (external_sheet_1);
+ g_free (external_sheet_2);
+ }
return ptr;
}
static char const *
oo_expr_rangeref_parse (GnmRangeRef *ref, char const *start, GnmParsePos const *pp,
- G_GNUC_UNUSED GnmConventions const *convs)
+ GnmConventions const *convs)
{
char const *ptr;
if (*start == '[') {
@@ -1212,7 +1276,7 @@ oo_expr_rangeref_parse (GnmRangeRef *ref, char const *start, GnmParsePos const *
ref->a.sheet = invalid_sheet;
return start + 7;
}
- ptr = oo_rangeref_parse (ref, start+1, pp);
+ ptr = oo_rangeref_parse (ref, start+1, pp, convs);
if (*ptr == ']')
return ptr + 1;
}
@@ -1399,10 +1463,11 @@ oo_func_map_in (GnmConventions const *convs, Workbook *scope,
char const *name, GnmExprList *args);
static GnmConventions *
-oo_conventions_new (void)
+oo_conventions_new (OOParseState *state, GsfXMLIn *xin)
{
- GnmConventions *conv = gnm_conventions_new ();
-
+ GnmConventions *conv = gnm_conventions_new_full
+ (sizeof (ODFConventions));
+ ODFConventions *oconv = (ODFConventions *)conv;
conv->decode_ampersands = TRUE;
conv->exp_is_left_associative = TRUE;
@@ -1417,12 +1482,14 @@ oo_conventions_new (void)
conv->input.range_ref = oo_expr_rangeref_parse;
conv->input.name_validate = odf_expr_name_validate;
conv->sheet_name_sep = '.';
+ oconv->state = state;
+ oconv->xin = xin;
return conv;
}
static void
-oo_load_convention (OOParseState *state, OOFormula type)
+oo_load_convention (OOParseState *state, GsfXMLIn *xin, OOFormula type)
{
GnmConventions *convs;
@@ -1434,13 +1501,13 @@ oo_load_convention (OOParseState *state, OOFormula type)
convs->exp_is_left_associative = TRUE;
break;
case FORMULA_OLD_OPENOFFICE:
- convs = oo_conventions_new ();
+ convs = oo_conventions_new (state, xin);
convs->sheet_name_sep = '!'; /* Note that we are using this also as a marker*/
/* in the function handlers */
break;
case FORMULA_OPENFORMULA:
default:
- convs = oo_conventions_new ();
+ convs = oo_conventions_new (state, xin);
break;
}
@@ -1455,7 +1522,7 @@ oo_expr_parse_str_try (GsfXMLIn *xin, char const *str,
OOParseState *state = (OOParseState *)xin->user_state;
if (state->convs[type] == NULL)
- oo_load_convention (state, type);
+ oo_load_convention (state, xin, type);
return gnm_expr_parse_str (str, pp, flags,
state->convs[type], perr);
}
@@ -2192,8 +2259,8 @@ oo_col_start (GsfXMLIn *xin, xmlChar const **attrs)
max_cols = oo_extent_sheet_cols (state->pos.sheet, state->pos.eval.col
+ repeat_count);
if (state->pos.eval.col + repeat_count > max_cols) {
- g_warning ("Ignoring column information beyond"
- " the range we can handle.");
+ oo_warning (xin, _("Ignoring column information beyond"
+ " column %i"), max_cols);
repeat_count = max_cols - state->pos.eval.col - 1;
}
}
@@ -5234,10 +5301,11 @@ oo_db_range_start (GsfXMLIn *xin, xmlChar const **attrs)
for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
if (gsf_xml_in_namecmp (xin, CXML2C (attrs[0]), OO_NS_TABLE, "target-range-address")) {
- char const *ptr = oo_cellref_parse (&ref.a, CXML2C (attrs[1]), &state->pos);
+ char const *ptr = oo_cellref_parse
+ (&ref.a, CXML2C (attrs[1]), &state->pos, NULL);
if (ref.a.sheet != invalid_sheet &&
':' == *ptr &&
- '\0' == *oo_cellref_parse (&ref.b, ptr+1, &state->pos) &&
+ '\0' == *oo_cellref_parse (&ref.b, ptr+1, &state->pos, NULL) &&
ref.b.sheet != invalid_sheet) {
state->filter = gnm_filter_new
(ref.a.sheet, range_init_rangeref (&r, &ref));
@@ -5556,7 +5624,8 @@ od_draw_control_start (GsfXMLIn *xin, xmlChar const **attrs)
GnmRangeRef ref;
char const *ptr = oo_rangeref_parse
(&ref, oc->linked_cell,
- parse_pos_init_sheet (&pp, state->pos.sheet));
+ parse_pos_init_sheet (&pp, state->pos.sheet),
+ NULL);
if (ptr != oc->linked_cell
&& ref.a.sheet != invalid_sheet) {
GnmValue *v = value_new_cellrange
@@ -5594,7 +5663,8 @@ od_draw_control_start (GsfXMLIn *xin, xmlChar const **attrs)
GnmRangeRef ref;
char const *ptr = oo_rangeref_parse
(&ref, oc->source_cell_range,
- parse_pos_init_sheet (&pp, state->pos.sheet));
+ parse_pos_init_sheet (&pp, state->pos.sheet),
+ NULL);
if (ptr != oc->source_cell_range &&
ref.a.sheet != invalid_sheet) {
GnmValue *v = value_new_cellrange
@@ -5631,6 +5701,17 @@ pop_hash (GSList **list, GHashTable **hash)
}
static void
+odf_clear_conventions (OOParseState *state)
+{
+ gint i;
+ for (i = 0; i < NUM_FORMULAE_SUPPORTED; i++)
+ if (state->convs[i] != NULL) {
+ gnm_conventions_unref (state->convs[i]);
+ state->convs[i] = NULL;
+ }
+}
+
+static void
od_draw_object (GsfXMLIn *xin, xmlChar const **attrs)
{
OOParseState *state = (OOParseState *)xin->user_state;
@@ -5717,8 +5798,10 @@ od_draw_object (GsfXMLIn *xin, xmlChar const **attrs)
if (content != NULL) {
GsfXMLInDoc *doc =
gsf_xml_in_doc_new (get_styles_dtd (), gsf_ooo_ns);
+ odf_clear_conventions (state); /* contain references to xin */
gsf_xml_in_doc_parse (doc, content, state);
gsf_xml_in_doc_free (doc);
+ odf_clear_conventions (state); /* contain references to xin */
g_object_unref (content);
}
@@ -5726,8 +5809,10 @@ od_draw_object (GsfXMLIn *xin, xmlChar const **attrs)
if (content != NULL) {
GsfXMLInDoc *doc =
gsf_xml_in_doc_new (get_dtd (), gsf_ooo_ns);
+ odf_clear_conventions (state); /* contain references to xin */
gsf_xml_in_doc_parse (doc, content, state);
gsf_xml_in_doc_free (doc);
+ odf_clear_conventions (state); /* contain references to xin */
g_object_unref (content);
}
if (state->debug)
@@ -6064,8 +6149,10 @@ oo_plot_assign_dim (GsfXMLIn *xin, xmlChar const *range, int dim_type, char cons
if (NULL != range) {
GnmRangeRef ref;
- char const *ptr = oo_rangeref_parse (&ref, CXML2C (range),
- parse_pos_init_sheet (&pp, state->pos.sheet));
+ char const *ptr = oo_rangeref_parse
+ (&ref, CXML2C (range),
+ parse_pos_init_sheet (&pp, state->pos.sheet),
+ NULL);
if (ptr == CXML2C (range) || ref.a.sheet == invalid_sheet)
return;
v = value_new_cellrange (&ref.a, &ref.b, 0, 0);
@@ -6201,8 +6288,9 @@ oo_plot_area (GsfXMLIn *xin, xmlChar const **attrs)
GnmEvalPos ep;
GnmRangeRef ref;
Sheet *dummy;
- char const *ptr = oo_rangeref_parse (&ref, CXML2C (source_range_str),
- parse_pos_init_sheet (&pp, state->pos.sheet));
+ char const *ptr = oo_rangeref_parse
+ (&ref, CXML2C (source_range_str),
+ parse_pos_init_sheet (&pp, state->pos.sheet), NULL);
if (ptr != CXML2C (source_range_str)
&& ref.a.sheet != invalid_sheet) {
gnm_rangeref_normalize (&ref,
@@ -6406,8 +6494,11 @@ oo_plot_series (GsfXMLIn *xin, xmlChar const **attrs)
GnmValue *v;
GnmExprTop const *texpr;
GnmParsePos pp;
- char const *ptr = oo_rangeref_parse (&ref, CXML2C (attrs[1]),
- parse_pos_init_sheet (&pp, state->pos.sheet));
+ char const *ptr = oo_rangeref_parse
+ (&ref, CXML2C (attrs[1]),
+ parse_pos_init_sheet
+ (&pp, state->pos.sheet),
+ NULL);
if (ptr == CXML2C (attrs[1]) ||
ref.a.sheet == invalid_sheet)
return;
@@ -6454,7 +6545,8 @@ oo_plot_series (GsfXMLIn *xin, xmlChar const **attrs)
GnmRangeRef ref;
char const *ptr = oo_rangeref_parse
(&ref, CXML2C (label),
- parse_pos_init_sheet (&pp, state->pos.sheet));
+ parse_pos_init_sheet (&pp, state->pos.sheet),
+ NULL);
if (ptr == CXML2C (label)
|| ref.a.sheet == invalid_sheet)
texpr = oo_expr_parse_str (xin, label,
@@ -6644,7 +6736,8 @@ odf_store_data (OOParseState *state, gchar const *str, GogObject *obj, int dim)
GnmRangeRef ref;
char const *ptr = oo_rangeref_parse
(&ref, CXML2C (str),
- parse_pos_init (&pp, state->pos.wb, NULL, 0, 0));
+ parse_pos_init (&pp, state->pos.wb, NULL, 0, 0),
+ NULL);
if (ptr != CXML2C (str) && ref.a.sheet != invalid_sheet) {
GnmValue *v = value_new_cellrange (&ref.a, &ref.b, 0, 0);
GnmExprTop const *texpr = gnm_expr_top_new_constant (v);
@@ -7110,7 +7203,8 @@ odf_line (GsfXMLIn *xin, xmlChar const **attrs)
GnmRangeRef ref;
char const *ptr = oo_rangeref_parse
(&ref, CXML2C (attrs[1]),
- parse_pos_init_sheet (&pp, state->pos.sheet));
+ parse_pos_init_sheet (&pp, state->pos.sheet),
+ NULL);
if (ptr != CXML2C (attrs[1])
&& ref.a.sheet != invalid_sheet) {
cell_base.end.col = ref.a.col;
@@ -8097,6 +8191,7 @@ static GsfXMLInNode const opendoc_content_dtd [] =
GSF_XML_IN_NODE (CHART_PLOT_AREA, CHART_OOO_COORDINATE_REGION, OO_NS_CHART_OOO, "coordinate-region", GSF_XML_NO_CONTENT, NULL, NULL),
#endif
GSF_XML_IN_NODE (SPREADSHEET, TABLE, OO_NS_TABLE, "table", GSF_XML_NO_CONTENT, &oo_table_start, &oo_table_end),
+ GSF_XML_IN_NODE (TABLE, TABLE_SOURCE, OO_NS_TABLE, "table-source", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (TABLE, FORMS, OO_NS_OFFICE, "forms", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (FORMS, FORM, OO_NS_FORM, "form", GSF_XML_NO_CONTENT, NULL, NULL),
GSF_XML_IN_NODE (FORM, FORM_PROPERTIES, OO_NS_FORM, "properties", GSF_XML_NO_CONTENT, NULL, NULL),
@@ -9156,6 +9251,7 @@ openoffice_file_open (GOFileOpener const *fo, GOIOContext *io_context,
GsfXMLInDoc *doc = gsf_xml_in_doc_new (styles_dtd, gsf_ooo_ns);
gsf_xml_in_doc_parse (doc, styles, &state);
gsf_xml_in_doc_free (doc);
+ odf_clear_conventions (&state); /* contain references to xin */
g_object_unref (styles);
}
@@ -9203,6 +9299,7 @@ openoffice_file_open (GOFileOpener const *fo, GOIOContext *io_context,
(opendoc_settings_dtd, gsf_ooo_ns);
gsf_xml_in_doc_parse (sdoc, settings, &state);
gsf_xml_in_doc_free (sdoc);
+ odf_clear_conventions (&state); /* contain references to xin */
g_object_unref (settings);
}
if (state.settings.stack != NULL) {
@@ -9236,6 +9333,7 @@ openoffice_file_open (GOFileOpener const *fo, GOIOContext *io_context,
} else
go_io_error_string (io_context, _("XML document not well formed!"));
gsf_xml_in_doc_free (doc);
+ odf_clear_conventions (&state);
go_io_progress_unset (state.context);
g_free (state.last_error);
@@ -9271,10 +9369,6 @@ openoffice_file_open (GOFileOpener const *fo, GOIOContext *io_context,
sheet_flag_recompute_spans (workbook_sheet_by_index (state.pos.wb, i));
workbook_queue_all_recalc (state.pos.wb);
- for (i = 0; i < NUM_FORMULAE_SUPPORTED; i++)
- if (state.convs[i] != NULL)
- gnm_conventions_unref (state.convs[i]);
-
gnm_pop_C_locale (locale);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]