3 * xml-sax-read.c : a sax based parser.
5 * Copyright (C) 2000-2007 Jody Goldberg (jody@gnome.org)
6 * Copyright (C) 2007-2009 Morten Welinder (terra@gnome.org)
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) version 3.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
24 #include <gnumeric-config.h>
27 #include <xml-io-version.h>
28 #include <gnm-plugin.h>
29 #include <sheet-view.h>
30 #include <sheet-style.h>
31 #include <sheet-merge.h>
32 #include <sheet-filter.h>
35 #include <tools/gnm-solver.h>
36 #include <tools/scenarios.h>
38 #include <style-border.h>
39 #include <style-color.h>
40 #include <style-conditions.h>
41 #include <validation.h>
43 #include <input-msg.h>
47 #include <expr-name.h>
48 #include <print-info.h>
50 #include <selection.h>
51 #include <command-context.h>
52 #include <workbook-view.h>
53 #include <workbook-control.h>
55 #include <sheet-object-impl.h>
56 #include <sheet-object-cell-comment.h>
57 #include <gnm-so-line.h>
58 #include <gnm-so-filled.h>
59 #include <gnm-so-path.h>
60 #include <gnm-format.h>
61 #include <sheet-object-graph.h>
62 #include <sheet-object-component.h>
63 #include <application.h>
65 #include <clipboard.h>
66 #include <number-match.h>
68 #include <goffice/goffice.h>
70 #include <gsf/gsf-libxml.h>
71 #include <gsf/gsf-input.h>
72 #include <gsf/gsf-input-memory.h>
73 #include <gsf/gsf-input-gzip.h>
74 #include <gsf/gsf-opendoc-utils.h>
75 #include <gsf/gsf-utils.h>
76 #include <glib/gi18n-lib.h>
77 #include <libxml/tree.h>
78 #include <libxml/parser.h>
79 #include <libxml/parserInternals.h>
84 /* libgsf defines OO_NS_OFFICE to be 0, so we need to take something different for GNM */
88 xml_sax_barf (const char *locus
, const char *reason
)
90 g_warning ("File is most likely corrupted.\n"
91 "The problem was detected in %s.\n"
92 "The failed check was: %s",
96 #define XML_CHECK3(_cond_,_code_,_reason_) \
98 if (G_UNLIKELY(!(_cond_))) { \
99 xml_sax_barf (G_STRFUNC, _reason_); \
105 #define XML_CHECK(_cond_) XML_CHECK3(_cond_,{},#_cond_)
106 #define XML_CHECK2(_cond_,_code_) XML_CHECK3(_cond_,_code_,#_cond_)
109 #define CXML2C(s) ((char const *)(s))
111 static inline gboolean
112 attr_eq (const xmlChar
*a
, const char *s
)
114 return !strcmp (CXML2C (a
), s
);
118 make_format (const char *str
)
121 gnm_format_import (str
,
122 GNM_FORMAT_IMPORT_NULL_INVALID
|
123 GNM_FORMAT_IMPORT_PATCHUP_INCOMPLETE
);
125 g_warning ("Ignoring invalid format [%s]", str
);
132 /*****************************************************************************/
135 gnm_xml_attr_double (xmlChar
const * const *attrs
, char const *name
, double * res
)
140 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
141 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
142 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
144 if (!attr_eq (attrs
[0], name
))
147 tmp
= go_strtod (CXML2C (attrs
[1]), &end
);
149 g_warning ("Invalid attribute '%s', expected double, received '%s'",
158 xml_sax_double (xmlChar
const *chars
, double *res
)
161 *res
= go_strtod (CXML2C (chars
), &end
);
166 gnm_xml_attr_bool (xmlChar
const * const *attrs
, char const *name
, gboolean
*res
)
168 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
169 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
170 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
172 if (!attr_eq (attrs
[0], name
))
175 *res
= g_ascii_strcasecmp (CXML2C (attrs
[1]), "false") && strcmp (CXML2C (attrs
[1]), "0");
181 gnm_xml_attr_int (xmlChar
const * const *attrs
, char const *name
, int *res
)
186 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
187 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
188 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
190 if (!attr_eq (attrs
[0], name
))
194 tmp
= strtol (CXML2C (attrs
[1]), &end
, 10);
196 g_warning ("Invalid attribute '%s', expected integer, received '%s'",
204 /* NOT SUITABLE FOR HIGH VOLUME VALUES
205 * Checking both name and nick gets expensive */
207 xml_sax_attr_enum (xmlChar
const * const *attrs
,
216 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
217 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
218 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
220 if (!attr_eq (attrs
[0], name
))
223 eclass
= G_ENUM_CLASS (g_type_class_ref (etype
));
224 ev
= g_enum_get_value_by_name (eclass
, CXML2C (attrs
[1]));
225 if (!ev
) ev
= g_enum_get_value_by_nick (eclass
, CXML2C (attrs
[1]));
226 g_type_class_unref (eclass
);
228 if (!ev
&& gnm_xml_attr_int (attrs
, name
, &i
))
229 /* Check that the value is valid. */
230 ev
= g_enum_get_value (eclass
, i
);
231 if (!ev
) return FALSE
;
239 xml_sax_attr_cellpos (xmlChar
const * const *attrs
, char const *name
, GnmCellPos
*val
, Sheet
const *sheet
)
241 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
242 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
243 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
245 if (!attr_eq (attrs
[0], name
))
248 if (cellpos_parse (CXML2C (attrs
[1]), gnm_sheet_get_size (sheet
), val
, TRUE
) == NULL
) {
249 g_warning ("Invalid attribute '%s', expected cellpos, received '%s'",
257 xml_sax_attr_color (xmlChar
const * const *attrs
, char const *name
, GnmColor
**res
)
259 unsigned int red
, green
, blue
, alpha
= 0xffff;
261 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
262 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
263 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
265 if (!attr_eq (attrs
[0], name
))
268 if (sscanf (CXML2C (attrs
[1]), "%X:%X:%X:%X", &red
, &green
, &blue
, &alpha
) < 3){
269 g_warning ("Invalid attribute '%s', expected colour, received '%s'",
273 *res
= gnm_color_new_rgba16 (red
, green
, blue
, alpha
);
278 xml_sax_attr_range (xmlChar
const * const *attrs
, GnmRange
*res
)
282 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
284 for (; attrs
[0] && attrs
[1] ; attrs
+= 2)
285 if (gnm_xml_attr_int (attrs
, "startCol", &res
->start
.col
))
287 else if (gnm_xml_attr_int (attrs
, "startRow", &res
->start
.row
))
289 else if (gnm_xml_attr_int (attrs
, "endCol", &res
->end
.col
))
291 else if (gnm_xml_attr_int (attrs
, "endRow", &res
->end
.row
))
299 /*****************************************************************************/
311 GOIOContext
*context
; /* The IOcontext managing things */
312 WorkbookView
*wb_view
; /* View for the new workbook */
313 Workbook
*wb
; /* The new workbook */
314 GnumericXMLVersion version
;
315 gsf_off_t last_progress_update
;
316 GnmConventions
*convs
;
317 gboolean do_progress
;
322 /* Only valid while parsing attributes */
328 /* Only valid when parsing wb or sheet names */
338 GnmExprTop
const *texpr
[2];
339 ValidationStyle style
;
342 gboolean allow_blank
;
343 gboolean use_dropdown
;
347 GnmStyle
*cond_save_style
;
349 gboolean style_range_init
;
350 GnmRange style_range
;
354 gboolean seen_cell_contents
;
355 int expr_id
, array_rows
, array_cols
;
360 GnmScenario
*scenario
;
361 GnmValue
*scenario_range
;
365 int display_formulas
;
370 int display_outlines
;
371 int outline_symbols_below
;
372 int outline_symbols_right
;
375 char *expr_conv_name
;
376 GnmSheetVisibility visibility
;
378 GnmColor
*tab_text_color
;
379 GnmColor
*grid_color
;
381 /* expressions with ref > 1 a map from index -> expr pointer */
382 GHashTable
*expr_map
;
383 GList
*delayed_names
;
386 int sheet_rows
, sheet_cols
;
387 GnmSheetType sheet_type
;
389 GnmPageBreaks
*page_breaks
;
391 GnmCellRegion
*clipboard
;
393 GnmXmlStyleHandler style_handler
;
394 gpointer style_handler_user
;
395 GsfXMLInDoc
*style_handler_doc
;
399 maybe_update_progress (GsfXMLIn
*xin
)
401 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
402 GsfInput
*input
= gsf_xml_in_get_input (xin
);
403 gsf_off_t pos
= gsf_input_tell (input
);
405 if (state
->do_progress
&& pos
>= state
->last_progress_update
+ 10000) {
406 go_io_value_progress_update (state
->context
, pos
);
407 state
->last_progress_update
= pos
;
412 * gnm_xml_in_cur_obj:
415 * Returns: (transfer none): the current sheet object.
418 gnm_xml_in_cur_obj (GsfXMLIn
const *xin
)
420 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
425 * gnm_xml_in_cur_sheet:
428 * Returns: (transfer none): the current sheet.
431 gnm_xml_in_cur_sheet (GsfXMLIn
const *xin
)
433 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
438 gnm_xml_finish_obj (GsfXMLIn
*xin
, XMLSaxParseState
*state
)
440 GnmCellRegion
*cr
= state
->clipboard
;
443 cr
->objects
= g_slist_prepend (cr
->objects
, state
->so
);
445 sheet_object_set_sheet (state
->so
, state
->sheet
);
446 g_object_unref (state
->so
);
452 /****************************************************************************/
455 unknown_attr (GsfXMLIn
*xin
, xmlChar
const * const *attrs
)
457 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
459 if (state
->version
== GNM_XML_LATEST
)
460 go_io_warning (state
->context
,
461 _("Unexpected attribute %s::%s == '%s'."),
462 (NULL
!= xin
->node
&&
463 NULL
!= xin
->node
->name
) ?
464 xin
->node
->name
: "<unknown name>",
469 xml_sax_wb (GsfXMLIn
*xin
, xmlChar
const **attrs
)
471 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
474 * NOTE: If we read a file with a dtd that is newer, i.e., from the
475 * future, then we will not get here! For that reason we also muck
476 * with ->version in xml_sax_version.
478 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
479 if (strcmp (CXML2C (attrs
[0]), "xmlns:gmr") == 0 ||
480 strcmp (CXML2C (attrs
[0]), "xmlns:gnm") == 0) {
482 char const * const id
;
483 GnumericXMLVersion
const version
;
484 } const GnumericVersions
[] = {
485 { "http://www.gnumeric.org/v14.dtd", GNM_XML_V14
}, /* 1.12.21 */
486 { "http://www.gnumeric.org/v13.dtd", GNM_XML_V13
}, /* 1.7.7 */
487 { "http://www.gnumeric.org/v12.dtd", GNM_XML_V12
}, /* 1.7.3 */
488 { "http://www.gnumeric.org/v11.dtd", GNM_XML_V11
}, /* 1.7.0 */
489 { "http://www.gnumeric.org/v10.dtd", GNM_XML_V10
}, /* 1.0.3 */
490 { "http://www.gnumeric.org/v9.dtd", GNM_XML_V9
}, /* 0.73 */
491 { "http://www.gnumeric.org/v8.dtd", GNM_XML_V8
}, /* 0.71 */
492 { "http://www.gnome.org/gnumeric/v7", GNM_XML_V7
}, /* 0.66 */
493 { "http://www.gnome.org/gnumeric/v6", GNM_XML_V6
}, /* 0.62 */
494 { "http://www.gnome.org/gnumeric/v5", GNM_XML_V5
},
495 { "http://www.gnome.org/gnumeric/v4", GNM_XML_V4
},
496 { "http://www.gnome.org/gnumeric/v3", GNM_XML_V3
},
497 { "http://www.gnome.org/gnumeric/v2", GNM_XML_V2
},
498 { "http://www.gnome.org/gnumeric/", GNM_XML_V1
},
502 for (i
= 0 ; GnumericVersions
[i
].id
!= NULL
; ++i
)
503 if (strcmp (CXML2C (attrs
[1]), GnumericVersions
[i
].id
) == 0) {
504 if (state
->version
!= GNM_XML_UNKNOWN
)
505 go_io_warning (state
->context
,
506 _("Multiple version specifications. Assuming %d"),
509 state
->version
= GnumericVersions
[i
].version
;
513 } else if (attr_eq (attrs
[0], "xmlns:xsi")) {
514 } else if (attr_eq (attrs
[0], "xsi:schemaLocation")) {
516 unknown_attr (xin
, attrs
);
521 xml_sax_document_meta (GsfXMLIn
*xin
, G_GNUC_UNUSED xmlChar
const **attrs
)
523 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
525 gsf_doc_meta_data_odf_subtree (go_doc_get_meta_data (GO_DOC (state
->wb
)), xin
);
531 xml_sax_version (GsfXMLIn
*xin
, xmlChar
const **attrs
)
533 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
539 state
->version
= GNM_XML_V11
;
540 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
541 if (gnm_xml_attr_int (attrs
, "Epoch", &epoch
))
543 else if (gnm_xml_attr_int (attrs
, "Major", &major
))
545 else if (gnm_xml_attr_int (attrs
, "Minor", &minor
))
549 version
= (epoch
* 100 + major
) * 100 + minor
;
550 if (state
->version
== GNM_XML_UNKNOWN
&& version
>= 10700) {
551 if (version
>= 11221)
552 state
->version
= GNM_XML_V14
;
553 else if (version
>= 10707)
554 state
->version
= GNM_XML_V13
;
555 else if (version
>= 10705)
556 state
->version
= GNM_XML_V12
;
557 else if (version
>= 10700)
558 state
->version
= GNM_XML_V11
;
563 xml_sax_wb_sheetsize (GsfXMLIn
*xin
, xmlChar
const **attrs
)
565 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
567 /* Defaults for legacy files. */
568 state
->sheet_cols
= 256;
569 state
->sheet_rows
= 65536;
570 state
->sheet_type
= GNM_SHEET_DATA
;
572 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
573 if (gnm_xml_attr_int (attrs
, "gnm:Cols", &state
->sheet_cols
))
575 else if (gnm_xml_attr_int (attrs
, "gnm:Rows", &state
->sheet_rows
))
577 else if (!strcmp (CXML2C (attrs
[0]), "gnm:SheetType") &&
578 !strcmp (CXML2C (attrs
[1]), "object"))
579 state
->sheet_type
= GNM_SHEET_OBJECT
;
581 unknown_attr (xin
, attrs
);
586 xml_sax_wb_sheetname (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
588 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
589 char const *name
= xin
->content
->str
;
590 Workbook
*wb
= state
->wb
;
592 g_return_if_fail (name
!= NULL
);
594 if (NULL
== workbook_sheet_by_name (wb
, name
)) {
597 if (!gnm_sheet_valid_size (state
->sheet_cols
,
598 state
->sheet_rows
)) {
599 gnm_sheet_suggest_size (&state
->sheet_cols
,
603 sheet
= sheet_new_with_type (wb
, name
,
607 workbook_sheet_attach (wb
, sheet
);
612 xml_sax_wb_view (GsfXMLIn
*xin
, xmlChar
const **attrs
)
614 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
617 int width
= -1, height
= -1;
619 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
620 if (gnm_xml_attr_int (attrs
, "SelectedTab", &sheet_index
)) {
621 Sheet
*sheet
= workbook_sheet_by_index (state
->wb
,
624 wb_view_sheet_focus (state
->wb_view
, sheet
);
626 else if (gnm_xml_attr_int (attrs
, "Width", &width
)) ;
627 else if (gnm_xml_attr_int (attrs
, "Height", &height
)) ;
629 unknown_attr (xin
, attrs
);
631 if (width
> 0 && height
> 0)
632 wb_view_preferred_size (state
->wb_view
, width
, height
);
635 xml_sax_calculation (GsfXMLIn
*xin
, xmlChar
const **attrs
)
637 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
642 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
643 if (gnm_xml_attr_bool (attrs
, "ManualRecalc", &b
))
644 workbook_set_recalcmode (state
->wb
, !b
);
645 else if (gnm_xml_attr_bool (attrs
, "EnableIteration", &b
))
646 workbook_iteration_enabled (state
->wb
, b
);
647 else if (gnm_xml_attr_int (attrs
, "MaxIterations", &i
))
648 workbook_iteration_max_number (state
->wb
, i
);
649 else if (gnm_xml_attr_double (attrs
, "IterationTolerance", &d
))
650 workbook_iteration_tolerance (state
->wb
, d
);
651 else if (strcmp (CXML2C (attrs
[0]), "DateConvention") == 0) {
652 GODateConventions
const *date_conv
=
653 go_date_conv_from_str (CXML2C (attrs
[1]));
655 workbook_set_date_conv (state
->wb
, date_conv
);
657 g_printerr ("Ignoring invalid date conventions.\n");
659 unknown_attr (xin
, attrs
);
663 xml_sax_old_dateconvention (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
665 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
666 workbook_set_1904 (state
->wb
, strcmp (xin
->content
->str
, "1904") == 0);
670 xml_sax_finish_parse_wb_attr (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
672 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
674 if (state
->attribute
.name
&& state
->attribute
.value
) {
675 wb_view_set_attribute (state
->wb_view
,
676 state
->attribute
.name
,
677 state
->attribute
.value
);
679 xml_sax_barf (G_STRFUNC
, _("workbook view attribute is incomplete"));
682 g_free (state
->attribute
.value
); state
->attribute
.value
= NULL
;
683 g_free (state
->attribute
.name
); state
->attribute
.name
= NULL
;
687 xml_sax_attr_elem (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
689 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
691 char const *content
= xin
->content
->str
;
692 int const len
= xin
->content
->len
;
694 switch (xin
->node
->user_data
.v_int
) {
696 g_return_if_fail (state
->attribute
.name
== NULL
);
697 state
->attribute
.name
= g_strndup (content
, len
);
701 g_return_if_fail (state
->attribute
.value
== NULL
);
702 state
->attribute
.value
= g_strndup (content
, len
);
706 g_assert_not_reached ();
711 xml_sax_sheet_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
713 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
717 GnmColor
*color
= NULL
;
719 state
->hide_col_header
= state
->hide_row_header
=
720 state
->display_formulas
= state
->hide_zero
=
721 state
->hide_grid
= state
->display_outlines
=
722 state
->outline_symbols_below
= state
->outline_symbols_right
=
723 state
->text_is_rtl
= state
->is_protected
= -1;
724 state
->expr_conv_name
= NULL
;
725 state
->visibility
= GNM_SHEET_VISIBILITY_VISIBLE
;
726 state
->tab_color
= NULL
;
727 state
->tab_text_color
= NULL
;
728 state
->grid_color
= NULL
;
729 state
->sheet_zoom
= 1.; /* default */
731 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
732 if (gnm_xml_attr_bool (attrs
, "DisplayFormulas", &tmp
))
733 state
->display_formulas
= tmp
;
734 else if (gnm_xml_attr_bool (attrs
, "HideZero", &tmp
))
735 state
->hide_zero
= tmp
;
736 else if (gnm_xml_attr_bool (attrs
, "HideGrid", &tmp
))
737 state
->hide_grid
= tmp
;
738 else if (gnm_xml_attr_bool (attrs
, "HideColHeader", &tmp
))
739 state
->hide_col_header
= tmp
;
740 else if (gnm_xml_attr_bool (attrs
, "HideRowHeader", &tmp
))
741 state
->hide_row_header
= tmp
;
742 else if (gnm_xml_attr_bool (attrs
, "DisplayOutlines", &tmp
))
743 state
->display_outlines
= tmp
;
744 else if (gnm_xml_attr_bool (attrs
, "OutlineSymbolsBelow", &tmp
))
745 state
->outline_symbols_below
= tmp
;
746 else if (gnm_xml_attr_bool (attrs
, "OutlineSymbolsRight", &tmp
))
747 state
->outline_symbols_right
= tmp
;
748 else if (xml_sax_attr_enum (attrs
, "Visibility", GNM_SHEET_VISIBILITY_TYPE
, &tmpi
))
749 state
->visibility
= tmpi
;
750 else if (gnm_xml_attr_bool (attrs
, "RTL_Layout", &tmp
))
751 state
->text_is_rtl
= tmp
;
752 else if (gnm_xml_attr_bool (attrs
, "Protected", &tmp
))
753 state
->is_protected
= tmp
;
754 else if (strcmp (CXML2C (attrs
[0]), "ExprConvention") == 0)
755 state
->expr_conv_name
= g_strdup (attrs
[1]);
756 else if (xml_sax_attr_color (attrs
, "TabColor", &color
))
757 state
->tab_color
= color
;
758 else if (xml_sax_attr_color (attrs
, "TabTextColor", &color
))
759 state
->tab_text_color
= color
;
760 else if (xml_sax_attr_color (attrs
, "GridColor", &color
))
761 state
->grid_color
= color
;
763 unknown_attr (xin
, attrs
);
767 xml_sax_must_have_sheet (XMLSaxParseState
*state
)
773 xml_sax_barf (G_STRFUNC
, "sheet should have been named");
775 state
->sheet
= workbook_sheet_add (state
->wb
, -1,
783 xml_sax_must_have_style (XMLSaxParseState
*state
)
786 xml_sax_barf (G_STRFUNC
, "style should have been started");
787 state
->style
= (state
->version
>= GNM_XML_V6
||
788 state
->version
<= GNM_XML_V2
)
789 ? gnm_style_new_default ()
798 xml_sax_sheet_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
800 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
802 xml_sax_must_have_sheet (state
);
804 /* Init ColRowInfo's size_pixels and force a full respan */
805 g_object_set (state
->sheet
, "zoom-factor", state
->sheet_zoom
, NULL
);
806 sheet_flag_recompute_spans (state
->sheet
);
811 xml_sax_sheet_name (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
813 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
818 char const * content
= xin
->content
->str
;
819 g_return_if_fail (state
->sheet
== NULL
);
821 /* * FIXME: Pull this out at some point, so we don't
822 * have to support < GNM_XML_V7 anymore
824 if (state
->version
>= GNM_XML_V7
) {
825 sheet
= workbook_sheet_by_name (state
->wb
, content
);
827 go_io_error_string (state
->context
,
828 _("File has inconsistent SheetNameIndex element."));
829 sheet
= sheet_new (state
->wb
, content
,
831 workbook_sheet_attach (state
->wb
, sheet
);
834 sheet
= sheet_new (state
->wb
, content
, columns
, rows
);
835 workbook_sheet_attach (state
->wb
, sheet
);
837 state
->sheet
= sheet
;
839 if (state
->display_formulas
>= 0)
840 g_object_set (sheet
, "display-formulas", state
->display_formulas
, NULL
);
841 if (state
->hide_zero
>= 0)
842 g_object_set (sheet
, "display-zeros", !state
->hide_zero
, NULL
);
843 if (state
->hide_grid
>= 0)
844 g_object_set (sheet
, "display-grid", !state
->hide_grid
, NULL
);
845 if (state
->hide_col_header
>= 0)
846 g_object_set (sheet
, "display-column-header", !state
->hide_col_header
, NULL
);
847 if (state
->hide_row_header
>= 0)
848 g_object_set (sheet
, "display-row-header", !state
->hide_row_header
, NULL
);
849 if (state
->display_outlines
>= 0)
850 g_object_set (sheet
, "display-outlines", state
->display_outlines
, NULL
);
851 if (state
->outline_symbols_below
>= 0)
852 g_object_set (sheet
, "display-outlines-below", state
->outline_symbols_below
, NULL
);
853 if (state
->outline_symbols_right
>= 0)
854 g_object_set (sheet
, "display-outlines-right", state
->outline_symbols_right
, NULL
);
855 if (state
->text_is_rtl
>= 0)
856 g_object_set (sheet
, "text-is-rtl", state
->text_is_rtl
, NULL
);
857 if (state
->is_protected
>= 0)
858 g_object_set (sheet
, "protected", state
->is_protected
, NULL
);
859 if (state
->expr_conv_name
!= NULL
) {
860 GnmConventions
const *convs
= gnm_conventions_default
;
861 if (0 == strcmp (state
->expr_conv_name
, "gnumeric:R1C1"))
862 convs
= gnm_conventions_xls_r1c1
;
863 g_object_set (sheet
, "conventions", convs
, NULL
);
865 g_free (state
->expr_conv_name
);
866 state
->expr_conv_name
= NULL
;
868 g_object_set (sheet
, "visibility", state
->visibility
, NULL
);
869 sheet
->tab_color
= state
->tab_color
;
870 sheet
->tab_text_color
= state
->tab_text_color
;
871 if (state
->grid_color
)
872 sheet_style_set_auto_pattern_color (sheet
, state
->grid_color
);
876 xml_sax_sheet_zoom (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
878 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
880 char const * content
= xin
->content
->str
;
883 xml_sax_must_have_sheet (state
);
885 if (xml_sax_double ((xmlChar
*)content
, &zoom
))
886 state
->sheet_zoom
= zoom
;
890 xml_sax_print_margins_unit (GsfXMLIn
*xin
, xmlChar
const **attrs
,
891 double *points
, GtkUnit
*desired_display
)
893 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
895 if (gnm_xml_attr_double (attrs
, "Points", &pts
)) {
897 } else if (attr_eq (attrs
[0], "PrefUnit")) {
898 *desired_display
= unit_name_to_unit (CXML2C (attrs
[1]));
900 unknown_attr (xin
, attrs
);
905 xml_sax_print_margins (GsfXMLIn
*xin
, xmlChar
const **attrs
)
907 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
909 GnmPrintInformation
*pi
;
912 xml_sax_must_have_sheet (state
);
914 pi
= state
->sheet
->print_info
;
915 switch (xin
->node
->user_data
.v_int
) {
917 xml_sax_print_margins_unit (xin
, attrs
,
919 &pi
->desired_display
.header
);
921 print_info_set_edge_to_below_header (pi
, points
);
924 xml_sax_print_margins_unit (xin
, attrs
,
926 &pi
->desired_display
.footer
);
928 print_info_set_edge_to_above_footer (pi
, points
);
931 xml_sax_print_margins_unit (xin
, attrs
,
932 &points
, &pi
->desired_display
.left
);
934 print_info_set_margin_left (pi
, points
);
937 xml_sax_print_margins_unit (xin
, attrs
,
938 &points
, &pi
->desired_display
.right
);
940 print_info_set_margin_right (pi
, points
);
943 xml_sax_print_margins_unit (xin
, attrs
,
944 &points
, &pi
->desired_display
.top
);
946 print_info_set_margin_header (pi
, points
);
949 xml_sax_print_margins_unit (xin
, attrs
,
950 &points
, &pi
->desired_display
.bottom
);
952 print_info_set_margin_footer (pi
, points
);
961 xml_sax_page_break (GsfXMLIn
*xin
, xmlChar
const **attrs
)
963 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
964 GnmPageBreakType type
= GNM_PAGE_BREAK_NONE
;
967 if (NULL
== state
->page_breaks
)
970 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
971 if (gnm_xml_attr_int (attrs
, "pos", &pos
)) ;
972 else if (!strcmp (CXML2C (attrs
[0]), "type"))
973 type
= gnm_page_break_type_from_str (CXML2C (attrs
[1]));
975 /* drops invalid positions */
976 gnm_page_breaks_append_break (state
->page_breaks
, pos
, type
);
980 xml_sax_page_breaks_begin (GsfXMLIn
*xin
, G_GNUC_UNUSED xmlChar
const **attrs
)
982 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
983 xml_sax_must_have_sheet (state
);
984 g_return_if_fail (state
->page_breaks
== NULL
);
985 state
->page_breaks
= gnm_page_breaks_new (xin
->node
->user_data
.v_int
);
989 xml_sax_page_breaks_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
991 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
993 if (NULL
!= state
->page_breaks
) {
994 print_info_set_breaks (state
->sheet
->print_info
,
996 state
->page_breaks
= NULL
;
1001 xml_sax_print_scale (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1003 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1005 GnmPrintInformation
*pi
;
1009 xml_sax_must_have_sheet (state
);
1011 pi
= state
->sheet
->print_info
;
1012 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1013 if (attr_eq (attrs
[0], "type"))
1014 pi
->scaling
.type
= !strcmp (CXML2C (attrs
[1]), "percentage")
1015 ? PRINT_SCALE_PERCENTAGE
: PRINT_SCALE_FIT_PAGES
;
1016 else if (gnm_xml_attr_double (attrs
, "percentage", &percentage
))
1017 pi
->scaling
.percentage
.x
= pi
->scaling
.percentage
.y
= percentage
;
1018 else if (gnm_xml_attr_int (attrs
, "cols", &cols
))
1019 pi
->scaling
.dim
.cols
= cols
;
1020 else if (gnm_xml_attr_int (attrs
, "rows", &rows
))
1021 pi
->scaling
.dim
.rows
= rows
;
1026 xml_sax_print_vcenter (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1028 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1029 GnmPrintInformation
*pi
;
1032 xml_sax_must_have_sheet (state
);
1034 pi
= state
->sheet
->print_info
;
1036 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1037 if (gnm_xml_attr_int (attrs
, "value", &val
))
1038 pi
->center_vertically
= val
;
1042 xml_sax_print_hcenter (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1044 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1045 GnmPrintInformation
*pi
;
1048 xml_sax_must_have_sheet (state
);
1050 pi
= state
->sheet
->print_info
;
1052 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1053 if (gnm_xml_attr_int (attrs
, "value", &val
))
1054 pi
->center_horizontally
= val
;
1058 xml_sax_print_grid (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1060 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1061 GnmPrintInformation
*pi
;
1064 xml_sax_must_have_sheet (state
);
1066 pi
= state
->sheet
->print_info
;
1068 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1069 if (gnm_xml_attr_int (attrs
, "value", &val
))
1070 pi
->print_grid_lines
= val
;
1074 xml_sax_print_do_not_print (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1076 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1077 GnmPrintInformation
*pi
;
1080 xml_sax_must_have_sheet (state
);
1082 pi
= state
->sheet
->print_info
;
1084 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1085 if (gnm_xml_attr_int (attrs
, "value", &val
))
1086 pi
->do_not_print
= val
;
1090 xml_sax_print_print_range (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1092 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1093 GnmPrintInformation
*pi
;
1096 xml_sax_must_have_sheet (state
);
1098 pi
= state
->sheet
->print_info
;
1100 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1101 if (xml_sax_attr_enum (attrs
, "value", GNM_PRINT_RANGE_TYPE
,
1103 print_info_set_printrange (pi
, val
);
1109 xml_sax_monochrome (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1111 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1112 GnmPrintInformation
*pi
;
1115 xml_sax_must_have_sheet (state
);
1117 pi
= state
->sheet
->print_info
;
1119 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1120 if (gnm_xml_attr_int (attrs
, "value", &val
))
1121 pi
->print_black_and_white
= val
;
1125 xml_sax_print_titles (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1127 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1128 GnmPrintInformation
*pi
;
1131 xml_sax_must_have_sheet (state
);
1133 pi
= state
->sheet
->print_info
;
1135 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1136 if (gnm_xml_attr_int (attrs
, "value", &val
))
1137 pi
->print_titles
= val
;
1141 xml_sax_repeat_top (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1143 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1144 GnmPrintInformation
*pi
;
1146 xml_sax_must_have_sheet (state
);
1148 pi
= state
->sheet
->print_info
;
1150 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1151 if (!strcmp (CXML2C (attrs
[0]), "value")) {
1152 g_free (pi
->repeat_top
);
1153 pi
->repeat_top
= g_strdup (CXML2C (attrs
[1]));
1159 xml_sax_repeat_left (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1161 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1162 GnmPrintInformation
*pi
;
1164 xml_sax_must_have_sheet (state
);
1166 pi
= state
->sheet
->print_info
;
1168 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1169 if (!strcmp (CXML2C (attrs
[0]), "value")) {
1170 g_free (pi
->repeat_left
);
1171 pi
->repeat_left
= g_strdup (CXML2C (attrs
[1]));
1177 xml_sax_print_hf (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1179 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1180 GnmPrintInformation
*pi
;
1183 xml_sax_must_have_sheet (state
);
1185 pi
= state
->sheet
->print_info
;
1187 switch (xin
->node
->user_data
.v_int
) {
1198 g_return_if_fail (hf
!= NULL
);
1200 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1201 if ( attr_eq (attrs
[0], "Left")) {
1202 g_free (hf
->left_format
);
1203 hf
->left_format
= g_strdup (CXML2C (attrs
[1]));
1204 } else if (attr_eq (attrs
[0], "Middle")) {
1205 g_free (hf
->middle_format
);
1206 hf
->middle_format
= g_strdup (CXML2C (attrs
[1]));
1207 } else if (attr_eq (attrs
[0], "Right")) {
1208 g_free (hf
->right_format
);
1209 hf
->right_format
= g_strdup (CXML2C (attrs
[1]));
1211 unknown_attr (xin
, attrs
);
1217 xml_sax_even_if_only_styles (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1219 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1220 GnmPrintInformation
*pi
;
1223 xml_sax_must_have_sheet (state
);
1225 pi
= state
->sheet
->print_info
;
1227 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1228 if (gnm_xml_attr_int (attrs
, "value", &val
))
1229 pi
->print_even_if_only_styles
= val
;
1236 xml_sax_selection_range (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1238 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1241 xml_sax_must_have_sheet (state
);
1242 if (xml_sax_attr_range (attrs
, &r
))
1243 sv_selection_add_range (
1244 sheet_get_view (state
->sheet
, state
->wb_view
), &r
);
1248 xml_sax_selection (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1250 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1251 Sheet
*sheet
= xml_sax_must_have_sheet (state
);
1252 int col
= -1, row
= -1;
1254 sv_selection_reset (sheet_get_view (sheet
, state
->wb_view
));
1256 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1257 if (gnm_xml_attr_int (attrs
, "CursorCol", &col
)) ;
1258 else if (gnm_xml_attr_int (attrs
, "CursorRow", &row
)) ;
1260 unknown_attr (xin
, attrs
);
1262 XML_CHECK (state
->cell
.col
< 0);
1263 XML_CHECK (state
->cell
.row
< 0);
1265 /* Default in case of error. */
1266 state
->cell
.col
= 0;
1267 state
->cell
.row
= 0;
1269 XML_CHECK (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
));
1270 XML_CHECK (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
));
1272 state
->cell
.col
= col
;
1273 state
->cell
.row
= row
;
1277 xml_sax_selection_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1279 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1281 GnmCellPos
const pos
= state
->cell
;
1282 state
->cell
.col
= state
->cell
.row
= -1;
1283 gnm_sheet_view_set_edit_pos (sheet_get_view (state
->sheet
, state
->wb_view
), &pos
);
1287 xml_sax_sheet_layout (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1289 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1292 xml_sax_must_have_sheet (state
);
1294 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1295 if (xml_sax_attr_cellpos (attrs
, "TopLeft", &tmp
, state
->sheet
))
1296 gnm_sheet_view_set_initial_top_left (
1297 sheet_get_view (state
->sheet
, state
->wb_view
),
1300 unknown_attr (xin
, attrs
);
1304 xml_sax_sheet_freezepanes (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1306 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1307 GnmCellPos frozen_tl
, unfrozen_tl
;
1310 xml_sax_must_have_sheet (state
);
1312 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1313 if (xml_sax_attr_cellpos (attrs
, "FrozenTopLeft", &frozen_tl
, state
->sheet
))
1315 else if (xml_sax_attr_cellpos (attrs
, "UnfrozenTopLeft", &unfrozen_tl
, state
->sheet
))
1318 unknown_attr (xin
, attrs
);
1321 gnm_sheet_view_freeze_panes (sheet_get_view (state
->sheet
, state
->wb_view
),
1322 &frozen_tl
, &unfrozen_tl
);
1326 xml_sax_cols_rows (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1328 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1330 gboolean
const is_col
= xin
->node
->user_data
.v_bool
;
1332 xml_sax_must_have_sheet (state
);
1334 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1335 if (gnm_xml_attr_double (attrs
, "DefaultSizePts", &def_size
)) {
1337 sheet_col_set_default_size_pts (state
->sheet
, def_size
);
1339 sheet_row_set_default_size_pts (state
->sheet
, def_size
);
1344 xml_sax_colrow (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1346 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1348 ColRowInfo
*cri
= NULL
;
1351 int hidden
= 0, hard_size
= 0, is_collapsed
= 0, outline_level
= 0;
1353 gboolean
const is_col
= xin
->node
->user_data
.v_bool
;
1354 Sheet
*sheet
= xml_sax_must_have_sheet (state
);
1356 maybe_update_progress (xin
);
1358 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1359 if (gnm_xml_attr_int (attrs
, "No", &pos
)) ;
1360 else if (gnm_xml_attr_double (attrs
, "Unit", &size
)) ;
1361 else if (gnm_xml_attr_int (attrs
, "Count", &count
)) ;
1362 else if (gnm_xml_attr_int (attrs
, "HardSize", &hard_size
)) ;
1363 else if (gnm_xml_attr_int (attrs
, "Hidden", &hidden
)) ;
1364 else if (gnm_xml_attr_int (attrs
, "Collapsed", &is_collapsed
)) ;
1365 else if (gnm_xml_attr_int (attrs
, "OutlineLevel", &outline_level
)) ;
1366 else if (gnm_xml_attr_int (attrs
, "MarginA", &val
))
1367 ; /* deprecated in 1.7.1 */
1368 else if (gnm_xml_attr_int (attrs
, "MarginB", &val
))
1369 ; /* deprecated in 1.7.1 */
1371 unknown_attr (xin
, attrs
);
1374 XML_CHECK (size
> -1);
1375 XML_CHECK (pos
>= 0 && pos
< colrow_max (is_col
, sheet
));
1376 XML_CHECK (count
>= 1);
1377 XML_CHECK (count
<= colrow_max (is_col
, sheet
) - pos
);
1380 ? sheet_col_fetch (state
->sheet
, pos
)
1381 : sheet_row_fetch (state
->sheet
, pos
);
1382 cri
->hard_size
= hard_size
;
1383 cri
->visible
= !hidden
;
1384 cri
->is_collapsed
= is_collapsed
;
1385 cri
->outline_level
= outline_level
;
1388 sheet_col_set_size_pts (state
->sheet
, pos
, size
, cri
->hard_size
);
1389 if (state
->sheet
->cols
.max_outline_level
< cri
->outline_level
)
1390 state
->sheet
->cols
.max_outline_level
= cri
->outline_level
;
1391 /* resize flags are already set only need to copy the sizes */
1393 col_row_info_copy (sheet_col_fetch (state
->sheet
, ++pos
), cri
);
1395 sheet_row_set_size_pts (state
->sheet
, pos
, size
, cri
->hard_size
);
1396 if (state
->sheet
->rows
.max_outline_level
< cri
->outline_level
)
1397 state
->sheet
->rows
.max_outline_level
= cri
->outline_level
;
1398 /* resize flags are already set only need to copy the sizes */
1400 col_row_info_copy (sheet_row_fetch (state
->sheet
, ++pos
), cri
);
1405 xml_sax_style_region_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1407 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1409 g_return_if_fail (state
->style_range_init
== FALSE
);
1410 g_return_if_fail (state
->style
== NULL
);
1412 if (attrs
== NULL
) {
1413 g_warning ("Invalid tag: gnm:StyleRegion start tag without attributes");
1417 state
->style
= (state
->version
>= GNM_XML_V6
||
1418 state
->version
<= GNM_XML_V2
)
1419 ? gnm_style_new_default ()
1422 state
->style_range_init
=
1423 xml_sax_attr_range (attrs
, &state
->style_range
);
1427 xml_sax_style_region_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1429 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1431 if (!state
->style_range_init
) {
1432 xml_sax_barf (G_STRFUNC
, "style region must have range");
1433 range_init (&state
->style_range
, 0, 0, 0, 0);
1434 state
->style_range_init
= TRUE
;
1437 xml_sax_must_have_style (state
);
1438 xml_sax_must_have_sheet (state
);
1440 if (state
->clipboard
) {
1441 GnmCellRegion
*cr
= state
->clipboard
;
1442 GnmStyleRegion
*sr
= g_new (GnmStyleRegion
, 1);
1444 sr
->range
= state
->style_range
;
1445 sr
->style
= state
->style
;
1447 cr
->styles
= g_slist_prepend (cr
->styles
, sr
);
1448 } else if (state
->version
>= GNM_XML_V6
|| state
->version
<= GNM_XML_V2
)
1449 sheet_style_set_range (state
->sheet
, &state
->style_range
,
1452 sheet_style_apply_range (state
->sheet
, &state
->style_range
,
1455 state
->style_range_init
= FALSE
;
1456 state
->style
= NULL
;
1458 maybe_update_progress (xin
);
1462 xml_sax_style_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1464 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1469 xml_sax_must_have_style (state
);
1471 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1472 if (xml_sax_attr_enum (attrs
, "HAlign", GNM_ALIGN_H_TYPE
, &val
))
1473 gnm_style_set_align_h (state
->style
, val
);
1474 else if (xml_sax_attr_enum (attrs
, "VAlign", GNM_ALIGN_V_TYPE
, &val
))
1475 gnm_style_set_align_v (state
->style
, val
);
1477 /* Pre version V6 */
1478 else if (gnm_xml_attr_int (attrs
, "Fit", &val
))
1479 gnm_style_set_wrap_text (state
->style
, val
);
1481 else if (gnm_xml_attr_int (attrs
, "WrapText", &val
))
1482 gnm_style_set_wrap_text (state
->style
, val
);
1483 else if (gnm_xml_attr_bool (attrs
, "ShrinkToFit", &val
))
1484 gnm_style_set_shrink_to_fit (state
->style
, val
);
1485 else if (gnm_xml_attr_int (attrs
, "Rotation", &val
)) {
1486 /* Work around a bug pre 1.5.1 that would allow
1487 * negative rotations. -1 == vertical, map everything
1488 * else back onto 0..359 */
1491 gnm_style_set_rotation (state
->style
, val
);
1492 } else if (gnm_xml_attr_int (attrs
, "Shade", &val
))
1493 gnm_style_set_pattern (state
->style
, val
);
1494 else if (gnm_xml_attr_int (attrs
, "Indent", &val
))
1495 gnm_style_set_indent (state
->style
, val
);
1496 else if (xml_sax_attr_color (attrs
, "Fore", &colour
))
1497 gnm_style_set_font_color (state
->style
, colour
);
1498 else if (xml_sax_attr_color (attrs
, "Back", &colour
))
1499 gnm_style_set_back_color (state
->style
, colour
);
1500 else if (xml_sax_attr_color (attrs
, "PatternColor", &colour
))
1501 gnm_style_set_pattern_color (state
->style
, colour
);
1502 else if (attr_eq (attrs
[0], "Format")) {
1503 GOFormat
*fmt
= make_format (CXML2C (attrs
[1]));
1505 gnm_style_set_format (state
->style
, fmt
);
1506 go_format_unref (fmt
);
1509 else if (gnm_xml_attr_int (attrs
, "Hidden", &val
))
1510 gnm_style_set_contents_hidden (state
->style
, val
);
1511 else if (gnm_xml_attr_int (attrs
, "Locked", &val
))
1512 gnm_style_set_contents_locked (state
->style
, val
);
1513 else if (gnm_xml_attr_int (attrs
, "Orient", &val
))
1514 ; /* ignore old useless attribute */
1516 unknown_attr (xin
, attrs
);
1521 xml_sax_style_font (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1523 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1525 double size_pts
= 10.;
1528 xml_sax_must_have_style (state
);
1530 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1531 if (gnm_xml_attr_double (attrs
, "Unit", &size_pts
)) {
1532 if (!(size_pts
>= 1.0))
1533 xml_sax_barf (G_STRFUNC
, "size_pts >= 1");
1535 gnm_style_set_font_size (state
->style
, size_pts
);
1536 } else if (gnm_xml_attr_int (attrs
, "Bold", &val
))
1537 gnm_style_set_font_bold (state
->style
, val
);
1538 else if (gnm_xml_attr_int (attrs
, "Italic", &val
))
1539 gnm_style_set_font_italic (state
->style
, val
);
1540 else if (gnm_xml_attr_int (attrs
, "Underline", &val
))
1541 gnm_style_set_font_uline (state
->style
, (GnmUnderline
)val
);
1542 else if (gnm_xml_attr_int (attrs
, "StrikeThrough", &val
))
1543 gnm_style_set_font_strike (state
->style
, val
);
1544 else if (gnm_xml_attr_int (attrs
, "Script", &val
)) {
1546 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_STANDARD
);
1548 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_SUB
);
1550 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_SUPER
);
1552 unknown_attr (xin
, attrs
);
1557 font_component (char const *fontname
, int idx
)
1560 char const *p
= fontname
;
1562 for (; *p
&& i
< idx
; p
++) {
1573 * style_font_read_from_x11:
1574 * @mstyle: the style to setup to this font.
1575 * @fontname: an X11-like font name.
1577 * Tries to guess the fontname, the weight and italization parameters
1580 * Returns: A valid style font.
1583 style_font_read_from_x11 (GnmStyle
*mstyle
, char const *fontname
)
1587 /* FIXME: we should do something about the typeface instead
1588 * of hardcoding it to helvetica.
1590 c
= font_component (fontname
, 2);
1591 if (strncmp (c
, "bold", 4) == 0)
1592 gnm_style_set_font_bold (mstyle
, TRUE
);
1594 c
= font_component (fontname
, 3);
1595 if (strncmp (c
, "o", 1) == 0)
1596 gnm_style_set_font_italic (mstyle
, TRUE
);
1598 if (strncmp (c
, "i", 1) == 0)
1599 gnm_style_set_font_italic (mstyle
, TRUE
);
1603 xml_sax_style_font_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1605 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1607 xml_sax_must_have_style (state
);
1609 if (xin
->content
->len
> 0) {
1610 char const * content
= xin
->content
->str
;
1611 if (*content
== '-')
1612 style_font_read_from_x11 (state
->style
, content
);
1614 gnm_style_set_font_name (state
->style
, content
);
1619 xml_sax_validation (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1621 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1626 g_return_if_fail (state
->validation
.title
== NULL
);
1627 g_return_if_fail (state
->validation
.msg
== NULL
);
1628 g_return_if_fail (state
->validation
.texpr
[0] == NULL
);
1629 g_return_if_fail (state
->validation
.texpr
[1] == NULL
);
1631 state
->validation
.style
= GNM_VALIDATION_STYLE_NONE
;
1632 state
->validation
.type
= GNM_VALIDATION_TYPE_ANY
;
1633 state
->validation
.op
= GNM_VALIDATION_OP_NONE
;
1634 state
->validation
.allow_blank
= TRUE
;
1635 state
->validation
.use_dropdown
= FALSE
;
1637 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1638 if (xml_sax_attr_enum (attrs
, "Style",
1639 GNM_VALIDATION_STYLE_TYPE
,
1641 state
->validation
.style
= dummy
;
1642 } else if (xml_sax_attr_enum (attrs
, "Type",
1643 GNM_VALIDATION_TYPE_TYPE
,
1645 state
->validation
.type
= dummy
;
1646 } else if (xml_sax_attr_enum (attrs
, "Operator",
1647 GNM_VALIDATION_OP_TYPE
,
1649 state
->validation
.op
= dummy
;
1650 } else if (attr_eq (attrs
[0], "Title")) {
1651 state
->validation
.title
= g_strdup (CXML2C (attrs
[1]));
1652 } else if (attr_eq (attrs
[0], "Message")) {
1653 state
->validation
.msg
= g_strdup (CXML2C (attrs
[1]));
1654 } else if (gnm_xml_attr_bool (attrs
, "AllowBlank", &b_dummy
)) {
1655 state
->validation
.allow_blank
= b_dummy
;
1656 } else if (gnm_xml_attr_bool (attrs
, "UseDropdown", &b_dummy
)) {
1657 state
->validation
.use_dropdown
= b_dummy
;
1659 unknown_attr (xin
, attrs
);
1664 xml_sax_validation_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1666 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1668 xml_sax_must_have_style (state
);
1670 gnm_style_set_validation (state
->style
,
1671 gnm_validation_new (state
->validation
.style
,
1672 state
->validation
.type
,
1673 state
->validation
.op
,
1675 state
->validation
.title
,
1676 state
->validation
.msg
,
1677 state
->validation
.texpr
[0],
1678 state
->validation
.texpr
[1],
1679 state
->validation
.allow_blank
,
1680 state
->validation
.use_dropdown
));
1682 g_free (state
->validation
.title
);
1683 state
->validation
.title
= NULL
;
1684 g_free (state
->validation
.msg
);
1685 state
->validation
.msg
= NULL
;
1686 state
->validation
.texpr
[0] = state
->validation
.texpr
[1] = NULL
;
1690 xml_sax_validation_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1692 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1694 int const i
= xin
->node
->user_data
.v_int
;
1695 GnmExprTop
const *texpr
;
1698 g_return_if_fail (state
->validation
.texpr
[i
] == NULL
);
1700 texpr
= gnm_expr_parse_str (xin
->content
->str
,
1701 parse_pos_init_sheet (&pos
, state
->sheet
),
1702 GNM_EXPR_PARSE_DEFAULT
,
1706 g_return_if_fail (texpr
!= NULL
);
1708 state
->validation
.texpr
[i
] = texpr
;
1712 xml_sax_condition (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1714 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1715 GnmStyleCondOp op
= GNM_STYLE_COND_CUSTOM
;
1717 g_return_if_fail (state
->cond
== NULL
);
1718 g_return_if_fail (state
->cond_save_style
== NULL
);
1720 xml_sax_must_have_style (state
);
1722 state
->cond_save_style
= state
->style
;
1723 state
->style
= gnm_style_new ();
1725 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1728 if (gnm_xml_attr_int (attrs
, "Operator", &dummy
))
1731 unknown_attr (xin
, attrs
);
1734 state
->cond
= gnm_style_cond_new (op
, state
->sheet
);
1738 xml_sax_condition_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1740 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1741 GnmStyleConditions
*sc
;
1743 xml_sax_must_have_style (state
);
1744 g_return_if_fail (state
->cond_save_style
!= NULL
);
1745 g_return_if_fail (state
->cond
!= NULL
);
1747 gnm_style_cond_set_overlay (state
->cond
, state
->style
);
1748 gnm_style_unref (state
->style
);
1749 state
->style
= state
->cond_save_style
;
1750 state
->cond_save_style
= NULL
;
1752 if (!gnm_style_is_element_set (state
->style
, MSTYLE_CONDITIONS
) ||
1753 NULL
== (sc
= gnm_style_get_conditions (state
->style
)))
1754 gnm_style_set_conditions (state
->style
,
1755 (sc
= gnm_style_conditions_new (state
->sheet
)));
1756 gnm_style_conditions_insert (sc
, state
->cond
, -1);
1758 gnm_style_cond_free (state
->cond
);
1763 * We have been saving expressions relative to A1. This means that when we
1764 * read, we see a relative reference to a cell above as R[65535]C. This
1765 * function patches that to R[-1]C.
1767 * We ought to fix the format, but then old Gnumerics couldn't read new
1768 * files. In fact, if we just added a "Position" attribute then we would
1769 * get silent corruption.
1771 static GnmExpr
const *
1772 cond_patchup (GnmExpr
const *expr
, GnmExprWalk
*data
)
1774 XMLSaxParseState
*state
= data
->user
;
1775 GnmCellPos
const *pos
= &state
->style_range
.start
;
1776 GnmCellRef
const *oref
= gnm_expr_get_cellref (expr
);
1777 GnmValue
const *ocst
= gnm_expr_get_constant (expr
);
1781 GnmCellRef tref
= *oref
;
1782 gnm_cellpos_init_cellref (&tpos
, oref
, pos
, state
->sheet
);
1783 if (tref
.col_relative
)
1784 tref
.col
= tpos
.col
- pos
->col
;
1785 if (tref
.row_relative
)
1786 tref
.row
= tpos
.row
- pos
->row
;
1787 if (gnm_cellref_equal (&tref
, oref
))
1789 return gnm_expr_new_cellref (&tref
);
1792 if (ocst
&& VALUE_IS_CELLRANGE (ocst
)) {
1793 GnmRangeRef
const *oref
= value_get_rangeref (ocst
);
1794 GnmRangeRef tref
= *oref
;
1796 Sheet
*start_sheet
, *end_sheet
;
1799 eval_pos_init_pos (&ep
, state
->sheet
, pos
);
1800 gnm_rangeref_normalize (oref
, &ep
, &start_sheet
, &end_sheet
,
1802 if (tref
.a
.col_relative
)
1803 tref
.a
.col
= trange
.start
.col
- pos
->col
;
1804 if (tref
.a
.row_relative
)
1805 tref
.a
.row
= trange
.start
.row
- pos
->row
;
1806 if (tref
.b
.col_relative
)
1807 tref
.b
.col
= trange
.end
.col
- pos
->col
;
1808 if (tref
.b
.row_relative
)
1809 tref
.b
.row
= trange
.end
.row
- pos
->row
;
1810 if (gnm_rangeref_equal (&tref
, oref
))
1812 return gnm_expr_new_constant (value_new_cellrange_unsafe (&tref
.a
, &tref
.b
));
1819 xml_sax_condition_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1821 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1823 int const i
= xin
->node
->user_data
.v_int
;
1824 GnmExprTop
const *texpr
;
1826 GnmExpr
const *patched_expr
;
1828 g_return_if_fail (gnm_style_cond_get_expr (state
->cond
, i
) == NULL
);
1830 parse_pos_init_sheet (&pos
, state
->sheet
);
1831 texpr
= gnm_expr_parse_str (xin
->content
->str
,
1833 GNM_EXPR_PARSE_DEFAULT
,
1836 g_return_if_fail (texpr
!= NULL
);
1838 patched_expr
= gnm_expr_walk (texpr
->expr
, cond_patchup
, state
);
1840 gnm_expr_top_unref (texpr
);
1841 texpr
= gnm_expr_top_new (patched_expr
);
1844 gnm_style_cond_set_expr (state
->cond
, texpr
, i
);
1845 gnm_expr_top_unref (texpr
);
1849 xml_sax_hlink (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1851 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1853 char *target
= NULL
;
1856 xml_sax_must_have_style (state
);
1858 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1859 if (attr_eq (attrs
[0], "type"))
1860 type
= g_strdup (CXML2C (attrs
[1]));
1861 else if (attr_eq (attrs
[0], "target"))
1862 target
= g_strdup (CXML2C (attrs
[1]));
1863 else if (attr_eq (attrs
[0], "tip"))
1864 tip
= g_strdup (CXML2C (attrs
[1]));
1866 unknown_attr (xin
, attrs
);
1869 if (NULL
!= type
&& NULL
!= target
) {
1870 GType typ
= g_type_from_name (type
);
1871 GnmHLink
*lnk
= gnm_hlink_new (typ
, state
->sheet
);
1872 gnm_hlink_set_target (lnk
, target
);
1873 gnm_hlink_set_tip (lnk
, tip
);
1874 gnm_style_set_hlink (state
->style
, lnk
);
1883 xml_sax_input_msg (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1885 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1889 xml_sax_must_have_style (state
);
1891 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1892 if (attr_eq (attrs
[0], "Title"))
1893 title
= g_strdup (CXML2C (attrs
[1]));
1894 else if (attr_eq (attrs
[0], "Message"))
1895 msg
= g_strdup (CXML2C (attrs
[1]));
1897 unknown_attr (xin
, attrs
);
1900 if (NULL
!= title
|| NULL
!= msg
)
1901 gnm_style_set_input_msg (state
->style
,
1902 gnm_input_msg_new (msg
, title
));
1908 xml_sax_style_border (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1910 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1913 GnmColor
*colour
= NULL
;
1915 xml_sax_must_have_style (state
);
1917 /* Colour is optional */
1918 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1919 if (xml_sax_attr_color (attrs
, "Color", &colour
)) ;
1920 else if (gnm_xml_attr_int (attrs
, "Style", &pattern
)) ;
1922 unknown_attr (xin
, attrs
);
1925 if (pattern
>= GNM_STYLE_BORDER_NONE
) {
1926 GnmStyleElement
const type
= xin
->node
->user_data
.v_int
;
1927 GnmStyleBorderLocation
const loc
=
1928 GNM_STYLE_BORDER_TOP
+ (int)(type
- MSTYLE_BORDER_TOP
);
1932 * Make sure we have a colour to prevent trouble further
1936 colour
= gnm_color_new_go (GO_COLOR_BLACK
);
1938 border
= gnm_style_border_fetch
1939 ((GnmStyleBorderType
)pattern
, colour
,
1940 gnm_style_border_get_orientation (loc
));
1941 gnm_style_set_border (state
->style
, type
, border
);
1946 xml_sax_cell (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1948 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1949 Sheet
*sheet
= state
->sheet
;
1951 int row
= -1, col
= -1;
1952 int rows
= -1, cols
= -1;
1953 int value_type
= -1;
1954 GOFormat
*value_fmt
= NULL
;
1956 const char *value_result
= NULL
;
1958 g_return_if_fail (state
->cell
.row
== -1);
1959 g_return_if_fail (state
->cell
.col
== -1);
1960 g_return_if_fail (state
->array_rows
== -1);
1961 g_return_if_fail (state
->array_cols
== -1);
1962 g_return_if_fail (state
->expr_id
== -1);
1963 g_return_if_fail (state
->value_type
== -1);
1964 g_return_if_fail (state
->value_result
== NULL
);
1966 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1967 if (gnm_xml_attr_int (attrs
, "Col", &col
)) ;
1968 else if (gnm_xml_attr_int (attrs
, "Row", &row
)) ;
1969 else if (gnm_xml_attr_int (attrs
, "Cols", &cols
)) ;
1970 else if (gnm_xml_attr_int (attrs
, "Rows", &rows
)) ;
1971 else if (gnm_xml_attr_int (attrs
, "ExprID", &expr_id
)) ;
1972 else if (gnm_xml_attr_int (attrs
, "ValueType", &value_type
)) ;
1973 else if (attr_eq (attrs
[0], "Value"))
1974 value_result
= CXML2C (attrs
[1]);
1975 else if (attr_eq (attrs
[0], "ValueFormat")) {
1976 go_format_unref (value_fmt
);
1977 value_fmt
= make_format (CXML2C (attrs
[1]));
1979 unknown_attr (xin
, attrs
);
1982 // Ignore value_result absent a type
1983 if (value_type
== -1)
1984 value_result
= NULL
;
1986 XML_CHECK2 (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
),
1987 go_format_unref (value_fmt
));
1988 XML_CHECK2 (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
),
1989 go_format_unref (value_fmt
));
1991 if (cols
> 0 || rows
> 0) {
1992 /* Both must be valid */
1993 XML_CHECK2 (cols
> 0 && rows
> 0,
1994 go_format_unref (value_fmt
));
1996 state
->array_cols
= cols
;
1997 state
->array_rows
= rows
;
2000 state
->cell
.row
= row
;
2001 state
->cell
.col
= col
;
2002 state
->expr_id
= expr_id
;
2003 state
->value_type
= value_type
;
2004 state
->value_fmt
= value_fmt
;
2005 state
->value_result
= g_strdup (value_result
);
2009 * xml_cell_set_array_expr : Utility routine to parse an expression
2010 * and store it as an array.
2012 * @cell: The upper left hand corner of the array.
2013 * @text: The text to parse.
2014 * @rows: The number of rows.
2015 * @cols: The number of columns.
2018 xml_cell_set_array_expr (XMLSaxParseState
*state
,
2019 GnmCell
*cell
, GnmCellCopy
*cc
, char const *text
,
2020 int const cols
, int const rows
)
2023 GnmExprTop
const *texpr
=
2024 gnm_expr_parse_str (text
,
2025 parse_pos_init_cell (&pp
, cell
),
2026 GNM_EXPR_PARSE_DEFAULT
,
2031 g_return_if_fail (texpr
!= NULL
);
2038 r
.start
= r
.end
= cell
->pos
;
2039 r
.end
.col
+= (cols
- 1);
2040 r
.end
.row
+= (rows
- 1);
2042 if (!gnm_cell_set_array (cell
->base
.sheet
, &r
, texpr
)) {
2043 xml_sax_barf (G_STRFUNC
, "target area empty");
2046 gnm_expr_top_unref (texpr
);
2050 * xml_not_used_old_array_spec : See if the string corresponds to
2051 * a pre-0.53 style array expression.
2052 * If it is the upper left corner - assign it.
2053 * If it is a member of an array - ignore it; the corner will assign it.
2054 * If it is not a member of an array return TRUE.
2057 xml_not_used_old_array_spec (XMLSaxParseState
*state
,
2058 GnmCell
*cell
, GnmCellCopy
*cc
,
2059 char const *content
)
2061 long rows
, cols
, row
, col
;
2062 char *end
, *expr_end
, *ptr
;
2064 /* This is the syntax we are trying to parse: "{%s}(%d,%d)[%d][%d]" */
2066 if (content
[0] != '=' || content
[1] != '{')
2069 expr_end
= strrchr (content
, '}');
2070 if (expr_end
== NULL
|| expr_end
[1] != '(')
2073 rows
= strtol (ptr
= expr_end
+ 2, &end
, 10);
2074 if (end
== ptr
|| *end
!= ',')
2076 cols
= strtol (ptr
= end
+ 1, &end
, 10);
2077 if (end
== ptr
|| end
[0] != ')' || end
[1] != '[')
2079 row
= strtol (ptr
= end
+ 2, &end
, 10);
2080 if (end
== ptr
|| end
[0] != ']' || end
[1] != '[')
2082 col
= strtol (ptr
= end
+ 2, &end
, 10);
2083 if (end
== ptr
|| end
[0] != ']' || end
[1] != '\0')
2086 if (row
== 0 && col
== 0) {
2088 xml_cell_set_array_expr (state
, cell
, cc
,
2089 content
+ 2, rows
, cols
);
2096 xml_sax_cell_content (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2098 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2099 Sheet
*sheet
= state
->sheet
;
2101 gboolean is_new_cell
= FALSE
, is_post_52_array
= FALSE
;
2104 GnmCell
*cell
= NULL
; /* Regular case */
2105 GnmCellCopy
*cc
= NULL
; /* Clipboard case */
2106 GnmCellRegion
*cr
= state
->clipboard
;
2107 GnmExprTop
const *texpr
= NULL
;
2109 char const *content
= xin
->content
->str
;
2110 gboolean has_contents
= (xin
->content
->len
> 0);
2111 const char *expr_start
= gnm_expr_char_start_p (content
);
2113 int const col
= state
->cell
.col
;
2114 int const row
= state
->cell
.row
;
2115 int const array_cols
= state
->array_cols
;
2116 int const array_rows
= state
->array_rows
;
2117 int expr_id
= state
->expr_id
;
2118 int const value_type
= state
->value_type
;
2119 gboolean
const seen_contents
= state
->seen_cell_contents
;
2120 GOFormat
*value_fmt
= state
->value_fmt
;
2121 char *value_result
= state
->value_result
;
2123 /* Clean out the state before any error checking */
2124 state
->cell
.row
= state
->cell
.col
= -1;
2125 state
->array_rows
= state
->array_cols
= -1;
2126 state
->expr_id
= -1;
2127 state
->value_type
= -1;
2128 state
->value_fmt
= NULL
;
2129 state
->value_result
= NULL
;
2130 state
->seen_cell_contents
= strcmp (xin
->node
->id
, "CELL_CONTENT") == 0;
2135 XML_CHECK (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
));
2136 XML_CHECK (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
));
2138 maybe_update_progress (xin
);
2141 cc
= gnm_cell_copy_new (cr
,
2143 row
- cr
->base
.row
);
2144 parse_pos_init (&pos
, NULL
, sheet
, col
, row
);
2146 cell
= sheet_cell_get (sheet
, col
, row
);
2147 is_new_cell
= (cell
== NULL
);
2149 cell
= sheet_cell_create (sheet
, col
, row
);
2153 parse_pos_init_cell (&pos
, cell
);
2156 // ----------------------------------------
2158 is_post_52_array
= (array_cols
> 0) && (array_rows
> 0);
2159 if (is_post_52_array
&& has_contents
) {
2161 g_return_if_fail (content
[0] == '=');
2162 xml_cell_set_array_expr (state
, cell
, cc
, content
+ 1,
2163 array_cols
, array_rows
);
2164 texpr
= cell
->base
.texpr
;
2165 if (texpr
) gnm_expr_top_ref (texpr
);
2169 // ----------------------------------------
2171 if (has_contents
&& state
->version
< GNM_XML_V3
&&
2172 !xml_not_used_old_array_spec (state
, cell
, cc
, content
)) {
2173 // Very old array syntax -- irrelevant
2177 // ----------------------------------------
2179 if (!has_contents
&& expr_id
> 0) {
2180 // Re-use of expression id
2181 texpr
= g_hash_table_lookup (state
->expr_map
,
2182 GINT_TO_POINTER (expr_id
));
2184 if (texpr
&& gnm_expr_top_is_array_corner (texpr
)) {
2185 g_printerr ("Shared array formula for %s -- how did that happen?\n",
2186 cell
? cell_name (cell
) : "clipboard");
2187 texpr
= gnm_expr_top_new (gnm_expr_copy (texpr
->expr
));
2190 gnm_expr_top_ref (texpr
);
2193 char *msg
= g_strdup_printf
2194 ("Looking up shared expression id %d",
2196 char *s
= g_strdup_printf ("<shared expression %d>", expr_id
);
2197 xml_sax_barf (G_STRFUNC
, msg
);
2200 texpr
= gnm_expr_top_new_constant (value_new_string_nocopy (s
));
2202 goto assign_and_done
;
2205 // ----------------------------------------
2207 if (value_type
> 0) {
2209 gboolean from_content
= (value_result
== NULL
);
2210 const char *txt
= from_content
? content
: value_result
;
2211 v
= value_new_from_string (value_type
, txt
, value_fmt
, FALSE
);
2213 char *msg
= g_strdup_printf
2214 ("Parsing \"%s\" as type 0x%x",
2216 xml_sax_barf (G_STRFUNC
, msg
);
2218 v
= value_new_string (txt
);
2221 // If we consumed the contents as a value, then it's not
2227 value_set_fmt (v
, value_fmt
);
2231 // ----------------------------------------
2233 if (expr_start
&& *expr_start
) {
2236 parse_error_init (&perr
);
2237 texpr
= gnm_expr_parse_str (expr_start
,
2239 GNM_EXPR_PARSE_DEFAULT
,
2242 // Don't warn in the clipboard case.
2243 // It's probably an unknown sheet ref
2245 g_warning ("Unparsable expression for %s: %s (%s)\n",
2246 cell
? cell_name (cell
) : "-",
2250 texpr
= gnm_expr_top_new_constant (value_new_string (expr_start
));
2251 parse_error_free (&perr
);
2254 gpointer id
= GINT_TO_POINTER (expr_id
);
2255 GnmExprTop
const *texpr0
=
2256 g_hash_table_lookup (state
->expr_map
, id
);
2258 if (!is_post_52_array
)
2259 g_warning ("XML-IO: Duplicate shared expression");
2267 v
= value_new_empty ();
2268 // When we get here:
2269 // 1. We own a ref to texpr (or it's NULL)
2270 // 2. We own v. After this section we no longer own v.
2274 gnm_cell_set_expr_and_value (cell
, texpr
, v
, TRUE
);
2276 gnm_cell_set_value (cell
, v
);
2279 cc
->texpr
= texpr
? gnm_expr_top_ref (texpr
) : NULL
;
2285 // We own a ref to texpr at this point. Store or discard.
2287 g_hash_table_insert (state
->expr_map
,
2288 GINT_TO_POINTER (expr_id
),
2291 gnm_expr_top_unref (texpr
);
2295 go_format_unref (value_fmt
);
2296 g_free (value_result
);
2300 xml_sax_merge (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2302 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2303 GnmCellRegion
*cr
= state
->clipboard
;
2304 Sheet
*sheet
= state
->sheet
;
2307 g_return_if_fail (xin
->content
->len
> 0);
2309 if (range_parse (&r
, xin
->content
->str
, gnm_sheet_get_size (sheet
))) {
2311 cr
->merged
= g_slist_prepend (cr
->merged
,
2312 gnm_range_dup (&r
));
2314 gnm_sheet_merge_add (sheet
, &r
, FALSE
,
2315 GO_CMD_CONTEXT (state
->context
));
2321 xml_sax_filter_operator (XMLSaxParseState
*state
,
2322 GnmFilterOp
*op
, xmlChar
const *str
)
2324 static char const *filter_cond_name
[] = { "eq", "gt", "lt", "gte", "lte", "ne" };
2327 for (i
= G_N_ELEMENTS (filter_cond_name
); i
-- ; )
2328 if (0 == g_ascii_strcasecmp (CXML2C (str
), filter_cond_name
[i
])) {
2333 go_io_warning (state
->context
, _("Unknown filter operator \"%s\""), str
);
2337 xml_sax_filter_condition (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2339 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2340 char const *type
= NULL
;
2341 char const *val0
= NULL
;
2342 char const *val1
= NULL
;
2343 GnmValueType vtype0
= VALUE_EMPTY
, vtype1
= VALUE_EMPTY
;
2344 GnmFilterOp op0
= GNM_FILTER_UNUSED
, op1
= GNM_FILTER_UNUSED
;
2345 GnmFilterCondition
*cond
= NULL
;
2346 gboolean top
= TRUE
, items
= TRUE
, is_and
= FALSE
;
2347 int i
, tmp
, cond_num
= 0;
2348 double bucket_count
= 10.;
2350 if (NULL
== state
->filter
) return;
2352 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2) {
2353 if (attr_eq (attrs
[i
], "Type")) type
= CXML2C (attrs
[i
+ 1]);
2354 else if (gnm_xml_attr_int (attrs
+i
, "Index", &cond_num
)) ;
2355 else if (gnm_xml_attr_bool (attrs
, "Top", &top
)) ;
2356 else if (gnm_xml_attr_bool (attrs
, "Items", &items
)) ;
2357 else if (gnm_xml_attr_double (attrs
, "Count", &bucket_count
)) ;
2358 else if (gnm_xml_attr_bool (attrs
, "IsAnd", &is_and
)) ;
2359 else if (attr_eq (attrs
[i
], "Op0")) xml_sax_filter_operator (state
, &op0
, attrs
[i
+ 1]);
2360 else if (attr_eq (attrs
[i
], "Op1")) xml_sax_filter_operator (state
, &op1
, attrs
[i
+ 1]);
2362 * WARNING WARNING WARING
2363 * Value and ValueType are _reversed_ !!!
2364 * An error in the DOM exporter was propogated to the SAX
2365 * exporter and fixing this reversal would break all old files.
2367 else if (attr_eq (attrs
[i
], "ValueType0")) val0
= CXML2C (attrs
[i
+ 1]);
2368 else if (attr_eq (attrs
[i
], "ValueType1")) val1
= CXML2C (attrs
[i
+ 1]);
2369 else if (gnm_xml_attr_int (attrs
+i
, "Value0", &tmp
)) vtype0
= tmp
;
2370 else if (gnm_xml_attr_int (attrs
+i
, "Value1", &tmp
)) vtype1
= tmp
;
2374 go_io_warning (state
->context
, _("Missing filter type"));
2375 } else if (0 == g_ascii_strcasecmp (type
, "expr")) {
2376 GnmValue
*v0
= NULL
, *v1
= NULL
;
2377 if (val0
&& vtype0
!= VALUE_EMPTY
&& op0
!= GNM_FILTER_UNUSED
)
2378 v0
= value_new_from_string (vtype0
, val0
, NULL
, FALSE
);
2379 if (val1
&& vtype1
!= VALUE_EMPTY
&& op1
!= GNM_FILTER_UNUSED
)
2380 v1
= value_new_from_string (vtype1
, val1
, NULL
, FALSE
);
2382 cond
= gnm_filter_condition_new_double (
2383 op0
, v0
, is_and
, op1
, v1
);
2385 cond
= gnm_filter_condition_new_single (op0
, v0
);
2387 go_io_warning (state
->context
, _("Malformed sheet filter condition"));
2391 } else if (0 == g_ascii_strcasecmp (type
, "blanks")) {
2392 cond
= gnm_filter_condition_new_single (
2393 GNM_FILTER_OP_BLANKS
, NULL
);
2394 } else if (0 == g_ascii_strcasecmp (type
, "noblanks")) {
2395 cond
= gnm_filter_condition_new_single (
2396 GNM_FILTER_OP_NON_BLANKS
, NULL
);
2397 } else if (0 == g_ascii_strcasecmp (type
, "bucket")) {
2398 cond
= gnm_filter_condition_new_bucket
2399 (top
, items
, TRUE
, bucket_count
);
2401 go_io_warning (state
->context
, _("Unknown filter type \"%s\""), type
);
2404 gnm_filter_set_condition (state
->filter
, cond_num
, cond
, FALSE
);
2408 xml_sax_filter_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2410 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2414 xml_sax_must_have_sheet (state
);
2415 g_return_if_fail (state
->filter
== NULL
);
2417 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2)
2418 if (attr_eq (attrs
[i
], "Area") &&
2419 range_parse (&r
, CXML2C (attrs
[i
+ 1]), gnm_sheet_get_size (state
->sheet
)))
2420 state
->filter
= gnm_filter_new (state
->sheet
, &r
);
2421 if (NULL
== state
->filter
)
2422 go_io_warning (state
->context
, _("Invalid filter, missing Area"));
2426 xml_sax_filter_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2428 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2429 state
->filter
= NULL
;
2433 xml_sax_read_obj (GsfXMLIn
*xin
, gboolean needs_cleanup
,
2434 char const *type_name
, xmlChar
const **attrs
)
2436 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2439 SheetObjectClass
*klass
;
2441 GODrawingAnchorDir anchor_dir
;
2442 GnmSOAnchorMode anchor_mode
;
2443 SheetObjectAnchor anchor
;
2444 double f_tmp
[4], *anchor_offset
= NULL
;
2446 g_return_if_fail (state
->so
== NULL
);
2449 if (!strcmp (type_name
, "Rectangle"))
2450 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2451 else if (!strcmp (type_name
, "Ellipse"))
2452 so
= g_object_new (GNM_SO_FILLED_TYPE
, "is-oval", TRUE
, NULL
);
2453 else if (!strcmp (type_name
, "Line"))
2454 so
= g_object_new (GNM_SO_LINE_TYPE
, NULL
);
2455 else if (!strcmp (type_name
, "Arrow")) {
2457 go_arrow_init_kite (&arrow
, 8., 10., 3.);
2458 so
= g_object_new (GNM_SO_LINE_TYPE
,
2459 "end-arrow", &arrow
,
2463 /* Class renamed between 1.0.x and 1.2.x */
2464 else if (!strcmp (type_name
, "GnmGraph"))
2465 so
= sheet_object_graph_new (NULL
);
2467 /* Class renamed in 1.2.2 */
2468 else if (!strcmp (type_name
, "CellComment"))
2469 so
= g_object_new (cell_comment_get_type (), NULL
);
2471 /* Class renamed in 1.3.91 */
2472 else if (!strcmp (type_name
, "SheetObjectGraphic"))
2473 so
= g_object_new (GNM_SO_LINE_TYPE
, NULL
);
2474 else if (!strcmp (type_name
, "SheetObjectFilled"))
2475 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2476 else if (!strcmp (type_name
, "SheetObjectText"))
2477 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2478 else if (!strcmp (type_name
, "SheetObjectComponent"))
2479 so
= sheet_object_component_new (NULL
);
2480 else if (!strcmp (type_name
, "SheetObjectPath"))
2481 so
= g_object_new (GNM_SO_PATH_TYPE
, NULL
);
2484 GType type
= g_type_from_name (type_name
);
2486 if (type
== 0 || !g_type_is_a (type
, GNM_SO_TYPE
)) {
2487 char *str
= g_strdup_printf (_("Unsupported object type '%s'"),
2489 go_io_warning_unsupported_feature (state
->context
, str
);
2494 so
= g_object_new (type
, NULL
);
2499 g_return_if_fail (so
!= NULL
);
2500 klass
= GNM_SO_CLASS (G_OBJECT_GET_CLASS (so
));
2501 g_return_if_fail (klass
!= NULL
);
2505 anchor_dir
= GOD_ANCHOR_DIR_UNKNOWN
;
2506 anchor_mode
= GNM_SO_ANCHOR_TWO_CELLS
;
2507 /* Provide a default. */
2508 anchor_r
= sheet_object_get_anchor (so
)->cell_bound
;
2510 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2) {
2511 if (attr_eq (attrs
[i
], "Name"))
2512 sheet_object_set_name (so
, CXML2C (attrs
[i
+ 1]));
2513 else if (xml_sax_attr_enum (attrs
+ i
, "AnchorMode", GNM_SHEET_OBJECT_ANCHOR_MODE_TYPE
, &tmp_int
))
2514 anchor_mode
= tmp_int
;
2515 else if (attr_eq (attrs
[i
], "ObjectBound"))
2516 range_parse (&anchor_r
, CXML2C (attrs
[i
+ 1]), gnm_sheet_get_size (state
->sheet
));
2517 else if (attr_eq (attrs
[i
], "ObjectOffset") &&
2518 4 == sscanf (CXML2C (attrs
[i
+ 1]), "%lg %lg %lg %lg",
2519 f_tmp
+ 0, f_tmp
+ 1, f_tmp
+ 2, f_tmp
+ 3))
2520 anchor_offset
= f_tmp
;
2521 else if (gnm_xml_attr_int (attrs
+i
, "Direction", &tmp_int
))
2522 anchor_dir
= tmp_int
;
2523 else if (gnm_xml_attr_int (attrs
+i
, "Print", &tmp_int
)) {
2524 gboolean b
= (tmp_int
!= 0);
2525 sheet_object_set_print_flag (so
, &b
);
2529 /* Patch problems introduced in some 1.7.x versions that stored
2530 * comments in merged cells with the full rectangle of the merged cell
2531 * rather than just the top left corner */
2532 if (G_OBJECT_TYPE (so
) == GNM_CELL_COMMENT_TYPE
)
2533 anchor_r
.end
= anchor_r
.start
;
2535 sheet_object_anchor_init (&anchor
, &anchor_r
, anchor_offset
, anchor_dir
, anchor_mode
);
2536 sheet_object_set_anchor (so
, &anchor
);
2538 if (NULL
!= klass
->prep_sax_parser
)
2539 (klass
->prep_sax_parser
) (so
, xin
, attrs
, state
->convs
);
2540 if (needs_cleanup
) {
2541 /* Put in something to get gnm_xml_finish_obj called */
2542 static GsfXMLInNode
const dtd
[] = {
2543 GSF_XML_IN_NODE (STYLE
, STYLE
, -1, "", GSF_XML_NO_CONTENT
, NULL
, NULL
),
2546 static GsfXMLInDoc
*doc
= NULL
;
2548 doc
= gsf_xml_in_doc_new (dtd
, NULL
);
2549 gnm_xml_in_doc_dispose_on_exit (&doc
);
2551 /* we need to pas state there because xin->user_state might have
2552 changed, see #751217 */
2553 gsf_xml_in_push_state (xin
, doc
, state
,
2554 (GsfXMLInExtDtor
) gnm_xml_finish_obj
, attrs
);
2559 xml_sax_object_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2561 char const *type_name
= xin
->node
->name
;
2562 maybe_update_progress (xin
);
2563 xml_sax_read_obj (xin
, FALSE
, type_name
, attrs
);
2567 xml_sax_object_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2569 gnm_xml_finish_obj (xin
, xin
->user_state
);
2571 * WARNING: the object is not completely finished at this
2572 * time. Any handler installed by gog_object_sax_push_parser
2573 * has not yet been called. As a consequence, we cannot
2574 * update the GUI here.
2579 parse_constraint_side (const char *s
, const GnmParsePos
*pp
)
2581 GODateConventions
const *date_conv
= sheet_date_conv (pp
->sheet
);
2582 GnmValue
*v
= format_match_number (s
, NULL
, date_conv
);
2585 GnmExprParseFlags flags
= GNM_EXPR_PARSE_DEFAULT
;
2586 v
= value_new_cellrange_parsepos_str (pp
, s
, flags
);
2593 xml_sax_solver_constr_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2596 GnmSolverConstraint
*c
;
2597 Sheet
*sheet
= gnm_xml_in_cur_sheet (xin
);
2598 GnmSolverParameters
*sp
= sheet
->solver_parameters
;
2599 int lhs_col
= 0, lhs_row
= 0, rhs_col
= 0, rhs_row
= 0;
2600 int cols
= 1, rows
= 1;
2601 gboolean old
= FALSE
;
2604 c
= gnm_solver_constraint_new (sheet
);
2606 parse_pos_init_sheet (&pp
, sheet
);
2608 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2609 if (gnm_xml_attr_int (attrs
, "Lcol", &lhs_col
) ||
2610 gnm_xml_attr_int (attrs
, "Lrow", &lhs_row
) ||
2611 gnm_xml_attr_int (attrs
, "Rcol", &rhs_col
) ||
2612 gnm_xml_attr_int (attrs
, "Rrow", &rhs_row
) ||
2613 gnm_xml_attr_int (attrs
, "Cols", &cols
) ||
2614 gnm_xml_attr_int (attrs
, "Rows", &rows
))
2616 else if (gnm_xml_attr_int (attrs
, "Type", &type
))
2618 else if (attr_eq (attrs
[0], "lhs")) {
2619 GnmValue
*v
= parse_constraint_side (CXML2C (attrs
[1]),
2621 gnm_solver_constraint_set_lhs (c
, v
);
2622 } else if (attr_eq (attrs
[0], "rhs")) {
2623 GnmValue
*v
= parse_constraint_side (CXML2C (attrs
[1]),
2625 gnm_solver_constraint_set_rhs (c
, v
);
2631 case 1: c
->type
= GNM_SOLVER_LE
; break;
2632 case 2: c
->type
= GNM_SOLVER_GE
; break;
2633 case 4: c
->type
= GNM_SOLVER_EQ
; break;
2634 case 8: c
->type
= GNM_SOLVER_INTEGER
; break;
2635 case 16: c
->type
= GNM_SOLVER_BOOLEAN
; break;
2639 gnm_solver_constraint_set_old (c
, c
->type
,
2644 sp
->constraints
= g_slist_append (sp
->constraints
, c
);
2648 xml_sax_solver_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2650 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2652 GnmSolverParameters
*sp
;
2653 int col
= -1, row
= -1;
2656 gboolean old
= FALSE
;
2658 xml_sax_must_have_sheet (state
);
2659 sheet
= gnm_xml_in_cur_sheet (xin
);
2660 sp
= sheet
->solver_parameters
;
2662 parse_pos_init_sheet (&pp
, sheet
);
2664 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2665 if (gnm_xml_attr_int (attrs
, "ModelType", &mtype
)) {
2666 sp
->options
.model_type
= (GnmSolverModelType
)mtype
;
2667 } else if (gnm_xml_attr_int (attrs
, "ProblemType", &ptype
)) {
2668 sp
->problem_type
= (GnmSolverProblemType
)ptype
;
2669 } else if (attr_eq (attrs
[0], "Inputs")) {
2670 GnmValue
*v
= value_new_cellrange_parsepos_str
2673 GNM_EXPR_PARSE_DEFAULT
);
2674 gnm_solver_param_set_input (sp
, v
);
2675 } else if (gnm_xml_attr_int (attrs
, "TargetCol", &col
) ||
2676 gnm_xml_attr_int (attrs
, "TargetRow", &row
)) {
2678 } else if (attr_eq (attrs
[0], "Target")) {
2679 GnmValue
*v
= value_new_cellrange_parsepos_str
2682 GNM_EXPR_PARSE_DEFAULT
);
2688 (gnm_sheet_range_from_value (&sr
, v
), !range_is_singleton (&sr
.range
)));
2694 gnm_cellref_init (&cr
, sr
.sheet
,
2698 gnm_solver_param_set_target (sp
, &cr
);
2699 } else if (gnm_xml_attr_int (attrs
, "MaxTime", &(sp
->options
.max_time_sec
)) ||
2700 gnm_xml_attr_int (attrs
, "MaxIter", &(sp
->options
.max_iter
)) ||
2701 gnm_xml_attr_bool (attrs
, "NonNeg", &(sp
->options
.assume_non_negative
)) ||
2702 gnm_xml_attr_bool (attrs
, "Discr", &(sp
->options
.assume_discrete
)) ||
2703 gnm_xml_attr_bool (attrs
, "AutoScale", &(sp
->options
.automatic_scaling
)) ||
2704 gnm_xml_attr_bool (attrs
, "ProgramR", &(sp
->options
.program_report
)) ||
2705 gnm_xml_attr_bool (attrs
, "SensitivityR", &(sp
->options
.sensitivity_report
)))
2710 col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
) &&
2711 row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
)) {
2713 gnm_cellref_init (&cr
, NULL
, col
, row
, TRUE
);
2714 gnm_solver_param_set_target (sp
, &cr
);
2719 xml_sax_scenario_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2721 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2722 const char *name
= "scenario";
2723 const char *comment
= NULL
;
2725 xml_sax_must_have_sheet (state
);
2727 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2728 if (attr_eq (attrs
[0], "Name")) {
2729 name
= CXML2C (attrs
[1]);
2730 } else if (attr_eq (attrs
[0], "Comment")) {
2731 comment
= CXML2C (attrs
[1]);
2735 state
->scenario
= gnm_sheet_scenario_new (state
->sheet
, name
);
2737 gnm_scenario_set_comment (state
->scenario
, comment
);
2741 xml_sax_scenario_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2743 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2744 GnmScenario
*sc
= state
->scenario
;
2745 sc
->items
= g_slist_reverse (sc
->items
);
2746 gnm_sheet_scenario_add (state
->sheet
, sc
);
2747 state
->scenario
= NULL
;
2751 xml_sax_scenario_item_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2753 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2754 const char *rtxt
= NULL
;
2757 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2758 if (attr_eq (attrs
[0], "Range")) {
2759 rtxt
= CXML2C (attrs
[1]);
2760 } else if (gnm_xml_attr_int (attrs
, "ValueType",
2761 &state
->value_type
))
2763 else if (attr_eq (attrs
[0], "ValueFormat"))
2764 state
->value_fmt
= make_format (CXML2C (attrs
[1]));
2767 parse_pos_init_sheet (&pp
, state
->sheet
);
2768 state
->scenario_range
= rtxt
2769 ? value_new_cellrange_parsepos_str (&pp
, rtxt
, GNM_EXPR_PARSE_DEFAULT
)
2774 xml_sax_scenario_item_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2776 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2777 char const * content
= xin
->content
->str
;
2778 int const len
= xin
->content
->len
;
2779 GnmScenarioItem
*sci
= NULL
;
2780 GnmScenario
*sc
= state
->scenario
;
2783 if (!state
->scenario_range
)
2786 gnm_sheet_range_from_value (&sr
, state
->scenario_range
);
2787 sci
= gnm_scenario_item_new (sc
->sheet
);
2788 gnm_scenario_item_set_range (sci
, &sr
);
2791 GnmValue
*v
= value_new_from_string (state
->value_type
,
2797 gnm_scenario_item_set_value (sci
, v
);
2801 sc
->items
= g_slist_prepend (sc
->items
, sci
);
2805 g_warning ("Ignoring invalid scenario item");
2807 gnm_scenario_item_free (sci
);
2810 state
->value_type
= -1;
2811 go_format_unref (state
->value_fmt
);
2812 state
->value_fmt
= NULL
;
2813 value_release (state
->scenario_range
);
2814 state
->scenario_range
= NULL
;
2818 xml_sax_named_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2820 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2822 GnmNamedExpr
*nexpr
;
2824 g_return_if_fail (state
->name
.name
!= NULL
);
2825 g_return_if_fail (state
->name
.value
!= NULL
);
2827 /*For the next while we have to ignore Print_areas that look like a whole sheet */
2828 if (0 == strcmp (state
->name
.name
, "Print_Area")
2829 && g_str_has_suffix (state
->name
.value
, "$A$1:$IV$65536")) {
2830 g_free (state
->name
.value
);
2831 state
->name
.value
= NULL
;
2832 g_free (state
->name
.position
);
2833 state
->name
.position
= NULL
;
2835 parse_pos_init (&pp
, state
->wb
, state
->sheet
, 0, 0);
2836 nexpr
= expr_name_add (&pp
, state
->name
.name
,
2837 gnm_expr_top_new_constant (value_new_empty ()),
2842 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->sheet
);
2843 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->name
.value
);
2844 state
->name
.value
= NULL
;
2845 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->name
.position
);
2846 state
->name
.position
= NULL
;
2847 state
->delayed_names
= g_list_prepend (state
->delayed_names
, nexpr
);
2849 g_warning ("Strangeness with defined name: %s",
2851 g_free (state
->name
.value
);
2852 state
->name
.value
= NULL
;
2853 g_free (state
->name
.position
);
2854 state
->name
.position
= NULL
;
2858 g_free (state
->name
.name
);
2859 state
->name
.name
= NULL
;
2863 xml_sax_named_expr_prop (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2865 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2867 char const * content
= xin
->content
->str
;
2868 int const len
= xin
->content
->len
;
2870 switch (xin
->node
->user_data
.v_int
) {
2872 g_return_if_fail (state
->name
.name
== NULL
);
2873 state
->name
.name
= g_strndup (content
, len
);
2876 g_return_if_fail (state
->name
.value
== NULL
);
2877 state
->name
.value
= g_strndup (content
, len
);
2880 g_return_if_fail (state
->name
.position
== NULL
);
2881 state
->name
.position
= g_strndup (content
, len
);
2889 xml_sax_print_order (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2891 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2893 xml_sax_must_have_sheet (state
);
2895 state
->sheet
->print_info
->print_across_then_down
=
2896 (strcmp (xin
->content
->str
, "r_then_d") == 0);
2900 xml_sax_print_comments_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2902 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2905 xml_sax_must_have_sheet (state
);
2907 /* In 1.11.x and later this is saved as an enum value */
2908 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
2909 if (xml_sax_attr_enum (attrs
, "placement", GNM_PRINT_COMMENT_PLACEMENT_TYPE
, &tmpi
))
2910 state
->sheet
->print_info
->comment_placement
= tmpi
;
2914 xml_sax_print_comments_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2916 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2918 if (xin
->content
->str
== NULL
|| *xin
->content
->str
== 0)
2919 /* 1.11.x or later file */
2922 xml_sax_must_have_sheet (state
);
2924 if (strcmp (xin
->content
->str
, "in_place") == 0)
2925 state
->sheet
->print_info
->comment_placement
=
2926 GNM_PRINT_COMMENTS_IN_PLACE
;
2927 else if (strcmp (xin
->content
->str
, "at_end") == 0)
2928 state
->sheet
->print_info
->comment_placement
=
2929 GNM_PRINT_COMMENTS_AT_END
;
2931 state
->sheet
->print_info
->comment_placement
=
2932 GNM_PRINT_COMMENTS_NONE
;
2936 xml_sax_print_errors_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2938 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2941 xml_sax_must_have_sheet (state
);
2943 /* In 1.11.x and later this is saved as an enum value */
2944 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
2945 if (xml_sax_attr_enum (attrs
, "PrintErrorsAs", GNM_PRINT_ERRORS_TYPE
, &tmpi
))
2946 state
->sheet
->print_info
->error_display
= tmpi
;
2951 xml_sax_print_errors_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2953 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2955 if (xin
->content
->str
== NULL
|| *xin
->content
->str
== 0)
2956 /* 1.11.x or later file */
2959 xml_sax_must_have_sheet (state
);
2961 if (strcmp (xin
->content
->str
, "as_blank") == 0)
2962 state
->sheet
->print_info
->error_display
=
2963 GNM_PRINT_ERRORS_AS_BLANK
;
2964 else if (strcmp (xin
->content
->str
, "as_dashes") == 0)
2965 state
->sheet
->print_info
->error_display
=
2966 GNM_PRINT_ERRORS_AS_DASHES
;
2967 else if (strcmp (xin
->content
->str
, "as_na") == 0)
2968 state
->sheet
->print_info
->error_display
=
2969 GNM_PRINT_ERRORS_AS_NA
;
2971 state
->sheet
->print_info
->error_display
=
2972 GNM_PRINT_ERRORS_AS_DISPLAYED
;
2977 xml_sax_orientation (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2979 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2980 GnmPrintInformation
*pi
;
2981 GtkPageOrientation orient
= GTK_PAGE_ORIENTATION_PORTRAIT
;
2983 xml_sax_must_have_sheet (state
);
2985 pi
= state
->sheet
->print_info
;
2987 #warning TODO: we should also handle inversion
2988 if (strcmp (xin
->content
->str
, "portrait") == 0)
2989 orient
= GTK_PAGE_ORIENTATION_PORTRAIT
;
2990 else if (strcmp (xin
->content
->str
, "landscape") == 0)
2991 orient
= GTK_PAGE_ORIENTATION_LANDSCAPE
;
2993 print_info_set_paper_orientation (pi
, orient
);
2997 xml_sax_paper (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2999 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3001 xml_sax_must_have_sheet (state
);
3003 print_info_set_paper (state
->sheet
->print_info
, xin
->content
->str
);
3007 xml_sax_print_to_uri (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
3009 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3011 xml_sax_must_have_sheet (state
);
3013 print_info_set_printtofile_uri (state
->sheet
->print_info
,
3018 handle_delayed_names (XMLSaxParseState
*state
)
3022 for (l
= state
->delayed_names
; l
; l
= l
->next
->next
->next
->next
) {
3023 GnmNamedExpr
*nexpr
= l
->data
;
3024 char *pos_str
= l
->next
->data
;
3025 char *expr_str
= l
->next
->next
->data
;
3026 Sheet
*sheet
= l
->next
->next
->next
->data
;
3028 GnmExprTop
const *texpr
;
3031 parse_pos_init (&pp
, state
->wb
, sheet
, 0, 0);
3035 GnmSheetSize
const *ss
=
3036 gnm_sheet_get_size2 (sheet
, state
->wb
);
3037 rest
= cellref_parse (&tmp
, ss
, pos_str
, &pp
.eval
);
3038 if (rest
!= NULL
&& *rest
== '\0') {
3039 pp
.eval
.col
= tmp
.col
;
3040 pp
.eval
.row
= tmp
.row
;
3044 parse_error_init (&perr
);
3045 texpr
= gnm_expr_parse_str (expr_str
, &pp
,
3046 GNM_EXPR_PARSE_DEFAULT
,
3050 go_io_warning (state
->context
, "%s", perr
.err
->message
);
3051 } else if (expr_name_check_for_loop (expr_name_name (nexpr
), texpr
)) {
3052 g_printerr ("Ignoring would-be circular definition of %s\n",
3053 expr_name_name (nexpr
));
3054 gnm_expr_top_unref (texpr
);
3056 nexpr
->pos
.eval
= pp
.eval
;
3057 expr_name_set_expr (nexpr
, texpr
);
3060 parse_error_free (&perr
);
3065 g_list_free (state
->delayed_names
);
3066 state
->delayed_names
= NULL
;
3070 xml_sax_go_doc (GsfXMLIn
*xin
, xmlChar
const **attrs
)
3072 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3073 go_doc_read (GO_DOC (state
->wb
), xin
, attrs
);
3076 /****************************************************************************/
3078 static GsfXMLInNS
const content_ns
[] = {
3079 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v14.dtd"), /* future */
3080 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v13.dtd"),
3081 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v12.dtd"),
3082 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v11.dtd"),
3083 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v10.dtd"),
3084 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v9.dtd"),
3085 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v8.dtd"),
3086 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v7"),
3087 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v6"),
3088 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v5"),
3089 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v4"),
3090 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v3"),
3091 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v2"),
3092 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/"),
3093 /* The next items are from libgsf, there is no obvious way of adding them automatically */
3094 GSF_XML_IN_NS (OO_NS_XSI
, "http://www.w3.org/2001/XMLSchema-instance"),
3095 GSF_XML_IN_NS (OO_NS_OFFICE
, "urn:oasis:names:tc:opendocument:xmlns:office:1.0"),
3096 GSF_XML_IN_NS (OO_NS_OOO
, "http://openoffice.org/2004/office"),
3097 GSF_XML_IN_NS (OO_NS_DC
, "http://purl.org/dc/elements/1.1/"),
3098 GSF_XML_IN_NS (OO_NS_XLINK
, "http://www.w3.org/1999/xlink"),
3099 GSF_XML_IN_NS (OO_NS_META
, "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"),
3103 static GsfXMLInNode gnumeric_1_0_dtd
[] = {
3104 GSF_XML_IN_NODE_FULL (START
, START
, -1, NULL
, GSF_XML_NO_CONTENT
, FALSE
, TRUE
, NULL
, NULL
, 0),
3105 GSF_XML_IN_NODE_FULL (START
, WB
, GNM
, "Workbook", GSF_XML_NO_CONTENT
, TRUE
, TRUE
, &xml_sax_wb
, NULL
, 0),
3106 GSF_XML_IN_NODE (WB
, WB_VERSION
, GNM
, "Version", GSF_XML_NO_CONTENT
, &xml_sax_version
, NULL
),
3107 GSF_XML_IN_NODE (WB
, WB_ATTRIBUTES
, GNM
, "Attributes", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3108 GSF_XML_IN_NODE (WB_ATTRIBUTES
, WB_ATTRIBUTE
, GNM
, "Attribute", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_finish_parse_wb_attr
),
3109 GSF_XML_IN_NODE_FULL (WB_ATTRIBUTE
, WB_ATTRIBUTE_NAME
, GNM
, "name", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_attr_elem
, 0),
3110 GSF_XML_IN_NODE_FULL (WB_ATTRIBUTE
, WB_ATTRIBUTE_VALUE
, GNM
, "value", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_attr_elem
, 1),
3111 GSF_XML_IN_NODE (WB_ATTRIBUTE
, WB_ATTRIBUTE_TYPE
, GNM
, "type", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3113 /* The old 'SummaryItem' Metadata. Removed in 1.7.x */
3114 GSF_XML_IN_NODE (WB
, WB_SUMMARY
, GNM
, "Summary", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3115 GSF_XML_IN_NODE (WB_SUMMARY
, WB_SUMMARY_ITEM
, GNM
, "Item", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3116 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_NAME
, GNM
, "name", GSF_XML_CONTENT
, NULL
, NULL
),
3117 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_VALUE_STR
, GNM
, "val-string", GSF_XML_CONTENT
, NULL
, NULL
),
3118 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_VALUE_INT
, GNM
, "val-int", GSF_XML_CONTENT
, NULL
, NULL
),
3120 GSF_XML_IN_NODE (WB
, WB_SHEETNAME_INDEX
, GNM
, "SheetNameIndex", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3121 GSF_XML_IN_NODE (WB_SHEETNAME_INDEX
, WB_SHEETNAME
, GNM
, "SheetName", GSF_XML_CONTENT
, &xml_sax_wb_sheetsize
, &xml_sax_wb_sheetname
),
3123 GSF_XML_IN_NODE (WB
, WB_NAMED_EXPRS
, GNM
, "Names", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3124 GSF_XML_IN_NODE (WB_NAMED_EXPRS
, WB_NAMED_EXPR
, GNM
, "Name", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_named_expr_end
),
3125 GSF_XML_IN_NODE_FULL (WB_NAMED_EXPR
, WB_NAMED_EXPR_NAME
, GNM
, "name", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 0),
3126 GSF_XML_IN_NODE_FULL (WB_NAMED_EXPR
, WB_NAMED_EXPR_VALUE
, GNM
, "value", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 1),
3127 GSF_XML_IN_NODE_FULL (WB_NAMED_EXPR
, WB_NAMED_EXPR_POSITION
, GNM
, "position", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 2),
3128 /* sometimes not namespaced */
3129 GSF_XML_IN_NODE_FULL (WB_NAMED_EXPR
, WB_NAMED_EXPR_NAME_NS
, -1, "name", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 0),
3130 GSF_XML_IN_NODE_FULL (WB_NAMED_EXPR
, WB_NAMED_EXPR_VALUE_NS
, -1, "value", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 1),
3131 GSF_XML_IN_NODE_FULL (WB_NAMED_EXPR
, WB_NAMED_EXPR_POSITION_NS
, -1, "position", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 2),
3133 GSF_XML_IN_NODE (WB
, WB_SHEETS
, GNM
, "Sheets", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3134 GSF_XML_IN_NODE (WB_SHEETS
, SHEET
, GNM
, "Sheet", GSF_XML_NO_CONTENT
, &xml_sax_sheet_start
, &xml_sax_sheet_end
),
3135 GSF_XML_IN_NODE (SHEET
, SHEET_NAME
, GNM
, "Name", GSF_XML_CONTENT
, NULL
, &xml_sax_sheet_name
),
3136 GSF_XML_IN_NODE (SHEET
, SHEET_MAXCOL
, GNM
, "MaxCol", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3137 GSF_XML_IN_NODE (SHEET
, SHEET_MAXROW
, GNM
, "MaxRow", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3138 GSF_XML_IN_NODE (SHEET
, SHEET_ZOOM
, GNM
, "Zoom", GSF_XML_CONTENT
, NULL
, &xml_sax_sheet_zoom
),
3139 GSF_XML_IN_NODE (SHEET
, SHEET_NAMED_EXPRS
, GNM
, "Names", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3140 GSF_XML_IN_NODE (SHEET_NAMED_EXPRS
, SHEET_NAMED_EXPR
, GNM
, "Name", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_named_expr_end
),
3141 GSF_XML_IN_NODE_FULL (SHEET_NAMED_EXPR
, SHEET_NAMED_EXPR_NAME
, GNM
, "name", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 0),
3142 GSF_XML_IN_NODE_FULL (SHEET_NAMED_EXPR
, SHEET_NAMED_EXPR_VALUE
, GNM
, "value", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 1),
3143 GSF_XML_IN_NODE_FULL (SHEET_NAMED_EXPR
, SHEET_NAMED_EXPR_POSITION
, GNM
, "position", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_named_expr_prop
, 2),
3145 GSF_XML_IN_NODE (SHEET
, SHEET_PRINTINFO
, GNM
, "PrintInformation", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3146 GSF_XML_IN_NODE (SHEET_PRINTINFO
, SHEET_PRINTUNIT
, GNM
, "PrintUnit", GSF_XML_NO_CONTENT
, NULL
, NULL
), /* ignore ancient field */
3147 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_MARGINS
, GNM
, "Margins", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3148 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_TOP
, GNM
, "top", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 0),
3149 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_BOTTOM
, GNM
, "bottom",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 1),
3150 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_LEFT
, GNM
, "left", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 2),
3151 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_RIGHT
, GNM
, "right", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 3),
3152 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_HEADER
, GNM
, "header",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 4),
3153 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_FOOTER
, GNM
, "footer",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 5),
3154 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, V_PAGE_BREAKS
, GNM
, "vPageBreaks", GSF_XML_NO_CONTENT
,
3155 FALSE
, FALSE
, &xml_sax_page_breaks_begin
, &xml_sax_page_breaks_end
, 1),
3156 GSF_XML_IN_NODE (V_PAGE_BREAKS
, PAGE_BREAK
, GNM
, "break", GSF_XML_NO_CONTENT
, &xml_sax_page_break
, NULL
),
3157 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, H_PAGE_BREAKS
, GNM
, "hPageBreaks", GSF_XML_NO_CONTENT
,
3158 FALSE
, FALSE
, &xml_sax_page_breaks_begin
, &xml_sax_page_breaks_end
, 0),
3159 GSF_XML_IN_NODE (H_PAGE_BREAKS
, PAGE_BREAK
, GNM
, "break", GSF_XML_2ND
, NULL
, NULL
),
3161 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_SCALE
, GNM
, "Scale", GSF_XML_CONTENT
, &xml_sax_print_scale
, NULL
),
3162 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_VCENTER
, GNM
, "vcenter", GSF_XML_CONTENT
, &xml_sax_print_vcenter
, NULL
),
3163 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_HCENTER
, GNM
, "hcenter", GSF_XML_CONTENT
, &xml_sax_print_hcenter
, NULL
),
3164 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_GRID
, GNM
, "grid", GSF_XML_NO_CONTENT
, &xml_sax_print_grid
, NULL
),
3165 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_DO_NOT_PRINT
, GNM
, "do_not_print",GSF_XML_NO_CONTENT
, &xml_sax_print_do_not_print
, NULL
),
3166 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_PRINT_RANGE
, GNM
, "print_range",GSF_XML_NO_CONTENT
, &xml_sax_print_print_range
, NULL
),
3167 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_MONO
, GNM
, "monochrome", GSF_XML_NO_CONTENT
, &xml_sax_monochrome
, NULL
),
3168 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_AS_DRAFT
, GNM
, "draft", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3169 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_COMMENTS
, GNM
, "comments", GSF_XML_CONTENT
, &xml_sax_print_comments_start
, &xml_sax_print_comments_end
),
3170 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ERRORS
, GNM
, "errors", GSF_XML_CONTENT
, &xml_sax_print_errors_start
, &xml_sax_print_errors_end
),
3171 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_TITLES
, GNM
, "titles", GSF_XML_NO_CONTENT
, &xml_sax_print_titles
, NULL
),
3172 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_REPEAT_TOP
, GNM
, "repeat_top", GSF_XML_NO_CONTENT
, &xml_sax_repeat_top
, NULL
),
3173 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_REPEAT_LEFT
,GNM
, "repeat_left", GSF_XML_NO_CONTENT
, &xml_sax_repeat_left
, NULL
),
3174 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, PRINT_FOOTER
, GNM
, "Footer", GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_print_hf
, NULL
, 0),
3175 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, PRINT_HEADER
, GNM
, "Header", GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_print_hf
, NULL
, 1),
3176 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ORDER
, GNM
, "order", GSF_XML_CONTENT
, NULL
, &xml_sax_print_order
),
3177 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_PAPER
, GNM
, "paper", GSF_XML_CONTENT
, NULL
, &xml_sax_paper
),
3178 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_TO_URI
, GNM
, "print-to-uri",GSF_XML_CONTENT
, NULL
, &xml_sax_print_to_uri
),
3179 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ORIENT
, GNM
, "orientation", GSF_XML_CONTENT
, NULL
, &xml_sax_orientation
),
3180 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ONLY_STYLE
, GNM
, "even_if_only_styles", GSF_XML_CONTENT
, &xml_sax_even_if_only_styles
, NULL
),
3182 GSF_XML_IN_NODE (SHEET
, SHEET_STYLES
, GNM
, "Styles", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3183 GSF_XML_IN_NODE (SHEET_STYLES
, STYLE_REGION
, GNM
, "StyleRegion", GSF_XML_NO_CONTENT
, &xml_sax_style_region_start
, &xml_sax_style_region_end
),
3184 GSF_XML_IN_NODE (STYLE_REGION
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, &xml_sax_style_start
, NULL
),
3185 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_FONT
, GNM
, "Font", GSF_XML_CONTENT
, &xml_sax_style_font
, &xml_sax_style_font_end
),
3186 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_BORDER
, GNM
, "StyleBorder", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3187 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_TOP
, GNM
, "Top",
3188 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_TOP
),
3189 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_BOTTOM
, GNM
, "Bottom",
3190 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_BOTTOM
),
3191 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_LEFT
, GNM
, "Left",
3192 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_LEFT
),
3193 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_RIGHT
, GNM
, "Right",
3194 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_RIGHT
),
3195 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_DIAG
, GNM
, "Diagonal",
3196 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_DIAGONAL
),
3197 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_REV_DIAG
,GNM
, "Rev-Diagonal",
3198 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_REV_DIAGONAL
),
3200 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_VALIDATION
, GNM
, "Validation", GSF_XML_NO_CONTENT
, &xml_sax_validation
, &xml_sax_validation_end
),
3201 GSF_XML_IN_NODE_FULL (STYLE_VALIDATION
, STYLE_VALIDATION_EXPR0
, GNM
, "Expression0",
3202 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_validation_expr_end
, 0),
3203 GSF_XML_IN_NODE_FULL (STYLE_VALIDATION
, STYLE_VALIDATION_EXPR1
, GNM
, "Expression1",
3204 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_validation_expr_end
, 1),
3205 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_HYPERLINK
, GNM
, "HyperLink", GSF_XML_NO_CONTENT
, &xml_sax_hlink
, NULL
),
3206 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_INPUT_MSG
, GNM
, "InputMessage", GSF_XML_NO_CONTENT
, &xml_sax_input_msg
, NULL
),
3207 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_CONDITION
, GNM
, "Condition", GSF_XML_NO_CONTENT
, &xml_sax_condition
, &xml_sax_condition_end
),
3208 GSF_XML_IN_NODE_FULL (STYLE_CONDITION
, STYLE_CONDITION_EXPR0
, GNM
, "Expression0",
3209 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_condition_expr_end
, 0),
3210 GSF_XML_IN_NODE_FULL (STYLE_CONDITION
, STYLE_CONDITION_EXPR1
, GNM
, "Expression1",
3211 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_condition_expr_end
, 1),
3212 GSF_XML_IN_NODE (STYLE_CONDITION
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3214 GSF_XML_IN_NODE_FULL (SHEET
, SHEET_COLS
, GNM
, "Cols",
3215 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_cols_rows
, NULL
, TRUE
),
3216 GSF_XML_IN_NODE_FULL (SHEET_COLS
, COL
, GNM
, "ColInfo",
3217 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_colrow
, NULL
, TRUE
),
3219 GSF_XML_IN_NODE_FULL (SHEET
, SHEET_ROWS
, GNM
, "Rows",
3220 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_cols_rows
, NULL
, FALSE
),
3221 GSF_XML_IN_NODE_FULL (SHEET_ROWS
, ROW
, GNM
, "RowInfo",
3222 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_colrow
, NULL
, FALSE
),
3224 GSF_XML_IN_NODE (SHEET
, SHEET_SELECTIONS
, GNM
, "Selections", GSF_XML_NO_CONTENT
, &xml_sax_selection
, &xml_sax_selection_end
),
3225 GSF_XML_IN_NODE (SHEET_SELECTIONS
, SELECTION
, GNM
, "Selection", GSF_XML_NO_CONTENT
, &xml_sax_selection_range
, NULL
),
3227 GSF_XML_IN_NODE (SHEET
, SHEET_CELLS
, GNM
, "Cells", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3228 GSF_XML_IN_NODE (SHEET_CELLS
, CELL
, GNM
, "Cell", GSF_XML_CONTENT
, &xml_sax_cell
, &xml_sax_cell_content
),
3229 GSF_XML_IN_NODE (CELL
, CELL_CONTENT
, GNM
, "Content", GSF_XML_CONTENT
, NULL
, &xml_sax_cell_content
),
3231 GSF_XML_IN_NODE (SHEET
, SHEET_MERGED_REGIONS
, GNM
, "MergedRegions", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3232 GSF_XML_IN_NODE (SHEET_MERGED_REGIONS
, MERGED_REGION
, GNM
, "Merge", GSF_XML_CONTENT
, NULL
, &xml_sax_merge
),
3234 GSF_XML_IN_NODE (SHEET
, SHEET_FILTERS
, GNM
, "Filters", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3235 GSF_XML_IN_NODE (SHEET_FILTERS
, FILTER
, GNM
, "Filter", GSF_XML_NO_CONTENT
, &xml_sax_filter_start
, &xml_sax_filter_end
),
3236 GSF_XML_IN_NODE (FILTER
, FILTER_FIELD
, GNM
, "Field", GSF_XML_NO_CONTENT
, &xml_sax_filter_condition
, NULL
),
3238 GSF_XML_IN_NODE (SHEET
, SHEET_LAYOUT
, GNM
, "SheetLayout", GSF_XML_NO_CONTENT
, &xml_sax_sheet_layout
, NULL
),
3239 GSF_XML_IN_NODE (SHEET_LAYOUT
, SHEET_FREEZEPANES
, GNM
, "FreezePanes", GSF_XML_NO_CONTENT
, &xml_sax_sheet_freezepanes
, NULL
),
3241 GSF_XML_IN_NODE (SHEET
, SHEET_SOLVER
, GNM
, "Solver", GSF_XML_NO_CONTENT
, xml_sax_solver_start
, NULL
),
3242 GSF_XML_IN_NODE (SHEET_SOLVER
, SOLVER_CONSTR
, GNM
, "Constr", GSF_XML_NO_CONTENT
, xml_sax_solver_constr_start
, NULL
),
3243 GSF_XML_IN_NODE (SHEET
, SHEET_SCENARIOS
, GNM
, "Scenarios", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3244 GSF_XML_IN_NODE (SHEET_SCENARIOS
, SHEET_SCENARIO
, GNM
, "Scenario", GSF_XML_NO_CONTENT
, xml_sax_scenario_start
, xml_sax_scenario_end
),
3245 GSF_XML_IN_NODE (SHEET_SCENARIO
, SCENARIO_ITEM
, GNM
, "Item", GSF_XML_CONTENT
, xml_sax_scenario_item_start
, xml_sax_scenario_item_end
),
3247 GSF_XML_IN_NODE (SHEET
, SHEET_OBJECTS
, GNM
, "Objects", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3249 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_RECT
, GNM
, "Rectangle", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3250 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_ELLIPSE
, GNM
, "Ellipse", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3251 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_ARROW
, GNM
, "Arrow", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3252 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_LINE
, GNM
, "Line", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3253 /* Class renamed between 1.0.x and 1.2.x */
3254 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_GRAPH
, GNM
, "GnmGraph", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3255 /* Class renamed in 1.2.2 */
3256 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_COMMENT
, GNM
, "CellComment", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3257 /* Class renamed in 1.3.91 */
3258 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_LINE
, GNM
, "SheetObjectGraphic", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3259 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_FILLED
, GNM
, "SheetObjectFilled", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3260 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_TEXT
, GNM
, "SheetObjectText", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3261 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_GRAPH
, GNM
, "SheetObjectGraph", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3262 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_IMAGE
, GNM
, "SheetObjectImage", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3263 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_COMPONENT
, GNM
, "SheetObjectComponent", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3264 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_PATH
, GNM
, "SheetObjectPath", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3266 GSF_XML_IN_NODE (WB
, WB_GEOMETRY
, GNM
, "Geometry", GSF_XML_NO_CONTENT
, &xml_sax_wb_view
, NULL
),
3267 GSF_XML_IN_NODE (WB
, WB_VIEW
, GNM
, "UIData", GSF_XML_NO_CONTENT
, &xml_sax_wb_view
, NULL
),
3268 GSF_XML_IN_NODE (WB
, WB_CALC
, GNM
, "Calculation", GSF_XML_NO_CONTENT
, &xml_sax_calculation
, NULL
),
3269 GSF_XML_IN_NODE (WB
, WB_DATE
, GNM
, "DateConvention", GSF_XML_CONTENT
, NULL
, &xml_sax_old_dateconvention
),
3270 GSF_XML_IN_NODE (WB
, GODOC
, -1, "GODoc", GSF_XML_NO_CONTENT
, &xml_sax_go_doc
, NULL
),
3271 GSF_XML_IN_NODE (WB
, DOCUMENTMETA
, OO_NS_OFFICE
, "document-meta", GSF_XML_NO_CONTENT
, &xml_sax_document_meta
, NULL
),
3276 xml_sax_clipboardrange_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
3278 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3279 int cols
= -1, rows
= -1, base_col
= -1, base_row
= -1;
3282 cr
= state
->clipboard
= gnm_cell_region_new (state
->sheet
);
3284 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
3285 if (gnm_xml_attr_int (attrs
, "Cols", &cols
) ||
3286 gnm_xml_attr_int (attrs
, "Rows", &rows
) ||
3287 gnm_xml_attr_int (attrs
, "BaseCol", &base_col
) ||
3288 gnm_xml_attr_int (attrs
, "BaseRow", &base_row
) ||
3289 gnm_xml_attr_bool (attrs
, "NotAsContent", &cr
->not_as_contents
))
3291 else if (attr_eq (attrs
[0], "DateConvention")) {
3292 GODateConventions
const *date_conv
=
3293 go_date_conv_from_str (CXML2C (attrs
[1]));
3295 cr
->date_conv
= date_conv
;
3297 g_printerr ("Ignoring invalid date conventions.\n");
3301 if (cols
<= 0 || rows
<= 0 || base_col
< 0 || base_row
< 0) {
3302 g_printerr ("Invalid clipboard contents.\n");
3306 cr
->base
.col
= base_col
;
3307 cr
->base
.row
= base_row
;
3311 static GsfXMLInNode clipboard_dtd
[] = {
3312 GSF_XML_IN_NODE_FULL (START
, START
, -1, NULL
, GSF_XML_NO_CONTENT
, FALSE
, TRUE
, NULL
, NULL
, 0),
3313 GSF_XML_IN_NODE_FULL (START
, CLIPBOARDRANGE
, GNM
, "ClipboardRange", GSF_XML_NO_CONTENT
, TRUE
, TRUE
, xml_sax_clipboardrange_start
, NULL
, 0),
3314 /* We insert "Styles" (etc) */
3319 gnm_xml_in_doc_add_subset (GsfXMLInDoc
*doc
, GsfXMLInNode
*dtd
,
3320 const char *id
, const char *new_parent
)
3322 GHashTable
*parents
= g_hash_table_new (g_str_hash
, g_str_equal
);
3323 GsfXMLInNode end_node
= GSF_XML_IN_NODE_END
;
3324 GArray
*new_dtd
= g_array_new (FALSE
, FALSE
, sizeof (GsfXMLInNode
));
3326 for (; dtd
->id
; dtd
++) {
3327 GsfXMLInNode node
= *dtd
;
3329 if (g_str_equal (id
, dtd
->id
)) {
3330 g_hash_table_insert (parents
,
3334 node
.parent_id
= new_parent
;
3335 } else if (g_hash_table_lookup (parents
, dtd
->parent_id
))
3336 g_hash_table_insert (parents
,
3342 g_array_append_val (new_dtd
, node
);
3345 g_array_append_val (new_dtd
, end_node
);
3347 gsf_xml_in_doc_add_nodes (doc
, (GsfXMLInNode
*)(new_dtd
->data
));
3349 g_array_free (new_dtd
, TRUE
);
3350 g_hash_table_destroy (parents
);
3355 xml_sax_unknown (GsfXMLIn
*xin
, xmlChar
const *elem
, xmlChar
const **attrs
)
3357 g_return_val_if_fail (xin
!= NULL
, FALSE
);
3358 g_return_val_if_fail (xin
->doc
!= NULL
, FALSE
);
3359 g_return_val_if_fail (xin
->node
!= NULL
, FALSE
);
3361 if (GNM
== xin
->node
->ns_id
&&
3362 0 == strcmp (xin
->node
->id
, "SHEET_OBJECTS")) {
3363 char const *type_name
= gsf_xml_in_check_ns (xin
, CXML2C (elem
), GNM
);
3364 if (type_name
!= NULL
) {
3365 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3366 /* This may change xin->user_state. */
3367 xml_sax_read_obj (xin
, TRUE
, type_name
, attrs
);
3368 /* xin->user_state hasn't been restored yet. */
3369 return state
->so
!= NULL
;
3376 read_file_init_state (XMLSaxParseState
*state
,
3377 GOIOContext
*io_context
,
3378 WorkbookView
*wb_view
, Sheet
*sheet
)
3380 state
->context
= io_context
;
3381 state
->wb_view
= wb_view
;
3384 : (wb_view
? wb_view_get_workbook (wb_view
) : NULL
);
3385 state
->sheet
= sheet
;
3386 state
->version
= GNM_XML_UNKNOWN
;
3387 state
->last_progress_update
= 0;
3388 state
->convs
= gnm_xml_io_conventions ();
3389 state
->attribute
.name
= state
->attribute
.value
= NULL
;
3390 state
->name
.name
= state
->name
.value
= state
->name
.position
= NULL
;
3391 state
->style_range_init
= FALSE
;
3392 state
->style
= NULL
;
3393 state
->cell
.row
= state
->cell
.col
= -1;
3394 state
->seen_cell_contents
= FALSE
;
3395 state
->array_rows
= state
->array_cols
= -1;
3396 state
->expr_id
= -1;
3397 state
->value_type
= -1;
3398 state
->value_fmt
= NULL
;
3399 state
->value_result
= NULL
;
3400 state
->scenario
= NULL
;
3401 state
->scenario_range
= NULL
;
3402 state
->filter
= NULL
;
3403 state
->validation
.title
= state
->validation
.msg
= NULL
;
3404 state
->validation
.texpr
[0] = state
->validation
.texpr
[1] = NULL
;
3406 state
->cond_save_style
= NULL
;
3407 state
->expr_map
= g_hash_table_new_full
3408 (g_direct_hash
, g_direct_equal
,
3409 NULL
, (GFreeFunc
)gnm_expr_top_unref
);
3410 state
->delayed_names
= NULL
;
3412 state
->page_breaks
= NULL
;
3413 state
->clipboard
= NULL
;
3414 state
->style_handler
= NULL
;
3415 state
->style_handler_user
= NULL
;
3416 state
->style_handler_doc
= NULL
;
3420 read_file_free_state (XMLSaxParseState
*state
, gboolean self
)
3422 g_hash_table_destroy (state
->expr_map
);
3423 state
->expr_map
= NULL
;
3425 gnm_conventions_unref (state
->convs
);
3426 state
->convs
= NULL
;
3429 * Malformed documents can cause the parser to exit early.
3430 * This cleans up various bits that may be left.
3434 gnm_style_unref (state
->style
);
3435 state
->style
= NULL
;
3438 if (state
->cond_save_style
) {
3439 gnm_style_unref (state
->cond_save_style
);
3440 state
->cond_save_style
= NULL
;
3444 gnm_style_cond_free (state
->cond
);
3448 if (state
->style_handler_doc
) {
3449 gsf_xml_in_doc_free (state
->style_handler_doc
);
3450 state
->style_handler_doc
= NULL
;
3458 read_file_common (ReadFileWhat what
, XMLSaxParseState
*state
,
3459 GOIOContext
*io_context
,
3460 WorkbookView
*wb_view
, Sheet
*sheet
,
3467 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wb_view
), FALSE
);
3468 g_return_val_if_fail (GSF_IS_INPUT (input
), FALSE
);
3470 read_file_init_state (state
, io_context
, wb_view
, sheet
);
3473 case READ_FULL_FILE
:
3474 state
->do_progress
= TRUE
;
3475 doc
= gsf_xml_in_doc_new (gnumeric_1_0_dtd
, content_ns
);
3477 case READ_CLIPBOARD
:
3478 state
->do_progress
= FALSE
;
3479 doc
= gsf_xml_in_doc_new (clipboard_dtd
, content_ns
);
3482 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3485 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3488 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3491 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3494 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3495 "SHEET_MERGED_REGIONS",
3497 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3502 g_assert_not_reached ();
3509 gsf_xml_in_doc_set_unknown_handler (doc
, &xml_sax_unknown
);
3511 go_doc_init_read (GO_DOC (state
->wb
), input
);
3512 gsf_input_seek (input
, 0, G_SEEK_SET
);
3514 if (state
->do_progress
) {
3515 go_io_progress_message (state
->context
,
3516 _("Reading file..."));
3517 go_io_value_progress_set (state
->context
,
3518 gsf_input_size (input
), 0);
3521 locale
= gnm_push_C_locale ();
3522 ok
= gsf_xml_in_doc_parse (doc
, input
, state
);
3523 handle_delayed_names (state
);
3524 gnm_pop_C_locale (locale
);
3526 go_doc_end_read (GO_DOC (state
->wb
));
3528 if (state
->do_progress
)
3529 go_io_progress_unset (state
->context
);
3532 go_io_error_string (state
->context
,
3533 _("XML document not well formed!"));
3536 gsf_xml_in_doc_free (doc
);
3541 /* ------------------------------------------------------------------------- */
3544 maybe_gunzip (GsfInput
*input
)
3546 GsfInput
*gzip
= gsf_input_gzip_new (input
, NULL
);
3548 g_object_unref (input
);
3551 gsf_input_seek (input
, 0, G_SEEK_SET
);
3557 maybe_convert (GsfInput
*input
, gboolean quiet
)
3559 static char const *noencheader
= "<?xml version=\"1.0\"?>";
3560 static char const *encheader
= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
3561 const size_t nelen
= strlen (noencheader
);
3562 const size_t elen
= strlen (encheader
);
3564 gsf_off_t input_size
;
3565 GString the_buffer
, *buffer
= &the_buffer
;
3567 GString
*converted
= NULL
;
3568 char const *encoding
;
3570 gboolean any_numbered
= FALSE
;
3572 input_size
= gsf_input_remaining (input
);
3574 buf
= gsf_input_read (input
, nelen
, NULL
);
3576 strncmp (noencheader
, (const char *)buf
, nelen
) != 0 ||
3577 input_size
>= (gsf_off_t
)(G_MAXINT
- elen
))
3580 input_size
-= nelen
;
3583 the_buffer
.allocated_len
= input_size
+ elen
+ 1;
3584 the_buffer
.str
= g_try_malloc (the_buffer
.allocated_len
);
3585 if (!the_buffer
.str
)
3588 g_string_append (buffer
, encheader
);
3589 ok
= gsf_input_read (input
, input_size
, (guint8
*)buffer
->str
+ elen
) != NULL
;
3590 gsf_input_seek (input
, 0, G_SEEK_SET
);
3592 g_free (buffer
->str
);
3595 buffer
->len
= input_size
+ elen
;
3596 buffer
->str
[buffer
->len
] = 0;
3598 for (ui
= 0; ui
< buffer
->len
; ui
++) {
3599 if (buffer
->str
[ui
] == '&' &&
3600 buffer
->str
[ui
+ 1] == '#' &&
3601 g_ascii_isdigit (buffer
->str
[ui
+ 2])) {
3605 while (g_ascii_isdigit (buffer
->str
[ui
])) {
3606 c
= c
* 10 + (buffer
->str
[ui
] - '0');
3609 if (buffer
->str
[ui
] == ';' && c
>= 128 && c
<= 255) {
3610 buffer
->str
[start
] = c
;
3611 g_string_erase (buffer
, start
+ 1, ui
- start
);
3614 any_numbered
= TRUE
;
3618 encoding
= go_guess_encoding (buffer
->str
, buffer
->len
, NULL
, &converted
, NULL
);
3619 if (encoding
&& !any_numbered
&&
3620 converted
&& buffer
->len
== converted
->len
&&
3621 strcmp (buffer
->str
, converted
->str
) == 0)
3624 g_free (buffer
->str
);
3627 gsize len
= converted
->len
;
3628 g_object_unref (input
);
3630 g_warning ("Converted xml document with no explicit encoding from transliterated %s to UTF-8.",
3632 return gsf_input_memory_new ((void *)g_string_free (converted
, FALSE
), len
, TRUE
);
3635 g_warning ("Failed to convert xml document with no explicit encoding to UTF-8.");
3641 gnm_xml_file_open (G_GNUC_UNUSED GOFileOpener
const *fo
, GOIOContext
*io_context
,
3642 GoView
*view
, GsfInput
*input
)
3644 XMLSaxParseState state
;
3647 g_object_ref (input
);
3648 input
= maybe_gunzip (input
);
3649 input
= maybe_convert (input
, FALSE
);
3651 ok
= read_file_common (READ_FULL_FILE
, &state
,
3652 io_context
, GNM_WORKBOOK_VIEW (view
), NULL
,
3655 g_object_unref (input
);
3658 workbook_queue_all_recalc (state
.wb
);
3660 workbook_set_saveinfo
3663 go_file_saver_for_id ("Gnumeric_XmlIO:sax"));
3666 read_file_free_state (&state
, FALSE
);
3669 /* ------------------------------------------------------------------------- */
3672 gnm_xml_cellregion_read (WorkbookControl
*wbc
, GOIOContext
*io_context
,
3674 const char *buffer
, int length
)
3676 WorkbookView
*wb_view
;
3678 XMLSaxParseState state
;
3679 GnmCellRegion
*result
;
3681 wb_view
= wb_control_view (wbc
);
3682 input
= gsf_input_memory_new (buffer
, length
, FALSE
);
3683 read_file_common (READ_CLIPBOARD
, &state
,
3684 io_context
, wb_view
, sheet
,
3686 g_object_unref (input
);
3688 result
= state
.clipboard
;
3689 state
.clipboard
= NULL
;
3691 read_file_free_state (&state
, FALSE
);
3696 /* ------------------------------------------------------------------------- */
3699 style_parser_done (GsfXMLIn
*xin
, XMLSaxParseState
*old_state
)
3701 GnmStyle
*style
= old_state
->style
;
3702 old_state
->style_handler (xin
, style
, old_state
->style_handler_user
);
3703 read_file_free_state (old_state
, TRUE
);
3707 * gnm_xml_prep_style_parser:
3710 * @handler: (scope async):
3715 gnm_xml_prep_style_parser (GsfXMLIn
*xin
,
3716 xmlChar
const **attrs
,
3717 GnmXmlStyleHandler handler
,
3720 static GsfXMLInNode dtd
[] = {
3721 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, &xml_sax_style_start
, NULL
),
3722 /* Nodes added below. */
3725 GsfXMLInDoc
*doc
= gsf_xml_in_doc_new (dtd
, NULL
);
3726 XMLSaxParseState
*state
= g_new0 (XMLSaxParseState
, 1);
3728 read_file_init_state (state
, NULL
, NULL
, NULL
);
3729 state
->style_handler
= handler
;
3730 state
->style_handler_user
= user
;
3731 state
->style_handler_doc
= doc
;
3732 state
->style
= gnm_style_new_default ();
3734 /* Not a full style, just those parts that do not require a sheet. */
3735 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3738 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3742 gsf_xml_in_push_state (xin
, doc
, state
,
3743 (GsfXMLInExtDtor
)style_parser_done
, attrs
);
3746 /* ------------------------------------------------------------------------- */
3749 gnm_xml_probe_element (const xmlChar
*name
,
3750 G_GNUC_UNUSED
const xmlChar
*prefix
,
3752 G_GNUC_UNUSED
int nb_namespaces
,
3753 G_GNUC_UNUSED
const xmlChar
**namespaces
,
3754 G_GNUC_UNUSED
int nb_attributes
,
3755 G_GNUC_UNUSED
int nb_defaulted
,
3756 G_GNUC_UNUSED
const xmlChar
**attributes
)
3758 return 0 == strcmp (name
, "Workbook") &&
3759 NULL
!= URI
&& NULL
!= strstr (URI
, "gnumeric");
3763 xml_probe (G_GNUC_UNUSED GOFileOpener
const *fo
, GsfInput
*input
, GOFileProbeLevel pl
)
3765 if (pl
== GO_FILE_PROBE_FILE_NAME
) {
3766 char const *name
= gsf_input_name (input
);
3772 len
= strlen (name
);
3773 if (len
>= 7 && !g_ascii_strcasecmp (name
+len
-7, ".xml.gz"))
3776 name
= gsf_extension_pointer (name
);
3778 return (name
!= NULL
&&
3779 (g_ascii_strcasecmp (name
, "gnumeric") == 0 ||
3780 g_ascii_strcasecmp (name
, "xml") == 0));
3782 /* probe by content */
3783 return gsf_xml_probe (input
, &gnm_xml_probe_element
);
3786 #define XML_SAX_ID "Gnumeric_XmlIO:sax"
3789 gnm_xml_sax_read_init (void)
3791 GOFileOpener
*opener
;
3792 GSList
*suffixes
= go_slist_create (g_strdup ("gnumeric"),
3795 GSList
*mimes
= go_slist_create (g_strdup ("application/x-gnumeric"),
3798 opener
= go_file_opener_new
3800 _("Gnumeric XML (*.gnumeric)"),
3802 xml_probe
, gnm_xml_file_open
);
3803 go_file_opener_register (opener
, 50);
3804 g_object_unref (opener
);
3808 gnm_xml_sax_read_shutdown (void)
3810 go_file_opener_unregister
3811 (go_file_opener_for_id (XML_SAX_ID
));