1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
4 * xml-sax-read.c : a sax based parser.
6 * Copyright (C) 2000-2007 Jody Goldberg (jody@gnome.org)
7 * Copyright (C) 2007-2009 Morten Welinder (terra@gnome.org)
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) version 3.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
25 #include <gnumeric-config.h>
28 #include "xml-io-version.h"
29 #include "gnm-plugin.h"
30 #include "sheet-view.h"
31 #include "sheet-style.h"
32 #include "sheet-merge.h"
33 #include "sheet-filter.h"
36 #include <tools/gnm-solver.h>
37 #include <tools/scenarios.h>
39 #include "style-border.h"
40 #include "style-color.h"
41 #include "style-conditions.h"
42 #include "validation.h"
44 #include "input-msg.h"
48 #include "expr-name.h"
49 #include "print-info.h"
51 #include "selection.h"
52 #include "command-context.h"
53 #include "workbook-view.h"
54 #include "workbook-control.h"
56 #include "sheet-object-impl.h"
57 #include "sheet-object-cell-comment.h"
58 #include "gnm-so-line.h"
59 #include "gnm-so-filled.h"
60 #include "gnm-so-path.h"
61 #include "gnm-format.h"
62 #include "sheet-object-graph.h"
63 #include "sheet-object-component.h"
64 #include "application.h"
66 #include "clipboard.h"
67 #include "number-match.h"
69 #include <goffice/goffice.h>
71 #include <gsf/gsf-libxml.h>
72 #include <gsf/gsf-input.h>
73 #include <gsf/gsf-input-memory.h>
74 #include <gsf/gsf-input-gzip.h>
75 #include <gsf/gsf-opendoc-utils.h>
76 #include <gsf/gsf-utils.h>
77 #include <glib/gi18n-lib.h>
78 #include <libxml/tree.h>
79 #include <libxml/parser.h>
80 #include <libxml/parserInternals.h>
85 /* libgsf defines OO_NS_OFFICE to be 0, so we need to take something different for GNM */
89 xml_sax_barf (const char *locus
, const char *reason
)
91 g_warning ("File is most likely corrupted.\n"
92 "The problem was detected in %s.\n"
93 "The failed check was: %s",
97 #define XML_CHECK3(_cond_,_code_,_reason_) \
99 if (G_UNLIKELY(!(_cond_))) { \
100 xml_sax_barf (G_STRFUNC, _reason_); \
106 #define XML_CHECK(_cond_) XML_CHECK3(_cond_,{},#_cond_)
107 #define XML_CHECK2(_cond_,_code_) XML_CHECK3(_cond_,_code_,#_cond_)
110 #define CXML2C(s) ((char const *)(s))
112 static inline gboolean
113 attr_eq (const xmlChar
*a
, const char *s
)
115 return !strcmp (CXML2C (a
), s
);
119 make_format (const char *str
)
122 gnm_format_import (str
,
123 GNM_FORMAT_IMPORT_NULL_INVALID
|
124 GNM_FORMAT_IMPORT_PATCHUP_INCOMPLETE
);
126 g_warning ("Ignoring invalid format [%s]", str
);
133 /*****************************************************************************/
136 gnm_xml_attr_double (xmlChar
const * const *attrs
, char const *name
, double * res
)
141 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
142 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
143 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
145 if (!attr_eq (attrs
[0], name
))
148 tmp
= go_strtod (CXML2C (attrs
[1]), &end
);
150 g_warning ("Invalid attribute '%s', expected double, received '%s'",
159 xml_sax_double (xmlChar
const *chars
, double *res
)
162 *res
= go_strtod (CXML2C (chars
), &end
);
167 gnm_xml_attr_bool (xmlChar
const * const *attrs
, char const *name
, gboolean
*res
)
169 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
170 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
171 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
173 if (!attr_eq (attrs
[0], name
))
176 *res
= g_ascii_strcasecmp (CXML2C (attrs
[1]), "false") && strcmp (CXML2C (attrs
[1]), "0");
182 gnm_xml_attr_int (xmlChar
const * const *attrs
, char const *name
, int *res
)
187 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
188 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
189 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
191 if (!attr_eq (attrs
[0], name
))
195 tmp
= strtol (CXML2C (attrs
[1]), &end
, 10);
197 g_warning ("Invalid attribute '%s', expected integer, received '%s'",
205 /* NOT SUITABLE FOR HIGH VOLUME VALUES
206 * Checking both name and nick gets expensive */
208 xml_sax_attr_enum (xmlChar
const * const *attrs
,
217 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
218 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
219 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
221 if (!attr_eq (attrs
[0], name
))
224 eclass
= G_ENUM_CLASS (g_type_class_ref (etype
));
225 ev
= g_enum_get_value_by_name (eclass
, CXML2C (attrs
[1]));
226 if (!ev
) ev
= g_enum_get_value_by_nick (eclass
, CXML2C (attrs
[1]));
227 g_type_class_unref (eclass
);
229 if (!ev
&& gnm_xml_attr_int (attrs
, name
, &i
))
230 /* Check that the value is valid. */
231 ev
= g_enum_get_value (eclass
, i
);
232 if (!ev
) return FALSE
;
240 xml_sax_attr_cellpos (xmlChar
const * const *attrs
, char const *name
, GnmCellPos
*val
, Sheet
const *sheet
)
242 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
243 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
244 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
246 if (!attr_eq (attrs
[0], name
))
249 if (cellpos_parse (CXML2C (attrs
[1]), gnm_sheet_get_size (sheet
), val
, TRUE
) == NULL
) {
250 g_warning ("Invalid attribute '%s', expected cellpos, received '%s'",
258 xml_sax_attr_color (xmlChar
const * const *attrs
, char const *name
, GnmColor
**res
)
260 unsigned int red
, green
, blue
, alpha
= 0xffff;
262 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
263 g_return_val_if_fail (attrs
[0] != NULL
, FALSE
);
264 g_return_val_if_fail (attrs
[1] != NULL
, FALSE
);
266 if (!attr_eq (attrs
[0], name
))
269 if (sscanf (CXML2C (attrs
[1]), "%X:%X:%X:%X", &red
, &green
, &blue
, &alpha
) < 3){
270 g_warning ("Invalid attribute '%s', expected colour, received '%s'",
274 *res
= gnm_color_new_rgba16 (red
, green
, blue
, alpha
);
279 xml_sax_attr_range (xmlChar
const * const *attrs
, GnmRange
*res
)
283 g_return_val_if_fail (attrs
!= NULL
, FALSE
);
285 for (; attrs
[0] && attrs
[1] ; attrs
+= 2)
286 if (gnm_xml_attr_int (attrs
, "startCol", &res
->start
.col
))
288 else if (gnm_xml_attr_int (attrs
, "startRow", &res
->start
.row
))
290 else if (gnm_xml_attr_int (attrs
, "endCol", &res
->end
.col
))
292 else if (gnm_xml_attr_int (attrs
, "endRow", &res
->end
.row
))
300 /*****************************************************************************/
312 GOIOContext
*context
; /* The IOcontext managing things */
313 WorkbookView
*wb_view
; /* View for the new workbook */
314 Workbook
*wb
; /* The new workbook */
315 GnumericXMLVersion version
;
316 gsf_off_t last_progress_update
;
317 GnmConventions
*convs
;
318 gboolean do_progress
;
323 /* Only valid while parsing attributes */
329 /* Only valid when parsing wb or sheet names */
339 GnmExprTop
const *texpr
[2];
340 ValidationStyle style
;
343 gboolean allow_blank
;
344 gboolean use_dropdown
;
348 GnmStyle
*cond_save_style
;
350 gboolean style_range_init
;
351 GnmRange style_range
;
355 gboolean seen_cell_contents
;
356 int expr_id
, array_rows
, array_cols
;
361 GnmScenario
*scenario
;
362 GnmValue
*scenario_range
;
366 int display_formulas
;
371 int display_outlines
;
372 int outline_symbols_below
;
373 int outline_symbols_right
;
376 char *expr_conv_name
;
377 GnmSheetVisibility visibility
;
379 GnmColor
*tab_text_color
;
380 GnmColor
*grid_color
;
382 /* expressions with ref > 1 a map from index -> expr pointer */
383 GHashTable
*expr_map
;
384 GList
*delayed_names
;
387 int sheet_rows
, sheet_cols
;
388 GnmSheetType sheet_type
;
390 GnmPageBreaks
*page_breaks
;
392 GnmCellRegion
*clipboard
;
394 GnmXmlStyleHandler style_handler
;
395 gpointer style_handler_user
;
396 GsfXMLInDoc
*style_handler_doc
;
400 maybe_update_progress (GsfXMLIn
*xin
)
402 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
403 GsfInput
*input
= gsf_xml_in_get_input (xin
);
404 gsf_off_t pos
= gsf_input_tell (input
);
406 if (state
->do_progress
&& pos
>= state
->last_progress_update
+ 10000) {
407 go_io_value_progress_update (state
->context
, pos
);
408 state
->last_progress_update
= pos
;
413 * gnm_xml_in_cur_obj:
416 * Returns: (transfer none): the current sheet object.
419 gnm_xml_in_cur_obj (GsfXMLIn
const *xin
)
421 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
426 * gnm_xml_in_cur_sheet:
429 * Returns: (transfer none): the current sheet.
432 gnm_xml_in_cur_sheet (GsfXMLIn
const *xin
)
434 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
439 gnm_xml_finish_obj (GsfXMLIn
*xin
, XMLSaxParseState
*state
)
441 GnmCellRegion
*cr
= state
->clipboard
;
444 cr
->objects
= g_slist_prepend (cr
->objects
, state
->so
);
446 sheet_object_set_sheet (state
->so
, state
->sheet
);
447 g_object_unref (state
->so
);
453 /****************************************************************************/
456 unknown_attr (GsfXMLIn
*xin
, xmlChar
const * const *attrs
)
458 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
460 if (state
->version
== GNM_XML_LATEST
)
461 go_io_warning (state
->context
,
462 _("Unexpected attribute %s::%s == '%s'."),
463 (NULL
!= xin
->node
&&
464 NULL
!= xin
->node
->name
) ?
465 xin
->node
->name
: "<unknown name>",
470 xml_sax_wb (GsfXMLIn
*xin
, xmlChar
const **attrs
)
472 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
475 * NOTE: If we read a file with a dtd that is newer, i.e., from the
476 * future, then we will not get here! For that reason we also muck
477 * with ->version in xml_sax_version.
479 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
480 if (strcmp (CXML2C (attrs
[0]), "xmlns:gmr") == 0 ||
481 strcmp (CXML2C (attrs
[0]), "xmlns:gnm") == 0) {
483 char const * const id
;
484 GnumericXMLVersion
const version
;
485 } const GnumericVersions
[] = {
486 { "http://www.gnumeric.org/v14.dtd", GNM_XML_V14
}, /* 1.12.21 */
487 { "http://www.gnumeric.org/v13.dtd", GNM_XML_V13
}, /* 1.7.7 */
488 { "http://www.gnumeric.org/v12.dtd", GNM_XML_V12
}, /* 1.7.3 */
489 { "http://www.gnumeric.org/v11.dtd", GNM_XML_V11
}, /* 1.7.0 */
490 { "http://www.gnumeric.org/v10.dtd", GNM_XML_V10
}, /* 1.0.3 */
491 { "http://www.gnumeric.org/v9.dtd", GNM_XML_V9
}, /* 0.73 */
492 { "http://www.gnumeric.org/v8.dtd", GNM_XML_V8
}, /* 0.71 */
493 { "http://www.gnome.org/gnumeric/v7", GNM_XML_V7
}, /* 0.66 */
494 { "http://www.gnome.org/gnumeric/v6", GNM_XML_V6
}, /* 0.62 */
495 { "http://www.gnome.org/gnumeric/v5", GNM_XML_V5
},
496 { "http://www.gnome.org/gnumeric/v4", GNM_XML_V4
},
497 { "http://www.gnome.org/gnumeric/v3", GNM_XML_V3
},
498 { "http://www.gnome.org/gnumeric/v2", GNM_XML_V2
},
499 { "http://www.gnome.org/gnumeric/", GNM_XML_V1
},
503 for (i
= 0 ; GnumericVersions
[i
].id
!= NULL
; ++i
)
504 if (strcmp (CXML2C (attrs
[1]), GnumericVersions
[i
].id
) == 0) {
505 if (state
->version
!= GNM_XML_UNKNOWN
)
506 go_io_warning (state
->context
,
507 _("Multiple version specifications. Assuming %d"),
510 state
->version
= GnumericVersions
[i
].version
;
514 } else if (attr_eq (attrs
[0], "xmlns:xsi")) {
515 } else if (attr_eq (attrs
[0], "xsi:schemaLocation")) {
517 unknown_attr (xin
, attrs
);
522 xml_sax_document_meta (GsfXMLIn
*xin
, G_GNUC_UNUSED xmlChar
const **attrs
)
524 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
526 gsf_doc_meta_data_odf_subtree (go_doc_get_meta_data (GO_DOC (state
->wb
)), xin
);
532 xml_sax_version (GsfXMLIn
*xin
, xmlChar
const **attrs
)
534 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
540 state
->version
= GNM_XML_V11
;
541 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
542 if (gnm_xml_attr_int (attrs
, "Epoch", &epoch
))
544 else if (gnm_xml_attr_int (attrs
, "Major", &major
))
546 else if (gnm_xml_attr_int (attrs
, "Minor", &minor
))
550 version
= (epoch
* 100 + major
) * 100 + minor
;
551 if (state
->version
== GNM_XML_UNKNOWN
&& version
>= 10700) {
552 if (version
>= 11221)
553 state
->version
= GNM_XML_V14
;
554 else if (version
>= 10707)
555 state
->version
= GNM_XML_V13
;
556 else if (version
>= 10705)
557 state
->version
= GNM_XML_V12
;
558 else if (version
>= 10700)
559 state
->version
= GNM_XML_V11
;
564 xml_sax_wb_sheetsize (GsfXMLIn
*xin
, xmlChar
const **attrs
)
566 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
568 /* Defaults for legacy files. */
569 state
->sheet_cols
= 256;
570 state
->sheet_rows
= 65536;
571 state
->sheet_type
= GNM_SHEET_DATA
;
573 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
574 if (gnm_xml_attr_int (attrs
, "gnm:Cols", &state
->sheet_cols
))
576 else if (gnm_xml_attr_int (attrs
, "gnm:Rows", &state
->sheet_rows
))
578 else if (!strcmp (CXML2C (attrs
[0]), "gnm:SheetType") &&
579 !strcmp (CXML2C (attrs
[1]), "object"))
580 state
->sheet_type
= GNM_SHEET_OBJECT
;
582 unknown_attr (xin
, attrs
);
587 xml_sax_wb_sheetname (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
589 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
590 char const *name
= xin
->content
->str
;
591 Workbook
*wb
= state
->wb
;
593 g_return_if_fail (name
!= NULL
);
595 if (NULL
== workbook_sheet_by_name (wb
, name
)) {
598 if (!gnm_sheet_valid_size (state
->sheet_cols
,
599 state
->sheet_rows
)) {
600 gnm_sheet_suggest_size (&state
->sheet_cols
,
604 sheet
= sheet_new_with_type (wb
, name
,
608 workbook_sheet_attach (wb
, sheet
);
613 xml_sax_wb_view (GsfXMLIn
*xin
, xmlChar
const **attrs
)
615 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
618 int width
= -1, height
= -1;
620 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
621 if (gnm_xml_attr_int (attrs
, "SelectedTab", &sheet_index
)) {
622 Sheet
*sheet
= workbook_sheet_by_index (state
->wb
,
625 wb_view_sheet_focus (state
->wb_view
, sheet
);
627 else if (gnm_xml_attr_int (attrs
, "Width", &width
)) ;
628 else if (gnm_xml_attr_int (attrs
, "Height", &height
)) ;
630 unknown_attr (xin
, attrs
);
632 if (width
> 0 && height
> 0)
633 wb_view_preferred_size (state
->wb_view
, width
, height
);
636 xml_sax_calculation (GsfXMLIn
*xin
, xmlChar
const **attrs
)
638 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
643 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
644 if (gnm_xml_attr_bool (attrs
, "ManualRecalc", &b
))
645 workbook_set_recalcmode (state
->wb
, !b
);
646 else if (gnm_xml_attr_bool (attrs
, "EnableIteration", &b
))
647 workbook_iteration_enabled (state
->wb
, b
);
648 else if (gnm_xml_attr_int (attrs
, "MaxIterations", &i
))
649 workbook_iteration_max_number (state
->wb
, i
);
650 else if (gnm_xml_attr_double (attrs
, "IterationTolerance", &d
))
651 workbook_iteration_tolerance (state
->wb
, d
);
652 else if (strcmp (CXML2C (attrs
[0]), "DateConvention") == 0) {
653 GODateConventions
const *date_conv
=
654 go_date_conv_from_str (CXML2C (attrs
[1]));
656 workbook_set_date_conv (state
->wb
, date_conv
);
658 g_printerr ("Ignoring invalid date conventions.\n");
660 unknown_attr (xin
, attrs
);
664 xml_sax_old_dateconvention (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
666 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
667 workbook_set_1904 (state
->wb
, strcmp (xin
->content
->str
, "1904") == 0);
671 xml_sax_finish_parse_wb_attr (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
673 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
675 if (state
->attribute
.name
&& state
->attribute
.value
) {
676 wb_view_set_attribute (state
->wb_view
,
677 state
->attribute
.name
,
678 state
->attribute
.value
);
680 xml_sax_barf (G_STRFUNC
, _("workbook view attribute is incomplete"));
683 g_free (state
->attribute
.value
); state
->attribute
.value
= NULL
;
684 g_free (state
->attribute
.name
); state
->attribute
.name
= NULL
;
688 xml_sax_attr_elem (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
690 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
692 char const *content
= xin
->content
->str
;
693 int const len
= xin
->content
->len
;
695 switch (xin
->node
->user_data
.v_int
) {
697 g_return_if_fail (state
->attribute
.name
== NULL
);
698 state
->attribute
.name
= g_strndup (content
, len
);
702 g_return_if_fail (state
->attribute
.value
== NULL
);
703 state
->attribute
.value
= g_strndup (content
, len
);
707 g_assert_not_reached ();
712 xml_sax_sheet_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
714 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
718 GnmColor
*color
= NULL
;
720 state
->hide_col_header
= state
->hide_row_header
=
721 state
->display_formulas
= state
->hide_zero
=
722 state
->hide_grid
= state
->display_outlines
=
723 state
->outline_symbols_below
= state
->outline_symbols_right
=
724 state
->text_is_rtl
= state
->is_protected
= -1;
725 state
->expr_conv_name
= NULL
;
726 state
->visibility
= GNM_SHEET_VISIBILITY_VISIBLE
;
727 state
->tab_color
= NULL
;
728 state
->tab_text_color
= NULL
;
729 state
->grid_color
= NULL
;
730 state
->sheet_zoom
= 1.; /* default */
732 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
733 if (gnm_xml_attr_bool (attrs
, "DisplayFormulas", &tmp
))
734 state
->display_formulas
= tmp
;
735 else if (gnm_xml_attr_bool (attrs
, "HideZero", &tmp
))
736 state
->hide_zero
= tmp
;
737 else if (gnm_xml_attr_bool (attrs
, "HideGrid", &tmp
))
738 state
->hide_grid
= tmp
;
739 else if (gnm_xml_attr_bool (attrs
, "HideColHeader", &tmp
))
740 state
->hide_col_header
= tmp
;
741 else if (gnm_xml_attr_bool (attrs
, "HideRowHeader", &tmp
))
742 state
->hide_row_header
= tmp
;
743 else if (gnm_xml_attr_bool (attrs
, "DisplayOutlines", &tmp
))
744 state
->display_outlines
= tmp
;
745 else if (gnm_xml_attr_bool (attrs
, "OutlineSymbolsBelow", &tmp
))
746 state
->outline_symbols_below
= tmp
;
747 else if (gnm_xml_attr_bool (attrs
, "OutlineSymbolsRight", &tmp
))
748 state
->outline_symbols_right
= tmp
;
749 else if (xml_sax_attr_enum (attrs
, "Visibility", GNM_SHEET_VISIBILITY_TYPE
, &tmpi
))
750 state
->visibility
= tmpi
;
751 else if (gnm_xml_attr_bool (attrs
, "RTL_Layout", &tmp
))
752 state
->text_is_rtl
= tmp
;
753 else if (gnm_xml_attr_bool (attrs
, "Protected", &tmp
))
754 state
->is_protected
= tmp
;
755 else if (strcmp (CXML2C (attrs
[0]), "ExprConvention") == 0)
756 state
->expr_conv_name
= g_strdup (attrs
[1]);
757 else if (xml_sax_attr_color (attrs
, "TabColor", &color
))
758 state
->tab_color
= color
;
759 else if (xml_sax_attr_color (attrs
, "TabTextColor", &color
))
760 state
->tab_text_color
= color
;
761 else if (xml_sax_attr_color (attrs
, "GridColor", &color
))
762 state
->grid_color
= color
;
764 unknown_attr (xin
, attrs
);
768 xml_sax_must_have_sheet (XMLSaxParseState
*state
)
774 xml_sax_barf (G_STRFUNC
, "sheet should have been named");
776 state
->sheet
= workbook_sheet_add (state
->wb
, -1,
784 xml_sax_must_have_style (XMLSaxParseState
*state
)
787 xml_sax_barf (G_STRFUNC
, "style should have been started");
788 state
->style
= (state
->version
>= GNM_XML_V6
||
789 state
->version
<= GNM_XML_V2
)
790 ? gnm_style_new_default ()
799 xml_sax_sheet_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
801 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
803 xml_sax_must_have_sheet (state
);
805 /* Init ColRowInfo's size_pixels and force a full respan */
806 g_object_set (state
->sheet
, "zoom-factor", state
->sheet_zoom
, NULL
);
807 sheet_flag_recompute_spans (state
->sheet
);
812 xml_sax_sheet_name (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
814 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
819 char const * content
= xin
->content
->str
;
820 g_return_if_fail (state
->sheet
== NULL
);
822 /* * FIXME: Pull this out at some point, so we don't
823 * have to support < GNM_XML_V7 anymore
825 if (state
->version
>= GNM_XML_V7
) {
826 sheet
= workbook_sheet_by_name (state
->wb
, content
);
828 go_io_error_string (state
->context
,
829 _("File has inconsistent SheetNameIndex element."));
830 sheet
= sheet_new (state
->wb
, content
,
832 workbook_sheet_attach (state
->wb
, sheet
);
835 sheet
= sheet_new (state
->wb
, content
, columns
, rows
);
836 workbook_sheet_attach (state
->wb
, sheet
);
838 state
->sheet
= sheet
;
840 if (state
->display_formulas
>= 0)
841 g_object_set (sheet
, "display-formulas", state
->display_formulas
, NULL
);
842 if (state
->hide_zero
>= 0)
843 g_object_set (sheet
, "display-zeros", !state
->hide_zero
, NULL
);
844 if (state
->hide_grid
>= 0)
845 g_object_set (sheet
, "display-grid", !state
->hide_grid
, NULL
);
846 if (state
->hide_col_header
>= 0)
847 g_object_set (sheet
, "display-column-header", !state
->hide_col_header
, NULL
);
848 if (state
->hide_row_header
>= 0)
849 g_object_set (sheet
, "display-row-header", !state
->hide_row_header
, NULL
);
850 if (state
->display_outlines
>= 0)
851 g_object_set (sheet
, "display-outlines", state
->display_outlines
, NULL
);
852 if (state
->outline_symbols_below
>= 0)
853 g_object_set (sheet
, "display-outlines-below", state
->outline_symbols_below
, NULL
);
854 if (state
->outline_symbols_right
>= 0)
855 g_object_set (sheet
, "display-outlines-right", state
->outline_symbols_right
, NULL
);
856 if (state
->text_is_rtl
>= 0)
857 g_object_set (sheet
, "text-is-rtl", state
->text_is_rtl
, NULL
);
858 if (state
->is_protected
>= 0)
859 g_object_set (sheet
, "protected", state
->is_protected
, NULL
);
860 if (state
->expr_conv_name
!= NULL
) {
861 GnmConventions
const *convs
= gnm_conventions_default
;
862 if (0 == strcmp (state
->expr_conv_name
, "gnumeric:R1C1"))
863 convs
= gnm_conventions_xls_r1c1
;
864 g_object_set (sheet
, "conventions", convs
, NULL
);
866 g_free (state
->expr_conv_name
);
867 state
->expr_conv_name
= NULL
;
869 g_object_set (sheet
, "visibility", state
->visibility
, NULL
);
870 sheet
->tab_color
= state
->tab_color
;
871 sheet
->tab_text_color
= state
->tab_text_color
;
872 if (state
->grid_color
)
873 sheet_style_set_auto_pattern_color (sheet
, state
->grid_color
);
877 xml_sax_sheet_zoom (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
879 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
881 char const * content
= xin
->content
->str
;
884 xml_sax_must_have_sheet (state
);
886 if (xml_sax_double ((xmlChar
*)content
, &zoom
))
887 state
->sheet_zoom
= zoom
;
891 xml_sax_print_margins_unit (GsfXMLIn
*xin
, xmlChar
const **attrs
,
892 double *points
, GtkUnit
*desired_display
)
894 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
896 if (gnm_xml_attr_double (attrs
, "Points", &pts
)) {
898 } else if (attr_eq (attrs
[0], "PrefUnit")) {
899 *desired_display
= unit_name_to_unit (CXML2C (attrs
[1]));
901 unknown_attr (xin
, attrs
);
906 xml_sax_print_margins (GsfXMLIn
*xin
, xmlChar
const **attrs
)
908 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
910 GnmPrintInformation
*pi
;
913 xml_sax_must_have_sheet (state
);
915 pi
= state
->sheet
->print_info
;
916 switch (xin
->node
->user_data
.v_int
) {
918 xml_sax_print_margins_unit (xin
, attrs
,
920 &pi
->desired_display
.header
);
922 print_info_set_edge_to_below_header (pi
, points
);
925 xml_sax_print_margins_unit (xin
, attrs
,
927 &pi
->desired_display
.footer
);
929 print_info_set_edge_to_above_footer (pi
, points
);
932 xml_sax_print_margins_unit (xin
, attrs
,
933 &points
, &pi
->desired_display
.left
);
935 print_info_set_margin_left (pi
, points
);
938 xml_sax_print_margins_unit (xin
, attrs
,
939 &points
, &pi
->desired_display
.right
);
941 print_info_set_margin_right (pi
, points
);
944 xml_sax_print_margins_unit (xin
, attrs
,
945 &points
, &pi
->desired_display
.top
);
947 print_info_set_margin_header (pi
, points
);
950 xml_sax_print_margins_unit (xin
, attrs
,
951 &points
, &pi
->desired_display
.bottom
);
953 print_info_set_margin_footer (pi
, points
);
962 xml_sax_page_break (GsfXMLIn
*xin
, xmlChar
const **attrs
)
964 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
965 GnmPageBreakType type
= GNM_PAGE_BREAK_NONE
;
968 if (NULL
== state
->page_breaks
)
971 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
972 if (gnm_xml_attr_int (attrs
, "pos", &pos
)) ;
973 else if (!strcmp (CXML2C (attrs
[0]), "type"))
974 type
= gnm_page_break_type_from_str (CXML2C (attrs
[1]));
976 /* drops invalid positions */
977 gnm_page_breaks_append_break (state
->page_breaks
, pos
, type
);
981 xml_sax_page_breaks_begin (GsfXMLIn
*xin
, G_GNUC_UNUSED xmlChar
const **attrs
)
983 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
984 xml_sax_must_have_sheet (state
);
985 g_return_if_fail (state
->page_breaks
== NULL
);
986 state
->page_breaks
= gnm_page_breaks_new (xin
->node
->user_data
.v_int
);
990 xml_sax_page_breaks_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
992 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
994 if (NULL
!= state
->page_breaks
) {
995 print_info_set_breaks (state
->sheet
->print_info
,
997 state
->page_breaks
= NULL
;
1002 xml_sax_print_scale (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1004 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1006 GnmPrintInformation
*pi
;
1010 xml_sax_must_have_sheet (state
);
1012 pi
= state
->sheet
->print_info
;
1013 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1014 if (attr_eq (attrs
[0], "type"))
1015 pi
->scaling
.type
= !strcmp (CXML2C (attrs
[1]), "percentage")
1016 ? PRINT_SCALE_PERCENTAGE
: PRINT_SCALE_FIT_PAGES
;
1017 else if (gnm_xml_attr_double (attrs
, "percentage", &percentage
))
1018 pi
->scaling
.percentage
.x
= pi
->scaling
.percentage
.y
= percentage
;
1019 else if (gnm_xml_attr_int (attrs
, "cols", &cols
))
1020 pi
->scaling
.dim
.cols
= cols
;
1021 else if (gnm_xml_attr_int (attrs
, "rows", &rows
))
1022 pi
->scaling
.dim
.rows
= rows
;
1027 xml_sax_print_vcenter (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1029 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1030 GnmPrintInformation
*pi
;
1033 xml_sax_must_have_sheet (state
);
1035 pi
= state
->sheet
->print_info
;
1037 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1038 if (gnm_xml_attr_int (attrs
, "value", &val
))
1039 pi
->center_vertically
= val
;
1043 xml_sax_print_hcenter (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1045 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1046 GnmPrintInformation
*pi
;
1049 xml_sax_must_have_sheet (state
);
1051 pi
= state
->sheet
->print_info
;
1053 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1054 if (gnm_xml_attr_int (attrs
, "value", &val
))
1055 pi
->center_horizontally
= val
;
1059 xml_sax_print_grid (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1061 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1062 GnmPrintInformation
*pi
;
1065 xml_sax_must_have_sheet (state
);
1067 pi
= state
->sheet
->print_info
;
1069 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1070 if (gnm_xml_attr_int (attrs
, "value", &val
))
1071 pi
->print_grid_lines
= val
;
1075 xml_sax_print_do_not_print (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1077 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1078 GnmPrintInformation
*pi
;
1081 xml_sax_must_have_sheet (state
);
1083 pi
= state
->sheet
->print_info
;
1085 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1086 if (gnm_xml_attr_int (attrs
, "value", &val
))
1087 pi
->do_not_print
= val
;
1091 xml_sax_print_print_range (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1093 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1094 GnmPrintInformation
*pi
;
1097 xml_sax_must_have_sheet (state
);
1099 pi
= state
->sheet
->print_info
;
1101 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1102 if (xml_sax_attr_enum (attrs
, "value", GNM_PRINT_RANGE_TYPE
,
1104 print_info_set_printrange (pi
, val
);
1110 xml_sax_monochrome (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1112 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1113 GnmPrintInformation
*pi
;
1116 xml_sax_must_have_sheet (state
);
1118 pi
= state
->sheet
->print_info
;
1120 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1121 if (gnm_xml_attr_int (attrs
, "value", &val
))
1122 pi
->print_black_and_white
= val
;
1126 xml_sax_print_titles (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1128 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1129 GnmPrintInformation
*pi
;
1132 xml_sax_must_have_sheet (state
);
1134 pi
= state
->sheet
->print_info
;
1136 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1137 if (gnm_xml_attr_int (attrs
, "value", &val
))
1138 pi
->print_titles
= val
;
1142 xml_sax_repeat_top (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1144 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1145 GnmPrintInformation
*pi
;
1147 xml_sax_must_have_sheet (state
);
1149 pi
= state
->sheet
->print_info
;
1151 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1152 if (!strcmp (CXML2C (attrs
[0]), "value")) {
1153 g_free (pi
->repeat_top
);
1154 pi
->repeat_top
= g_strdup (CXML2C (attrs
[1]));
1160 xml_sax_repeat_left (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1162 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1163 GnmPrintInformation
*pi
;
1165 xml_sax_must_have_sheet (state
);
1167 pi
= state
->sheet
->print_info
;
1169 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1170 if (!strcmp (CXML2C (attrs
[0]), "value")) {
1171 g_free (pi
->repeat_left
);
1172 pi
->repeat_left
= g_strdup (CXML2C (attrs
[1]));
1178 xml_sax_print_hf (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1180 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1181 GnmPrintInformation
*pi
;
1184 xml_sax_must_have_sheet (state
);
1186 pi
= state
->sheet
->print_info
;
1188 switch (xin
->node
->user_data
.v_int
) {
1199 g_return_if_fail (hf
!= NULL
);
1201 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1202 if ( attr_eq (attrs
[0], "Left")) {
1203 g_free (hf
->left_format
);
1204 hf
->left_format
= g_strdup (CXML2C (attrs
[1]));
1205 } else if (attr_eq (attrs
[0], "Middle")) {
1206 g_free (hf
->middle_format
);
1207 hf
->middle_format
= g_strdup (CXML2C (attrs
[1]));
1208 } else if (attr_eq (attrs
[0], "Right")) {
1209 g_free (hf
->right_format
);
1210 hf
->right_format
= g_strdup (CXML2C (attrs
[1]));
1212 unknown_attr (xin
, attrs
);
1218 xml_sax_even_if_only_styles (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1220 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1221 GnmPrintInformation
*pi
;
1224 xml_sax_must_have_sheet (state
);
1226 pi
= state
->sheet
->print_info
;
1228 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1229 if (gnm_xml_attr_int (attrs
, "value", &val
))
1230 pi
->print_even_if_only_styles
= val
;
1237 xml_sax_selection_range (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1239 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1242 xml_sax_must_have_sheet (state
);
1243 if (xml_sax_attr_range (attrs
, &r
))
1244 sv_selection_add_range (
1245 sheet_get_view (state
->sheet
, state
->wb_view
), &r
);
1249 xml_sax_selection (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1251 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1252 Sheet
*sheet
= xml_sax_must_have_sheet (state
);
1253 int col
= -1, row
= -1;
1255 sv_selection_reset (sheet_get_view (sheet
, state
->wb_view
));
1257 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1258 if (gnm_xml_attr_int (attrs
, "CursorCol", &col
)) ;
1259 else if (gnm_xml_attr_int (attrs
, "CursorRow", &row
)) ;
1261 unknown_attr (xin
, attrs
);
1263 XML_CHECK (state
->cell
.col
< 0);
1264 XML_CHECK (state
->cell
.row
< 0);
1266 /* Default in case of error. */
1267 state
->cell
.col
= 0;
1268 state
->cell
.row
= 0;
1270 XML_CHECK (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
));
1271 XML_CHECK (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
));
1273 state
->cell
.col
= col
;
1274 state
->cell
.row
= row
;
1278 xml_sax_selection_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1280 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1282 GnmCellPos
const pos
= state
->cell
;
1283 state
->cell
.col
= state
->cell
.row
= -1;
1284 gnm_sheet_view_set_edit_pos (sheet_get_view (state
->sheet
, state
->wb_view
), &pos
);
1288 xml_sax_sheet_layout (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1290 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1293 xml_sax_must_have_sheet (state
);
1295 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1296 if (xml_sax_attr_cellpos (attrs
, "TopLeft", &tmp
, state
->sheet
))
1297 gnm_sheet_view_set_initial_top_left (
1298 sheet_get_view (state
->sheet
, state
->wb_view
),
1301 unknown_attr (xin
, attrs
);
1305 xml_sax_sheet_freezepanes (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1307 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1308 GnmCellPos frozen_tl
, unfrozen_tl
;
1311 xml_sax_must_have_sheet (state
);
1313 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1314 if (xml_sax_attr_cellpos (attrs
, "FrozenTopLeft", &frozen_tl
, state
->sheet
))
1316 else if (xml_sax_attr_cellpos (attrs
, "UnfrozenTopLeft", &unfrozen_tl
, state
->sheet
))
1319 unknown_attr (xin
, attrs
);
1322 gnm_sheet_view_freeze_panes (sheet_get_view (state
->sheet
, state
->wb_view
),
1323 &frozen_tl
, &unfrozen_tl
);
1327 xml_sax_cols_rows (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1329 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1331 gboolean
const is_col
= xin
->node
->user_data
.v_bool
;
1333 xml_sax_must_have_sheet (state
);
1335 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1336 if (gnm_xml_attr_double (attrs
, "DefaultSizePts", &def_size
)) {
1338 sheet_col_set_default_size_pts (state
->sheet
, def_size
);
1340 sheet_row_set_default_size_pts (state
->sheet
, def_size
);
1345 xml_sax_colrow (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1347 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1349 ColRowInfo
*cri
= NULL
;
1352 int hidden
= 0, hard_size
= 0, is_collapsed
= 0, outline_level
= 0;
1354 gboolean
const is_col
= xin
->node
->user_data
.v_bool
;
1355 Sheet
*sheet
= xml_sax_must_have_sheet (state
);
1357 maybe_update_progress (xin
);
1359 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1360 if (gnm_xml_attr_int (attrs
, "No", &pos
)) ;
1361 else if (gnm_xml_attr_double (attrs
, "Unit", &size
)) ;
1362 else if (gnm_xml_attr_int (attrs
, "Count", &count
)) ;
1363 else if (gnm_xml_attr_int (attrs
, "HardSize", &hard_size
)) ;
1364 else if (gnm_xml_attr_int (attrs
, "Hidden", &hidden
)) ;
1365 else if (gnm_xml_attr_int (attrs
, "Collapsed", &is_collapsed
)) ;
1366 else if (gnm_xml_attr_int (attrs
, "OutlineLevel", &outline_level
)) ;
1367 else if (gnm_xml_attr_int (attrs
, "MarginA", &val
))
1368 ; /* deprecated in 1.7.1 */
1369 else if (gnm_xml_attr_int (attrs
, "MarginB", &val
))
1370 ; /* deprecated in 1.7.1 */
1372 unknown_attr (xin
, attrs
);
1375 XML_CHECK (size
> -1);
1376 XML_CHECK (pos
>= 0 && pos
< colrow_max (is_col
, sheet
));
1377 XML_CHECK (count
>= 1);
1378 XML_CHECK (count
<= colrow_max (is_col
, sheet
) - pos
);
1381 ? sheet_col_fetch (state
->sheet
, pos
)
1382 : sheet_row_fetch (state
->sheet
, pos
);
1383 cri
->hard_size
= hard_size
;
1384 cri
->visible
= !hidden
;
1385 cri
->is_collapsed
= is_collapsed
;
1386 cri
->outline_level
= outline_level
;
1389 sheet_col_set_size_pts (state
->sheet
, pos
, size
, cri
->hard_size
);
1390 if (state
->sheet
->cols
.max_outline_level
< cri
->outline_level
)
1391 state
->sheet
->cols
.max_outline_level
= cri
->outline_level
;
1392 /* resize flags are already set only need to copy the sizes */
1394 col_row_info_copy (sheet_col_fetch (state
->sheet
, ++pos
), cri
);
1396 sheet_row_set_size_pts (state
->sheet
, pos
, size
, cri
->hard_size
);
1397 if (state
->sheet
->rows
.max_outline_level
< cri
->outline_level
)
1398 state
->sheet
->rows
.max_outline_level
= cri
->outline_level
;
1399 /* resize flags are already set only need to copy the sizes */
1401 col_row_info_copy (sheet_row_fetch (state
->sheet
, ++pos
), cri
);
1406 xml_sax_style_region_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1408 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1410 g_return_if_fail (state
->style_range_init
== FALSE
);
1411 g_return_if_fail (state
->style
== NULL
);
1413 if (attrs
== NULL
) {
1414 g_warning ("Invalid tag: gnm:StyleRegion start tag without attributes");
1418 state
->style
= (state
->version
>= GNM_XML_V6
||
1419 state
->version
<= GNM_XML_V2
)
1420 ? gnm_style_new_default ()
1423 state
->style_range_init
=
1424 xml_sax_attr_range (attrs
, &state
->style_range
);
1428 xml_sax_style_region_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1430 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1432 if (!state
->style_range_init
) {
1433 xml_sax_barf (G_STRFUNC
, "style region must have range");
1434 range_init (&state
->style_range
, 0, 0, 0, 0);
1435 state
->style_range_init
= TRUE
;
1438 xml_sax_must_have_style (state
);
1439 xml_sax_must_have_sheet (state
);
1441 if (state
->clipboard
) {
1442 GnmCellRegion
*cr
= state
->clipboard
;
1443 GnmStyleRegion
*sr
= g_new (GnmStyleRegion
, 1);
1445 sr
->range
= state
->style_range
;
1446 sr
->style
= state
->style
;
1448 cr
->styles
= g_slist_prepend (cr
->styles
, sr
);
1449 } else if (state
->version
>= GNM_XML_V6
|| state
->version
<= GNM_XML_V2
)
1450 sheet_style_set_range (state
->sheet
, &state
->style_range
,
1453 sheet_style_apply_range (state
->sheet
, &state
->style_range
,
1456 state
->style_range_init
= FALSE
;
1457 state
->style
= NULL
;
1459 maybe_update_progress (xin
);
1463 xml_sax_style_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1465 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1470 xml_sax_must_have_style (state
);
1472 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1473 if (xml_sax_attr_enum (attrs
, "HAlign", GNM_ALIGN_H_TYPE
, &val
))
1474 gnm_style_set_align_h (state
->style
, val
);
1475 else if (xml_sax_attr_enum (attrs
, "VAlign", GNM_ALIGN_V_TYPE
, &val
))
1476 gnm_style_set_align_v (state
->style
, val
);
1478 /* Pre version V6 */
1479 else if (gnm_xml_attr_int (attrs
, "Fit", &val
))
1480 gnm_style_set_wrap_text (state
->style
, val
);
1482 else if (gnm_xml_attr_int (attrs
, "WrapText", &val
))
1483 gnm_style_set_wrap_text (state
->style
, val
);
1484 else if (gnm_xml_attr_bool (attrs
, "ShrinkToFit", &val
))
1485 gnm_style_set_shrink_to_fit (state
->style
, val
);
1486 else if (gnm_xml_attr_int (attrs
, "Rotation", &val
)) {
1487 /* Work around a bug pre 1.5.1 that would allow
1488 * negative rotations. -1 == vertical, map everything
1489 * else back onto 0..359 */
1492 gnm_style_set_rotation (state
->style
, val
);
1493 } else if (gnm_xml_attr_int (attrs
, "Shade", &val
))
1494 gnm_style_set_pattern (state
->style
, val
);
1495 else if (gnm_xml_attr_int (attrs
, "Indent", &val
))
1496 gnm_style_set_indent (state
->style
, val
);
1497 else if (xml_sax_attr_color (attrs
, "Fore", &colour
))
1498 gnm_style_set_font_color (state
->style
, colour
);
1499 else if (xml_sax_attr_color (attrs
, "Back", &colour
))
1500 gnm_style_set_back_color (state
->style
, colour
);
1501 else if (xml_sax_attr_color (attrs
, "PatternColor", &colour
))
1502 gnm_style_set_pattern_color (state
->style
, colour
);
1503 else if (attr_eq (attrs
[0], "Format")) {
1504 GOFormat
*fmt
= make_format (CXML2C (attrs
[1]));
1506 gnm_style_set_format (state
->style
, fmt
);
1507 go_format_unref (fmt
);
1510 else if (gnm_xml_attr_int (attrs
, "Hidden", &val
))
1511 gnm_style_set_contents_hidden (state
->style
, val
);
1512 else if (gnm_xml_attr_int (attrs
, "Locked", &val
))
1513 gnm_style_set_contents_locked (state
->style
, val
);
1514 else if (gnm_xml_attr_int (attrs
, "Orient", &val
))
1515 ; /* ignore old useless attribute */
1517 unknown_attr (xin
, attrs
);
1522 xml_sax_style_font (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1524 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1526 double size_pts
= 10.;
1529 xml_sax_must_have_style (state
);
1531 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1532 if (gnm_xml_attr_double (attrs
, "Unit", &size_pts
)) {
1533 if (!(size_pts
>= 1.0))
1534 xml_sax_barf (G_STRFUNC
, "size_pts >= 1");
1536 gnm_style_set_font_size (state
->style
, size_pts
);
1537 } else if (gnm_xml_attr_int (attrs
, "Bold", &val
))
1538 gnm_style_set_font_bold (state
->style
, val
);
1539 else if (gnm_xml_attr_int (attrs
, "Italic", &val
))
1540 gnm_style_set_font_italic (state
->style
, val
);
1541 else if (gnm_xml_attr_int (attrs
, "Underline", &val
))
1542 gnm_style_set_font_uline (state
->style
, (GnmUnderline
)val
);
1543 else if (gnm_xml_attr_int (attrs
, "StrikeThrough", &val
))
1544 gnm_style_set_font_strike (state
->style
, val
);
1545 else if (gnm_xml_attr_int (attrs
, "Script", &val
)) {
1547 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_STANDARD
);
1549 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_SUB
);
1551 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_SUPER
);
1553 unknown_attr (xin
, attrs
);
1558 font_component (char const *fontname
, int idx
)
1561 char const *p
= fontname
;
1563 for (; *p
&& i
< idx
; p
++) {
1574 * style_font_read_from_x11:
1575 * @mstyle: the style to setup to this font.
1576 * @fontname: an X11-like font name.
1578 * Tries to guess the fontname, the weight and italization parameters
1581 * Returns: A valid style font.
1584 style_font_read_from_x11 (GnmStyle
*mstyle
, char const *fontname
)
1588 /* FIXME: we should do something about the typeface instead
1589 * of hardcoding it to helvetica.
1591 c
= font_component (fontname
, 2);
1592 if (strncmp (c
, "bold", 4) == 0)
1593 gnm_style_set_font_bold (mstyle
, TRUE
);
1595 c
= font_component (fontname
, 3);
1596 if (strncmp (c
, "o", 1) == 0)
1597 gnm_style_set_font_italic (mstyle
, TRUE
);
1599 if (strncmp (c
, "i", 1) == 0)
1600 gnm_style_set_font_italic (mstyle
, TRUE
);
1604 xml_sax_style_font_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1606 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1608 xml_sax_must_have_style (state
);
1610 if (xin
->content
->len
> 0) {
1611 char const * content
= xin
->content
->str
;
1612 if (*content
== '-')
1613 style_font_read_from_x11 (state
->style
, content
);
1615 gnm_style_set_font_name (state
->style
, content
);
1620 xml_sax_validation (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1622 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1627 g_return_if_fail (state
->validation
.title
== NULL
);
1628 g_return_if_fail (state
->validation
.msg
== NULL
);
1629 g_return_if_fail (state
->validation
.texpr
[0] == NULL
);
1630 g_return_if_fail (state
->validation
.texpr
[1] == NULL
);
1632 state
->validation
.style
= GNM_VALIDATION_STYLE_NONE
;
1633 state
->validation
.type
= GNM_VALIDATION_TYPE_ANY
;
1634 state
->validation
.op
= GNM_VALIDATION_OP_NONE
;
1635 state
->validation
.allow_blank
= TRUE
;
1636 state
->validation
.use_dropdown
= FALSE
;
1638 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1639 if (xml_sax_attr_enum (attrs
, "Style",
1640 GNM_VALIDATION_STYLE_TYPE
,
1642 state
->validation
.style
= dummy
;
1643 } else if (xml_sax_attr_enum (attrs
, "Type",
1644 GNM_VALIDATION_TYPE_TYPE
,
1646 state
->validation
.type
= dummy
;
1647 } else if (xml_sax_attr_enum (attrs
, "Operator",
1648 GNM_VALIDATION_OP_TYPE
,
1650 state
->validation
.op
= dummy
;
1651 } else if (attr_eq (attrs
[0], "Title")) {
1652 state
->validation
.title
= g_strdup (CXML2C (attrs
[1]));
1653 } else if (attr_eq (attrs
[0], "Message")) {
1654 state
->validation
.msg
= g_strdup (CXML2C (attrs
[1]));
1655 } else if (gnm_xml_attr_bool (attrs
, "AllowBlank", &b_dummy
)) {
1656 state
->validation
.allow_blank
= b_dummy
;
1657 } else if (gnm_xml_attr_bool (attrs
, "UseDropdown", &b_dummy
)) {
1658 state
->validation
.use_dropdown
= b_dummy
;
1660 unknown_attr (xin
, attrs
);
1665 xml_sax_validation_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1667 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1669 xml_sax_must_have_style (state
);
1671 gnm_style_set_validation (state
->style
,
1672 gnm_validation_new (state
->validation
.style
,
1673 state
->validation
.type
,
1674 state
->validation
.op
,
1676 state
->validation
.title
,
1677 state
->validation
.msg
,
1678 state
->validation
.texpr
[0],
1679 state
->validation
.texpr
[1],
1680 state
->validation
.allow_blank
,
1681 state
->validation
.use_dropdown
));
1683 g_free (state
->validation
.title
);
1684 state
->validation
.title
= NULL
;
1685 g_free (state
->validation
.msg
);
1686 state
->validation
.msg
= NULL
;
1687 state
->validation
.texpr
[0] = state
->validation
.texpr
[1] = NULL
;
1691 xml_sax_validation_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1693 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1695 int const i
= xin
->node
->user_data
.v_int
;
1696 GnmExprTop
const *texpr
;
1699 g_return_if_fail (state
->validation
.texpr
[i
] == NULL
);
1701 texpr
= gnm_expr_parse_str (xin
->content
->str
,
1702 parse_pos_init_sheet (&pos
, state
->sheet
),
1703 GNM_EXPR_PARSE_DEFAULT
,
1707 g_return_if_fail (texpr
!= NULL
);
1709 state
->validation
.texpr
[i
] = texpr
;
1713 xml_sax_condition (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1715 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1716 GnmStyleCondOp op
= GNM_STYLE_COND_CUSTOM
;
1718 g_return_if_fail (state
->cond
== NULL
);
1719 g_return_if_fail (state
->cond_save_style
== NULL
);
1721 xml_sax_must_have_style (state
);
1723 state
->cond_save_style
= state
->style
;
1724 state
->style
= gnm_style_new ();
1726 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1729 if (gnm_xml_attr_int (attrs
, "Operator", &dummy
))
1732 unknown_attr (xin
, attrs
);
1735 state
->cond
= gnm_style_cond_new (op
, state
->sheet
);
1739 xml_sax_condition_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1741 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1742 GnmStyleConditions
*sc
;
1744 xml_sax_must_have_style (state
);
1745 g_return_if_fail (state
->cond_save_style
!= NULL
);
1746 g_return_if_fail (state
->cond
!= NULL
);
1748 gnm_style_cond_set_overlay (state
->cond
, state
->style
);
1749 gnm_style_unref (state
->style
);
1750 state
->style
= state
->cond_save_style
;
1751 state
->cond_save_style
= NULL
;
1753 if (!gnm_style_is_element_set (state
->style
, MSTYLE_CONDITIONS
) ||
1754 NULL
== (sc
= gnm_style_get_conditions (state
->style
)))
1755 gnm_style_set_conditions (state
->style
,
1756 (sc
= gnm_style_conditions_new (state
->sheet
)));
1757 gnm_style_conditions_insert (sc
, state
->cond
, -1);
1759 gnm_style_cond_free (state
->cond
);
1764 * We have been saving expressions relative to A1. This means that when we
1765 * read, we see a relative reference to a cell above as R[65535]C. This
1766 * function patches that to R[-1]C.
1768 * We ought to fix the format, but then old Gnumerics couldn't read new
1769 * files. In fact, if we just added a "Position" attribute then we would
1770 * get silent corruption.
1772 static GnmExpr
const *
1773 cond_patchup (GnmExpr
const *expr
, GnmExprWalk
*data
)
1775 XMLSaxParseState
*state
= data
->user
;
1776 GnmCellPos
const *pos
= &state
->style_range
.start
;
1777 GnmCellRef
const *oref
= gnm_expr_get_cellref (expr
);
1778 GnmValue
const *ocst
= gnm_expr_get_constant (expr
);
1782 GnmCellRef tref
= *oref
;
1783 gnm_cellpos_init_cellref (&tpos
, oref
, pos
, state
->sheet
);
1784 if (tref
.col_relative
)
1785 tref
.col
= tpos
.col
- pos
->col
;
1786 if (tref
.row_relative
)
1787 tref
.row
= tpos
.row
- pos
->row
;
1788 if (gnm_cellref_equal (&tref
, oref
))
1790 return gnm_expr_new_cellref (&tref
);
1793 if (ocst
&& VALUE_IS_CELLRANGE (ocst
)) {
1794 GnmRangeRef
const *oref
= value_get_rangeref (ocst
);
1795 GnmRangeRef tref
= *oref
;
1797 Sheet
*start_sheet
, *end_sheet
;
1800 eval_pos_init_pos (&ep
, state
->sheet
, pos
);
1801 gnm_rangeref_normalize (oref
, &ep
, &start_sheet
, &end_sheet
,
1803 if (tref
.a
.col_relative
)
1804 tref
.a
.col
= trange
.start
.col
- pos
->col
;
1805 if (tref
.a
.row_relative
)
1806 tref
.a
.row
= trange
.start
.row
- pos
->row
;
1807 if (tref
.b
.col_relative
)
1808 tref
.b
.col
= trange
.end
.col
- pos
->col
;
1809 if (tref
.b
.row_relative
)
1810 tref
.b
.row
= trange
.end
.row
- pos
->row
;
1811 if (gnm_rangeref_equal (&tref
, oref
))
1813 return gnm_expr_new_constant (value_new_cellrange_unsafe (&tref
.a
, &tref
.b
));
1820 xml_sax_condition_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1822 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1824 int const i
= xin
->node
->user_data
.v_int
;
1825 GnmExprTop
const *texpr
;
1827 GnmExpr
const *patched_expr
;
1829 g_return_if_fail (gnm_style_cond_get_expr (state
->cond
, i
) == NULL
);
1831 parse_pos_init_sheet (&pos
, state
->sheet
);
1832 texpr
= gnm_expr_parse_str (xin
->content
->str
,
1834 GNM_EXPR_PARSE_DEFAULT
,
1837 g_return_if_fail (texpr
!= NULL
);
1839 patched_expr
= gnm_expr_walk (texpr
->expr
, cond_patchup
, state
);
1841 gnm_expr_top_unref (texpr
);
1842 texpr
= gnm_expr_top_new (patched_expr
);
1845 gnm_style_cond_set_expr (state
->cond
, texpr
, i
);
1846 gnm_expr_top_unref (texpr
);
1850 xml_sax_hlink (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1852 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1854 char *target
= NULL
;
1857 xml_sax_must_have_style (state
);
1859 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1860 if (attr_eq (attrs
[0], "type"))
1861 type
= g_strdup (CXML2C (attrs
[1]));
1862 else if (attr_eq (attrs
[0], "target"))
1863 target
= g_strdup (CXML2C (attrs
[1]));
1864 else if (attr_eq (attrs
[0], "tip"))
1865 tip
= g_strdup (CXML2C (attrs
[1]));
1867 unknown_attr (xin
, attrs
);
1870 if (NULL
!= type
&& NULL
!= target
) {
1871 GType typ
= g_type_from_name (type
);
1872 GnmHLink
*lnk
= gnm_hlink_new (typ
, state
->sheet
);
1873 gnm_hlink_set_target (lnk
, target
);
1874 gnm_hlink_set_tip (lnk
, tip
);
1875 gnm_style_set_hlink (state
->style
, lnk
);
1884 xml_sax_input_msg (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1886 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1890 xml_sax_must_have_style (state
);
1892 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1893 if (attr_eq (attrs
[0], "Title"))
1894 title
= g_strdup (CXML2C (attrs
[1]));
1895 else if (attr_eq (attrs
[0], "Message"))
1896 msg
= g_strdup (CXML2C (attrs
[1]));
1898 unknown_attr (xin
, attrs
);
1901 if (NULL
!= title
|| NULL
!= msg
)
1902 gnm_style_set_input_msg (state
->style
,
1903 gnm_input_msg_new (msg
, title
));
1909 xml_sax_style_border (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1911 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1914 GnmColor
*colour
= NULL
;
1916 xml_sax_must_have_style (state
);
1918 /* Colour is optional */
1919 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1920 if (xml_sax_attr_color (attrs
, "Color", &colour
)) ;
1921 else if (gnm_xml_attr_int (attrs
, "Style", &pattern
)) ;
1923 unknown_attr (xin
, attrs
);
1926 if (pattern
>= GNM_STYLE_BORDER_NONE
) {
1927 GnmStyleElement
const type
= xin
->node
->user_data
.v_int
;
1928 GnmStyleBorderLocation
const loc
=
1929 GNM_STYLE_BORDER_TOP
+ (int)(type
- MSTYLE_BORDER_TOP
);
1933 * Make sure we have a colour to prevent trouble further
1937 colour
= gnm_color_new_go (GO_COLOR_BLACK
);
1939 border
= gnm_style_border_fetch
1940 ((GnmStyleBorderType
)pattern
, colour
,
1941 gnm_style_border_get_orientation (loc
));
1942 gnm_style_set_border (state
->style
, type
, border
);
1947 xml_sax_cell (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1949 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1950 Sheet
*sheet
= state
->sheet
;
1952 int row
= -1, col
= -1;
1953 int rows
= -1, cols
= -1;
1954 int value_type
= -1;
1955 GOFormat
*value_fmt
= NULL
;
1957 const char *value_result
= NULL
;
1959 g_return_if_fail (state
->cell
.row
== -1);
1960 g_return_if_fail (state
->cell
.col
== -1);
1961 g_return_if_fail (state
->array_rows
== -1);
1962 g_return_if_fail (state
->array_cols
== -1);
1963 g_return_if_fail (state
->expr_id
== -1);
1964 g_return_if_fail (state
->value_type
== -1);
1965 g_return_if_fail (state
->value_result
== NULL
);
1967 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1968 if (gnm_xml_attr_int (attrs
, "Col", &col
)) ;
1969 else if (gnm_xml_attr_int (attrs
, "Row", &row
)) ;
1970 else if (gnm_xml_attr_int (attrs
, "Cols", &cols
)) ;
1971 else if (gnm_xml_attr_int (attrs
, "Rows", &rows
)) ;
1972 else if (gnm_xml_attr_int (attrs
, "ExprID", &expr_id
)) ;
1973 else if (gnm_xml_attr_int (attrs
, "ValueType", &value_type
)) ;
1974 else if (attr_eq (attrs
[0], "Value"))
1975 value_result
= CXML2C (attrs
[1]);
1976 else if (attr_eq (attrs
[0], "ValueFormat")) {
1977 go_format_unref (value_fmt
);
1978 value_fmt
= make_format (CXML2C (attrs
[1]));
1980 unknown_attr (xin
, attrs
);
1983 // Ignore value_result absent a type
1984 if (value_type
== -1)
1985 value_result
= NULL
;
1987 XML_CHECK2 (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
),
1988 go_format_unref (value_fmt
));
1989 XML_CHECK2 (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
),
1990 go_format_unref (value_fmt
));
1992 if (cols
> 0 || rows
> 0) {
1993 /* Both must be valid */
1994 XML_CHECK2 (cols
> 0 && rows
> 0,
1995 go_format_unref (value_fmt
));
1997 state
->array_cols
= cols
;
1998 state
->array_rows
= rows
;
2001 state
->cell
.row
= row
;
2002 state
->cell
.col
= col
;
2003 state
->expr_id
= expr_id
;
2004 state
->value_type
= value_type
;
2005 state
->value_fmt
= value_fmt
;
2006 state
->value_result
= g_strdup (value_result
);
2010 * xml_cell_set_array_expr : Utility routine to parse an expression
2011 * and store it as an array.
2013 * @cell: The upper left hand corner of the array.
2014 * @text: The text to parse.
2015 * @rows: The number of rows.
2016 * @cols: The number of columns.
2019 xml_cell_set_array_expr (XMLSaxParseState
*state
,
2020 GnmCell
*cell
, GnmCellCopy
*cc
, char const *text
,
2021 int const cols
, int const rows
)
2024 GnmExprTop
const *texpr
=
2025 gnm_expr_parse_str (text
,
2026 parse_pos_init_cell (&pp
, cell
),
2027 GNM_EXPR_PARSE_DEFAULT
,
2032 g_return_if_fail (texpr
!= NULL
);
2039 r
.start
= r
.end
= cell
->pos
;
2040 r
.end
.col
+= (cols
- 1);
2041 r
.end
.row
+= (rows
- 1);
2043 if (!gnm_cell_set_array (cell
->base
.sheet
, &r
, texpr
)) {
2044 xml_sax_barf (G_STRFUNC
, "target area empty");
2047 gnm_expr_top_unref (texpr
);
2051 * xml_not_used_old_array_spec : See if the string corresponds to
2052 * a pre-0.53 style array expression.
2053 * If it is the upper left corner - assign it.
2054 * If it is a member of an array - ignore it; the corner will assign it.
2055 * If it is not a member of an array return TRUE.
2058 xml_not_used_old_array_spec (XMLSaxParseState
*state
,
2059 GnmCell
*cell
, GnmCellCopy
*cc
,
2060 char const *content
)
2062 long rows
, cols
, row
, col
;
2063 char *end
, *expr_end
, *ptr
;
2065 /* This is the syntax we are trying to parse: "{%s}(%d,%d)[%d][%d]" */
2067 if (content
[0] != '=' || content
[1] != '{')
2070 expr_end
= strrchr (content
, '}');
2071 if (expr_end
== NULL
|| expr_end
[1] != '(')
2074 rows
= strtol (ptr
= expr_end
+ 2, &end
, 10);
2075 if (end
== ptr
|| *end
!= ',')
2077 cols
= strtol (ptr
= end
+ 1, &end
, 10);
2078 if (end
== ptr
|| end
[0] != ')' || end
[1] != '[')
2080 row
= strtol (ptr
= end
+ 2, &end
, 10);
2081 if (end
== ptr
|| end
[0] != ']' || end
[1] != '[')
2083 col
= strtol (ptr
= end
+ 2, &end
, 10);
2084 if (end
== ptr
|| end
[0] != ']' || end
[1] != '\0')
2087 if (row
== 0 && col
== 0) {
2089 xml_cell_set_array_expr (state
, cell
, cc
,
2090 content
+ 2, rows
, cols
);
2097 xml_sax_cell_content (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2099 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2100 Sheet
*sheet
= state
->sheet
;
2102 gboolean is_new_cell
= FALSE
, is_post_52_array
= FALSE
;
2105 GnmCell
*cell
= NULL
; /* Regular case */
2106 GnmCellCopy
*cc
= NULL
; /* Clipboard case */
2107 GnmCellRegion
*cr
= state
->clipboard
;
2108 GnmExprTop
const *texpr
= NULL
;
2110 char const *content
= xin
->content
->str
;
2111 gboolean has_contents
= (xin
->content
->len
> 0);
2112 const char *expr_start
= gnm_expr_char_start_p (content
);
2114 int const col
= state
->cell
.col
;
2115 int const row
= state
->cell
.row
;
2116 int const array_cols
= state
->array_cols
;
2117 int const array_rows
= state
->array_rows
;
2118 int expr_id
= state
->expr_id
;
2119 int const value_type
= state
->value_type
;
2120 gboolean
const seen_contents
= state
->seen_cell_contents
;
2121 GOFormat
*value_fmt
= state
->value_fmt
;
2122 char *value_result
= state
->value_result
;
2124 /* Clean out the state before any error checking */
2125 state
->cell
.row
= state
->cell
.col
= -1;
2126 state
->array_rows
= state
->array_cols
= -1;
2127 state
->expr_id
= -1;
2128 state
->value_type
= -1;
2129 state
->value_fmt
= NULL
;
2130 state
->value_result
= NULL
;
2131 state
->seen_cell_contents
= strcmp (xin
->node
->id
, "CELL_CONTENT") == 0;
2136 XML_CHECK (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
));
2137 XML_CHECK (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
));
2139 maybe_update_progress (xin
);
2142 cc
= gnm_cell_copy_new (cr
,
2144 row
- cr
->base
.row
);
2145 parse_pos_init (&pos
, NULL
, sheet
, col
, row
);
2147 cell
= sheet_cell_get (sheet
, col
, row
);
2148 is_new_cell
= (cell
== NULL
);
2150 cell
= sheet_cell_create (sheet
, col
, row
);
2154 parse_pos_init_cell (&pos
, cell
);
2157 // ----------------------------------------
2159 is_post_52_array
= (array_cols
> 0) && (array_rows
> 0);
2160 if (is_post_52_array
&& has_contents
) {
2162 g_return_if_fail (content
[0] == '=');
2163 xml_cell_set_array_expr (state
, cell
, cc
, content
+ 1,
2164 array_cols
, array_rows
);
2165 texpr
= cell
->base
.texpr
;
2166 if (texpr
) gnm_expr_top_ref (texpr
);
2170 // ----------------------------------------
2172 if (has_contents
&& state
->version
< GNM_XML_V3
&&
2173 !xml_not_used_old_array_spec (state
, cell
, cc
, content
)) {
2174 // Very old array syntax -- irrelevant
2178 // ----------------------------------------
2180 if (!has_contents
&& expr_id
> 0) {
2181 // Re-use of expression id
2182 texpr
= g_hash_table_lookup (state
->expr_map
,
2183 GINT_TO_POINTER (expr_id
));
2185 if (texpr
&& gnm_expr_top_is_array_corner (texpr
)) {
2186 g_printerr ("Shared array formula for %s -- how did that happen?\n",
2187 cell
? cell_name (cell
) : "clipboard");
2188 texpr
= gnm_expr_top_new (gnm_expr_copy (texpr
->expr
));
2191 gnm_expr_top_ref (texpr
);
2194 char *msg
= g_strdup_printf
2195 ("Looking up shared expression id %d",
2197 char *s
= g_strdup_printf ("<shared expression %d>", expr_id
);
2198 xml_sax_barf (G_STRFUNC
, msg
);
2201 texpr
= gnm_expr_top_new_constant (value_new_string_nocopy (s
));
2203 goto assign_and_done
;
2206 // ----------------------------------------
2208 if (value_type
> 0) {
2210 gboolean from_content
= (value_result
== NULL
);
2211 const char *txt
= from_content
? content
: value_result
;
2212 v
= value_new_from_string (value_type
, txt
, value_fmt
, FALSE
);
2214 char *msg
= g_strdup_printf
2215 ("Parsing \"%s\" as type 0x%x",
2217 xml_sax_barf (G_STRFUNC
, msg
);
2219 v
= value_new_string (txt
);
2222 // If we consumed the contents as a value, then it's not
2228 value_set_fmt (v
, value_fmt
);
2232 // ----------------------------------------
2234 if (expr_start
&& *expr_start
) {
2237 parse_error_init (&perr
);
2238 texpr
= gnm_expr_parse_str (expr_start
,
2240 GNM_EXPR_PARSE_DEFAULT
,
2243 // Don't warn in the clipboard case.
2244 // It's probably an unknown sheet ref
2246 g_warning ("Unparsable expression for %s: %s (%s)\n",
2247 cell
? cell_name (cell
) : "-",
2251 texpr
= gnm_expr_top_new_constant (value_new_string (expr_start
));
2252 parse_error_free (&perr
);
2255 gpointer id
= GINT_TO_POINTER (expr_id
);
2256 GnmExprTop
const *texpr0
=
2257 g_hash_table_lookup (state
->expr_map
, id
);
2259 if (!is_post_52_array
)
2260 g_warning ("XML-IO: Duplicate shared expression");
2268 v
= value_new_empty ();
2269 // When we get here:
2270 // 1. We own a ref to texpr (or it's NULL)
2271 // 2. We own v. After this section we no longer own v.
2275 gnm_cell_set_expr_and_value (cell
, texpr
, v
, TRUE
);
2277 gnm_cell_set_value (cell
, v
);
2280 cc
->texpr
= texpr
? gnm_expr_top_ref (texpr
) : NULL
;
2286 // We own a ref to texpr at this point. Store or discard.
2288 g_hash_table_insert (state
->expr_map
,
2289 GINT_TO_POINTER (expr_id
),
2292 gnm_expr_top_unref (texpr
);
2296 go_format_unref (value_fmt
);
2297 g_free (value_result
);
2301 xml_sax_merge (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2303 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2304 GnmCellRegion
*cr
= state
->clipboard
;
2305 Sheet
*sheet
= state
->sheet
;
2308 g_return_if_fail (xin
->content
->len
> 0);
2310 if (range_parse (&r
, xin
->content
->str
, gnm_sheet_get_size (sheet
))) {
2312 cr
->merged
= g_slist_prepend (cr
->merged
,
2313 gnm_range_dup (&r
));
2315 gnm_sheet_merge_add (sheet
, &r
, FALSE
,
2316 GO_CMD_CONTEXT (state
->context
));
2322 xml_sax_filter_operator (XMLSaxParseState
*state
,
2323 GnmFilterOp
*op
, xmlChar
const *str
)
2325 static char const *filter_cond_name
[] = { "eq", "gt", "lt", "gte", "lte", "ne" };
2328 for (i
= G_N_ELEMENTS (filter_cond_name
); i
-- ; )
2329 if (0 == g_ascii_strcasecmp (CXML2C (str
), filter_cond_name
[i
])) {
2334 go_io_warning (state
->context
, _("Unknown filter operator \"%s\""), str
);
2338 xml_sax_filter_condition (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2340 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2341 char const *type
= NULL
;
2342 char const *val0
= NULL
;
2343 char const *val1
= NULL
;
2344 GnmValueType vtype0
= VALUE_EMPTY
, vtype1
= VALUE_EMPTY
;
2345 GnmFilterOp op0
= GNM_FILTER_UNUSED
, op1
= GNM_FILTER_UNUSED
;
2346 GnmFilterCondition
*cond
= NULL
;
2347 gboolean top
= TRUE
, items
= TRUE
, is_and
= FALSE
;
2348 int i
, tmp
, cond_num
= 0;
2349 double bucket_count
= 10.;
2351 if (NULL
== state
->filter
) return;
2353 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2) {
2354 if (attr_eq (attrs
[i
], "Type")) type
= CXML2C (attrs
[i
+ 1]);
2355 else if (gnm_xml_attr_int (attrs
+i
, "Index", &cond_num
)) ;
2356 else if (gnm_xml_attr_bool (attrs
, "Top", &top
)) ;
2357 else if (gnm_xml_attr_bool (attrs
, "Items", &items
)) ;
2358 else if (gnm_xml_attr_double (attrs
, "Count", &bucket_count
)) ;
2359 else if (gnm_xml_attr_bool (attrs
, "IsAnd", &is_and
)) ;
2360 else if (attr_eq (attrs
[i
], "Op0")) xml_sax_filter_operator (state
, &op0
, attrs
[i
+ 1]);
2361 else if (attr_eq (attrs
[i
], "Op1")) xml_sax_filter_operator (state
, &op1
, attrs
[i
+ 1]);
2363 * WARNING WARNING WARING
2364 * Value and ValueType are _reversed_ !!!
2365 * An error in the DOM exporter was propogated to the SAX
2366 * exporter and fixing this reversal would break all old files.
2368 else if (attr_eq (attrs
[i
], "ValueType0")) val0
= CXML2C (attrs
[i
+ 1]);
2369 else if (attr_eq (attrs
[i
], "ValueType1")) val1
= CXML2C (attrs
[i
+ 1]);
2370 else if (gnm_xml_attr_int (attrs
+i
, "Value0", &tmp
)) vtype0
= tmp
;
2371 else if (gnm_xml_attr_int (attrs
+i
, "Value1", &tmp
)) vtype1
= tmp
;
2375 go_io_warning (state
->context
, _("Missing filter type"));
2376 } else if (0 == g_ascii_strcasecmp (type
, "expr")) {
2377 GnmValue
*v0
= NULL
, *v1
= NULL
;
2378 if (val0
&& vtype0
!= VALUE_EMPTY
&& op0
!= GNM_FILTER_UNUSED
)
2379 v0
= value_new_from_string (vtype0
, val0
, NULL
, FALSE
);
2380 if (val1
&& vtype1
!= VALUE_EMPTY
&& op1
!= GNM_FILTER_UNUSED
)
2381 v1
= value_new_from_string (vtype1
, val1
, NULL
, FALSE
);
2383 cond
= gnm_filter_condition_new_double (
2384 op0
, v0
, is_and
, op1
, v1
);
2386 cond
= gnm_filter_condition_new_single (op0
, v0
);
2388 go_io_warning (state
->context
, _("Malformed sheet filter condition"));
2392 } else if (0 == g_ascii_strcasecmp (type
, "blanks")) {
2393 cond
= gnm_filter_condition_new_single (
2394 GNM_FILTER_OP_BLANKS
, NULL
);
2395 } else if (0 == g_ascii_strcasecmp (type
, "noblanks")) {
2396 cond
= gnm_filter_condition_new_single (
2397 GNM_FILTER_OP_NON_BLANKS
, NULL
);
2398 } else if (0 == g_ascii_strcasecmp (type
, "bucket")) {
2399 cond
= gnm_filter_condition_new_bucket
2400 (top
, items
, TRUE
, bucket_count
);
2402 go_io_warning (state
->context
, _("Unknown filter type \"%s\""), type
);
2405 gnm_filter_set_condition (state
->filter
, cond_num
, cond
, FALSE
);
2409 xml_sax_filter_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2411 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2415 xml_sax_must_have_sheet (state
);
2416 g_return_if_fail (state
->filter
== NULL
);
2418 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2)
2419 if (attr_eq (attrs
[i
], "Area") &&
2420 range_parse (&r
, CXML2C (attrs
[i
+ 1]), gnm_sheet_get_size (state
->sheet
)))
2421 state
->filter
= gnm_filter_new (state
->sheet
, &r
);
2422 if (NULL
== state
->filter
)
2423 go_io_warning (state
->context
, _("Invalid filter, missing Area"));
2427 xml_sax_filter_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2429 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2430 state
->filter
= NULL
;
2434 xml_sax_read_obj (GsfXMLIn
*xin
, gboolean needs_cleanup
,
2435 char const *type_name
, xmlChar
const **attrs
)
2437 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2440 SheetObjectClass
*klass
;
2442 GODrawingAnchorDir anchor_dir
;
2443 GnmSOAnchorMode anchor_mode
;
2444 SheetObjectAnchor anchor
;
2445 double f_tmp
[4], *anchor_offset
= NULL
;
2447 g_return_if_fail (state
->so
== NULL
);
2450 if (!strcmp (type_name
, "Rectangle"))
2451 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2452 else if (!strcmp (type_name
, "Ellipse"))
2453 so
= g_object_new (GNM_SO_FILLED_TYPE
, "is-oval", TRUE
, NULL
);
2454 else if (!strcmp (type_name
, "Line"))
2455 so
= g_object_new (GNM_SO_LINE_TYPE
, NULL
);
2456 else if (!strcmp (type_name
, "Arrow")) {
2458 go_arrow_init_kite (&arrow
, 8., 10., 3.);
2459 so
= g_object_new (GNM_SO_LINE_TYPE
,
2460 "end-arrow", &arrow
,
2464 /* Class renamed between 1.0.x and 1.2.x */
2465 else if (!strcmp (type_name
, "GnmGraph"))
2466 so
= sheet_object_graph_new (NULL
);
2468 /* Class renamed in 1.2.2 */
2469 else if (!strcmp (type_name
, "CellComment"))
2470 so
= g_object_new (cell_comment_get_type (), NULL
);
2472 /* Class renamed in 1.3.91 */
2473 else if (!strcmp (type_name
, "SheetObjectGraphic"))
2474 so
= g_object_new (GNM_SO_LINE_TYPE
, NULL
);
2475 else if (!strcmp (type_name
, "SheetObjectFilled"))
2476 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2477 else if (!strcmp (type_name
, "SheetObjectText"))
2478 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2479 else if (!strcmp (type_name
, "SheetObjectComponent"))
2480 so
= sheet_object_component_new (NULL
);
2481 else if (!strcmp (type_name
, "SheetObjectPath"))
2482 so
= g_object_new (GNM_SO_PATH_TYPE
, NULL
);
2485 GType type
= g_type_from_name (type_name
);
2487 if (type
== 0 || !g_type_is_a (type
, GNM_SO_TYPE
)) {
2488 char *str
= g_strdup_printf (_("Unsupported object type '%s'"),
2490 go_io_warning_unsupported_feature (state
->context
, str
);
2495 so
= g_object_new (type
, NULL
);
2500 g_return_if_fail (so
!= NULL
);
2501 klass
= GNM_SO_CLASS (G_OBJECT_GET_CLASS (so
));
2502 g_return_if_fail (klass
!= NULL
);
2506 anchor_dir
= GOD_ANCHOR_DIR_UNKNOWN
;
2507 anchor_mode
= GNM_SO_ANCHOR_TWO_CELLS
;
2508 /* Provide a default. */
2509 anchor_r
= sheet_object_get_anchor (so
)->cell_bound
;
2511 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2) {
2512 if (attr_eq (attrs
[i
], "Name"))
2513 sheet_object_set_name (so
, CXML2C (attrs
[i
+ 1]));
2514 else if (xml_sax_attr_enum (attrs
+ i
, "AnchorMode", GNM_SHEET_OBJECT_ANCHOR_MODE_TYPE
, &tmp_int
))
2515 anchor_mode
= tmp_int
;
2516 else if (attr_eq (attrs
[i
], "ObjectBound"))
2517 range_parse (&anchor_r
, CXML2C (attrs
[i
+ 1]), gnm_sheet_get_size (state
->sheet
));
2518 else if (attr_eq (attrs
[i
], "ObjectOffset") &&
2519 4 == sscanf (CXML2C (attrs
[i
+ 1]), "%lg %lg %lg %lg",
2520 f_tmp
+ 0, f_tmp
+ 1, f_tmp
+ 2, f_tmp
+ 3))
2521 anchor_offset
= f_tmp
;
2522 else if (gnm_xml_attr_int (attrs
+i
, "Direction", &tmp_int
))
2523 anchor_dir
= tmp_int
;
2524 else if (gnm_xml_attr_int (attrs
+i
, "Print", &tmp_int
)) {
2525 gboolean b
= (tmp_int
!= 0);
2526 sheet_object_set_print_flag (so
, &b
);
2530 /* Patch problems introduced in some 1.7.x versions that stored
2531 * comments in merged cells with the full rectangle of the merged cell
2532 * rather than just the top left corner */
2533 if (G_OBJECT_TYPE (so
) == GNM_CELL_COMMENT_TYPE
)
2534 anchor_r
.end
= anchor_r
.start
;
2536 sheet_object_anchor_init (&anchor
, &anchor_r
, anchor_offset
, anchor_dir
, anchor_mode
);
2537 sheet_object_set_anchor (so
, &anchor
);
2539 if (NULL
!= klass
->prep_sax_parser
)
2540 (klass
->prep_sax_parser
) (so
, xin
, attrs
, state
->convs
);
2541 if (needs_cleanup
) {
2542 /* Put in something to get gnm_xml_finish_obj called */
2543 static GsfXMLInNode
const dtd
[] = {
2544 GSF_XML_IN_NODE (STYLE
, STYLE
, -1, "", GSF_XML_NO_CONTENT
, NULL
, NULL
),
2547 static GsfXMLInDoc
*doc
= NULL
;
2549 doc
= gsf_xml_in_doc_new (dtd
, NULL
);
2550 gnm_xml_in_doc_dispose_on_exit (&doc
);
2552 /* we need to pas state there because xin->user_state might have
2553 changed, see #751217 */
2554 gsf_xml_in_push_state (xin
, doc
, state
,
2555 (GsfXMLInExtDtor
) gnm_xml_finish_obj
, attrs
);
2560 xml_sax_object_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2562 char const *type_name
= xin
->node
->name
;
2563 maybe_update_progress (xin
);
2564 xml_sax_read_obj (xin
, FALSE
, type_name
, attrs
);
2568 xml_sax_object_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2570 gnm_xml_finish_obj (xin
, xin
->user_state
);
2572 * WARNING: the object is not completely finished at this
2573 * time. Any handler installed by gog_object_sax_push_parser
2574 * has not yet been called. As a consequence, we cannot
2575 * update the GUI here.
2580 parse_constraint_side (const char *s
, const GnmParsePos
*pp
)
2582 GODateConventions
const *date_conv
= sheet_date_conv (pp
->sheet
);
2583 GnmValue
*v
= format_match_number (s
, NULL
, date_conv
);
2586 GnmExprParseFlags flags
= GNM_EXPR_PARSE_DEFAULT
;
2587 v
= value_new_cellrange_parsepos_str (pp
, s
, flags
);
2594 xml_sax_solver_constr_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2597 GnmSolverConstraint
*c
;
2598 Sheet
*sheet
= gnm_xml_in_cur_sheet (xin
);
2599 GnmSolverParameters
*sp
= sheet
->solver_parameters
;
2600 int lhs_col
= 0, lhs_row
= 0, rhs_col
= 0, rhs_row
= 0;
2601 int cols
= 1, rows
= 1;
2602 gboolean old
= FALSE
;
2605 c
= gnm_solver_constraint_new (sheet
);
2607 parse_pos_init_sheet (&pp
, sheet
);
2609 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2610 if (gnm_xml_attr_int (attrs
, "Lcol", &lhs_col
) ||
2611 gnm_xml_attr_int (attrs
, "Lrow", &lhs_row
) ||
2612 gnm_xml_attr_int (attrs
, "Rcol", &rhs_col
) ||
2613 gnm_xml_attr_int (attrs
, "Rrow", &rhs_row
) ||
2614 gnm_xml_attr_int (attrs
, "Cols", &cols
) ||
2615 gnm_xml_attr_int (attrs
, "Rows", &rows
))
2617 else if (gnm_xml_attr_int (attrs
, "Type", &type
))
2619 else if (attr_eq (attrs
[0], "lhs")) {
2620 GnmValue
*v
= parse_constraint_side (CXML2C (attrs
[1]),
2622 gnm_solver_constraint_set_lhs (c
, v
);
2623 } else if (attr_eq (attrs
[0], "rhs")) {
2624 GnmValue
*v
= parse_constraint_side (CXML2C (attrs
[1]),
2626 gnm_solver_constraint_set_rhs (c
, v
);
2632 case 1: c
->type
= GNM_SOLVER_LE
; break;
2633 case 2: c
->type
= GNM_SOLVER_GE
; break;
2634 case 4: c
->type
= GNM_SOLVER_EQ
; break;
2635 case 8: c
->type
= GNM_SOLVER_INTEGER
; break;
2636 case 16: c
->type
= GNM_SOLVER_BOOLEAN
; break;
2640 gnm_solver_constraint_set_old (c
, c
->type
,
2645 sp
->constraints
= g_slist_append (sp
->constraints
, c
);
2649 xml_sax_solver_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2651 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2653 GnmSolverParameters
*sp
;
2654 int col
= -1, row
= -1;
2657 gboolean old
= FALSE
;
2659 xml_sax_must_have_sheet (state
);
2660 sheet
= gnm_xml_in_cur_sheet (xin
);
2661 sp
= sheet
->solver_parameters
;
2663 parse_pos_init_sheet (&pp
, sheet
);
2665 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2666 if (gnm_xml_attr_int (attrs
, "ModelType", &mtype
)) {
2667 sp
->options
.model_type
= (GnmSolverModelType
)mtype
;
2668 } else if (gnm_xml_attr_int (attrs
, "ProblemType", &ptype
)) {
2669 sp
->problem_type
= (GnmSolverProblemType
)ptype
;
2670 } else if (attr_eq (attrs
[0], "Inputs")) {
2671 GnmValue
*v
= value_new_cellrange_parsepos_str
2674 GNM_EXPR_PARSE_DEFAULT
);
2675 gnm_solver_param_set_input (sp
, v
);
2676 } else if (gnm_xml_attr_int (attrs
, "TargetCol", &col
) ||
2677 gnm_xml_attr_int (attrs
, "TargetRow", &row
)) {
2679 } else if (attr_eq (attrs
[0], "Target")) {
2680 GnmValue
*v
= value_new_cellrange_parsepos_str
2683 GNM_EXPR_PARSE_DEFAULT
);
2689 (gnm_sheet_range_from_value (&sr
, v
), !range_is_singleton (&sr
.range
)));
2695 gnm_cellref_init (&cr
, sr
.sheet
,
2699 gnm_solver_param_set_target (sp
, &cr
);
2700 } else if (gnm_xml_attr_int (attrs
, "MaxTime", &(sp
->options
.max_time_sec
)) ||
2701 gnm_xml_attr_int (attrs
, "MaxIter", &(sp
->options
.max_iter
)) ||
2702 gnm_xml_attr_bool (attrs
, "NonNeg", &(sp
->options
.assume_non_negative
)) ||
2703 gnm_xml_attr_bool (attrs
, "Discr", &(sp
->options
.assume_discrete
)) ||
2704 gnm_xml_attr_bool (attrs
, "AutoScale", &(sp
->options
.automatic_scaling
)) ||
2705 gnm_xml_attr_bool (attrs
, "ProgramR", &(sp
->options
.program_report
)) ||
2706 gnm_xml_attr_bool (attrs
, "SensitivityR", &(sp
->options
.sensitivity_report
)))
2711 col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
) &&
2712 row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
)) {
2714 gnm_cellref_init (&cr
, NULL
, col
, row
, TRUE
);
2715 gnm_solver_param_set_target (sp
, &cr
);
2720 xml_sax_scenario_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2722 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2723 const char *name
= "scenario";
2724 const char *comment
= NULL
;
2726 xml_sax_must_have_sheet (state
);
2728 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2729 if (attr_eq (attrs
[0], "Name")) {
2730 name
= CXML2C (attrs
[1]);
2731 } else if (attr_eq (attrs
[0], "Comment")) {
2732 comment
= CXML2C (attrs
[1]);
2736 state
->scenario
= gnm_sheet_scenario_new (state
->sheet
, name
);
2738 gnm_scenario_set_comment (state
->scenario
, comment
);
2742 xml_sax_scenario_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2744 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2745 GnmScenario
*sc
= state
->scenario
;
2746 sc
->items
= g_slist_reverse (sc
->items
);
2747 gnm_sheet_scenario_add (state
->sheet
, sc
);
2748 state
->scenario
= NULL
;
2752 xml_sax_scenario_item_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2754 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2755 const char *rtxt
= NULL
;
2758 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2759 if (attr_eq (attrs
[0], "Range")) {
2760 rtxt
= CXML2C (attrs
[1]);
2761 } else if (gnm_xml_attr_int (attrs
, "ValueType",
2762 &state
->value_type
))
2764 else if (attr_eq (attrs
[0], "ValueFormat"))
2765 state
->value_fmt
= make_format (CXML2C (attrs
[1]));
2768 parse_pos_init_sheet (&pp
, state
->sheet
);
2769 state
->scenario_range
= rtxt
2770 ? value_new_cellrange_parsepos_str (&pp
, rtxt
, GNM_EXPR_PARSE_DEFAULT
)
2775 xml_sax_scenario_item_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2777 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2778 char const * content
= xin
->content
->str
;
2779 int const len
= xin
->content
->len
;
2780 GnmScenarioItem
*sci
= NULL
;
2781 GnmScenario
*sc
= state
->scenario
;
2784 if (!state
->scenario_range
)
2787 gnm_sheet_range_from_value (&sr
, state
->scenario_range
);
2788 sci
= gnm_scenario_item_new (sc
->sheet
);
2789 gnm_scenario_item_set_range (sci
, &sr
);
2792 GnmValue
*v
= value_new_from_string (state
->value_type
,
2798 gnm_scenario_item_set_value (sci
, v
);
2802 sc
->items
= g_slist_prepend (sc
->items
, sci
);
2806 g_warning ("Ignoring invalid scenario item");
2808 gnm_scenario_item_free (sci
);
2811 state
->value_type
= -1;
2812 go_format_unref (state
->value_fmt
);
2813 state
->value_fmt
= NULL
;
2814 value_release (state
->scenario_range
);
2815 state
->scenario_range
= NULL
;
2819 xml_sax_named_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2821 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2823 GnmNamedExpr
*nexpr
;
2825 g_return_if_fail (state
->name
.name
!= NULL
);
2826 g_return_if_fail (state
->name
.value
!= NULL
);
2828 /*For the next while we have to ignore Print_areas that look like a whole sheet */
2829 if (0 == strcmp (state
->name
.name
, "Print_Area")
2830 && g_str_has_suffix (state
->name
.value
, "$A$1:$IV$65536")) {
2831 g_free (state
->name
.value
);
2832 state
->name
.value
= NULL
;
2833 g_free (state
->name
.position
);
2834 state
->name
.position
= NULL
;
2836 parse_pos_init (&pp
, state
->wb
, state
->sheet
, 0, 0);
2837 nexpr
= expr_name_add (&pp
, state
->name
.name
,
2838 gnm_expr_top_new_constant (value_new_empty ()),
2843 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->sheet
);
2844 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->name
.value
);
2845 state
->name
.value
= NULL
;
2846 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->name
.position
);
2847 state
->name
.position
= NULL
;
2848 state
->delayed_names
= g_list_prepend (state
->delayed_names
, nexpr
);
2850 g_warning ("Strangeness with defined name: %s",
2852 g_free (state
->name
.value
);
2853 state
->name
.value
= NULL
;
2854 g_free (state
->name
.position
);
2855 state
->name
.position
= NULL
;
2859 g_free (state
->name
.name
);
2860 state
->name
.name
= NULL
;
2864 xml_sax_named_expr_prop (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2866 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2868 char const * content
= xin
->content
->str
;
2869 int const len
= xin
->content
->len
;
2871 switch (xin
->node
->user_data
.v_int
) {
2873 g_return_if_fail (state
->name
.name
== NULL
);
2874 state
->name
.name
= g_strndup (content
, len
);
2877 g_return_if_fail (state
->name
.value
== NULL
);
2878 state
->name
.value
= g_strndup (content
, len
);
2881 g_return_if_fail (state
->name
.position
== NULL
);
2882 state
->name
.position
= g_strndup (content
, len
);
2890 xml_sax_print_order (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2892 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2894 xml_sax_must_have_sheet (state
);
2896 state
->sheet
->print_info
->print_across_then_down
=
2897 (strcmp (xin
->content
->str
, "r_then_d") == 0);
2901 xml_sax_print_comments_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2903 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2906 xml_sax_must_have_sheet (state
);
2908 /* In 1.11.x and later this is saved as an enum value */
2909 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
2910 if (xml_sax_attr_enum (attrs
, "placement", GNM_PRINT_COMMENT_PLACEMENT_TYPE
, &tmpi
))
2911 state
->sheet
->print_info
->comment_placement
= tmpi
;
2915 xml_sax_print_comments_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2917 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2919 if (xin
->content
->str
== NULL
|| *xin
->content
->str
== 0)
2920 /* 1.11.x or later file */
2923 xml_sax_must_have_sheet (state
);
2925 if (strcmp (xin
->content
->str
, "in_place") == 0)
2926 state
->sheet
->print_info
->comment_placement
=
2927 GNM_PRINT_COMMENTS_IN_PLACE
;
2928 else if (strcmp (xin
->content
->str
, "at_end") == 0)
2929 state
->sheet
->print_info
->comment_placement
=
2930 GNM_PRINT_COMMENTS_AT_END
;
2932 state
->sheet
->print_info
->comment_placement
=
2933 GNM_PRINT_COMMENTS_NONE
;
2937 xml_sax_print_errors_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2939 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2942 xml_sax_must_have_sheet (state
);
2944 /* In 1.11.x and later this is saved as an enum value */
2945 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
2946 if (xml_sax_attr_enum (attrs
, "PrintErrorsAs", GNM_PRINT_ERRORS_TYPE
, &tmpi
))
2947 state
->sheet
->print_info
->error_display
= tmpi
;
2952 xml_sax_print_errors_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2954 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2956 if (xin
->content
->str
== NULL
|| *xin
->content
->str
== 0)
2957 /* 1.11.x or later file */
2960 xml_sax_must_have_sheet (state
);
2962 if (strcmp (xin
->content
->str
, "as_blank") == 0)
2963 state
->sheet
->print_info
->error_display
=
2964 GNM_PRINT_ERRORS_AS_BLANK
;
2965 else if (strcmp (xin
->content
->str
, "as_dashes") == 0)
2966 state
->sheet
->print_info
->error_display
=
2967 GNM_PRINT_ERRORS_AS_DASHES
;
2968 else if (strcmp (xin
->content
->str
, "as_na") == 0)
2969 state
->sheet
->print_info
->error_display
=
2970 GNM_PRINT_ERRORS_AS_NA
;
2972 state
->sheet
->print_info
->error_display
=
2973 GNM_PRINT_ERRORS_AS_DISPLAYED
;
2978 xml_sax_orientation (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2980 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2981 GnmPrintInformation
*pi
;
2982 GtkPageOrientation orient
= GTK_PAGE_ORIENTATION_PORTRAIT
;
2984 xml_sax_must_have_sheet (state
);
2986 pi
= state
->sheet
->print_info
;
2988 #warning TODO: we should also handle inversion
2989 if (strcmp (xin
->content
->str
, "portrait") == 0)
2990 orient
= GTK_PAGE_ORIENTATION_PORTRAIT
;
2991 else if (strcmp (xin
->content
->str
, "landscape") == 0)
2992 orient
= GTK_PAGE_ORIENTATION_LANDSCAPE
;
2994 print_info_set_paper_orientation (pi
, orient
);
2998 xml_sax_paper (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
3000 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3002 xml_sax_must_have_sheet (state
);
3004 print_info_set_paper (state
->sheet
->print_info
, xin
->content
->str
);
3008 xml_sax_print_to_uri (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
3010 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3012 xml_sax_must_have_sheet (state
);
3014 print_info_set_printtofile_uri (state
->sheet
->print_info
,
3019 handle_delayed_names (XMLSaxParseState
*state
)
3023 for (l
= state
->delayed_names
; l
; l
= l
->next
->next
->next
->next
) {
3024 GnmNamedExpr
*nexpr
= l
->data
;
3025 char *pos_str
= l
->next
->data
;
3026 char *expr_str
= l
->next
->next
->data
;
3027 Sheet
*sheet
= l
->next
->next
->next
->data
;
3029 GnmExprTop
const *texpr
;
3032 parse_pos_init (&pp
, state
->wb
, sheet
, 0, 0);
3036 GnmSheetSize
const *ss
=
3037 gnm_sheet_get_size2 (sheet
, state
->wb
);
3038 rest
= cellref_parse (&tmp
, ss
, pos_str
, &pp
.eval
);
3039 if (rest
!= NULL
&& *rest
== '\0') {
3040 pp
.eval
.col
= tmp
.col
;
3041 pp
.eval
.row
= tmp
.row
;
3045 parse_error_init (&perr
);
3046 texpr
= gnm_expr_parse_str (expr_str
, &pp
,
3047 GNM_EXPR_PARSE_DEFAULT
,
3051 go_io_warning (state
->context
, "%s", perr
.err
->message
);
3052 } else if (expr_name_check_for_loop (expr_name_name (nexpr
), texpr
)) {
3053 g_printerr ("Ignoring would-be circular definition of %s\n",
3054 expr_name_name (nexpr
));
3055 gnm_expr_top_unref (texpr
);
3057 nexpr
->pos
.eval
= pp
.eval
;
3058 expr_name_set_expr (nexpr
, texpr
);
3061 parse_error_free (&perr
);
3066 g_list_free (state
->delayed_names
);
3067 state
->delayed_names
= NULL
;
3071 xml_sax_go_doc (GsfXMLIn
*xin
, xmlChar
const **attrs
)
3073 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3074 go_doc_read (GO_DOC (state
->wb
), xin
, attrs
);
3077 /****************************************************************************/
3079 static GsfXMLInNS
const content_ns
[] = {
3080 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v14.dtd"), /* future */
3081 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v13.dtd"),
3082 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v12.dtd"),
3083 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v11.dtd"),
3084 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v10.dtd"),
3085 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v9.dtd"),
3086 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v8.dtd"),
3087 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v7"),
3088 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v6"),
3089 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v5"),
3090 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v4"),
3091 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v3"),
3092 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v2"),
3093 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/"),
3094 /* The next items are from libgsf, there is no obvious way of adding them automatically */
3095 GSF_XML_IN_NS (OO_NS_XSI
, "http://www.w3.org/2001/XMLSchema-instance"),
3096 GSF_XML_IN_NS (OO_NS_OFFICE
, "urn:oasis:names:tc:opendocument:xmlns:office:1.0"),
3097 GSF_XML_IN_NS (OO_NS_OOO
, "http://openoffice.org/2004/office"),
3098 GSF_XML_IN_NS (OO_NS_DC
, "http://purl.org/dc/elements/1.1/"),
3099 GSF_XML_IN_NS (OO_NS_XLINK
, "http://www.w3.org/1999/xlink"),
3100 GSF_XML_IN_NS (OO_NS_META
, "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"),
3104 static GsfXMLInNode gnumeric_1_0_dtd
[] = {
3105 GSF_XML_IN_NODE_FULL (START
, START
, -1, NULL
, GSF_XML_NO_CONTENT
, FALSE
, TRUE
, NULL
, NULL
, 0),
3106 GSF_XML_IN_NODE_FULL (START
, WB
, GNM
, "Workbook", GSF_XML_NO_CONTENT
, TRUE
, TRUE
, &xml_sax_wb
, NULL
, 0),
3107 GSF_XML_IN_NODE (WB
, WB_VERSION
, GNM
, "Version", GSF_XML_NO_CONTENT
, &xml_sax_version
, NULL
),
3108 GSF_XML_IN_NODE (WB
, WB_ATTRIBUTES
, GNM
, "Attributes", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3109 GSF_XML_IN_NODE (WB_ATTRIBUTES
, WB_ATTRIBUTE
, GNM
, "Attribute", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_finish_parse_wb_attr
),
3110 GSF_XML_IN_NODE_FULL (WB_ATTRIBUTE
, WB_ATTRIBUTE_NAME
, GNM
, "name", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_attr_elem
, 0),
3111 GSF_XML_IN_NODE_FULL (WB_ATTRIBUTE
, WB_ATTRIBUTE_VALUE
, GNM
, "value", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_attr_elem
, 1),
3112 GSF_XML_IN_NODE (WB_ATTRIBUTE
, WB_ATTRIBUTE_TYPE
, GNM
, "type", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3114 /* The old 'SummaryItem' Metadata. Removed in 1.7.x */
3115 GSF_XML_IN_NODE (WB
, WB_SUMMARY
, GNM
, "Summary", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3116 GSF_XML_IN_NODE (WB_SUMMARY
, WB_SUMMARY_ITEM
, GNM
, "Item", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3117 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_NAME
, GNM
, "name", GSF_XML_CONTENT
, NULL
, NULL
),
3118 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_VALUE_STR
, GNM
, "val-string", GSF_XML_CONTENT
, NULL
, NULL
),
3119 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_VALUE_INT
, GNM
, "val-int", GSF_XML_CONTENT
, NULL
, NULL
),
3121 GSF_XML_IN_NODE (WB
, WB_SHEETNAME_INDEX
, GNM
, "SheetNameIndex", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3122 GSF_XML_IN_NODE (WB_SHEETNAME_INDEX
, WB_SHEETNAME
, GNM
, "SheetName", GSF_XML_CONTENT
, &xml_sax_wb_sheetsize
, &xml_sax_wb_sheetname
),
3124 GSF_XML_IN_NODE (WB
, WB_NAMED_EXPRS
, GNM
, "Names", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3125 GSF_XML_IN_NODE (WB_NAMED_EXPRS
, WB_NAMED_EXPR
, GNM
, "Name", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_named_expr_end
),
3126 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),
3127 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),
3128 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),
3129 /* sometimes not namespaced */
3130 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),
3131 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),
3132 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),
3134 GSF_XML_IN_NODE (WB
, WB_SHEETS
, GNM
, "Sheets", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3135 GSF_XML_IN_NODE (WB_SHEETS
, SHEET
, GNM
, "Sheet", GSF_XML_NO_CONTENT
, &xml_sax_sheet_start
, &xml_sax_sheet_end
),
3136 GSF_XML_IN_NODE (SHEET
, SHEET_NAME
, GNM
, "Name", GSF_XML_CONTENT
, NULL
, &xml_sax_sheet_name
),
3137 GSF_XML_IN_NODE (SHEET
, SHEET_MAXCOL
, GNM
, "MaxCol", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3138 GSF_XML_IN_NODE (SHEET
, SHEET_MAXROW
, GNM
, "MaxRow", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3139 GSF_XML_IN_NODE (SHEET
, SHEET_ZOOM
, GNM
, "Zoom", GSF_XML_CONTENT
, NULL
, &xml_sax_sheet_zoom
),
3140 GSF_XML_IN_NODE (SHEET
, SHEET_NAMED_EXPRS
, GNM
, "Names", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3141 GSF_XML_IN_NODE (SHEET_NAMED_EXPRS
, SHEET_NAMED_EXPR
, GNM
, "Name", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_named_expr_end
),
3142 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),
3143 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),
3144 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),
3146 GSF_XML_IN_NODE (SHEET
, SHEET_PRINTINFO
, GNM
, "PrintInformation", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3147 GSF_XML_IN_NODE (SHEET_PRINTINFO
, SHEET_PRINTUNIT
, GNM
, "PrintUnit", GSF_XML_NO_CONTENT
, NULL
, NULL
), /* ignore ancient field */
3148 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_MARGINS
, GNM
, "Margins", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3149 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_TOP
, GNM
, "top", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 0),
3150 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_BOTTOM
, GNM
, "bottom",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 1),
3151 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_LEFT
, GNM
, "left", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 2),
3152 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_RIGHT
, GNM
, "right", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 3),
3153 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_HEADER
, GNM
, "header",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 4),
3154 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_FOOTER
, GNM
, "footer",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 5),
3155 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, V_PAGE_BREAKS
, GNM
, "vPageBreaks", GSF_XML_NO_CONTENT
,
3156 FALSE
, FALSE
, &xml_sax_page_breaks_begin
, &xml_sax_page_breaks_end
, 1),
3157 GSF_XML_IN_NODE (V_PAGE_BREAKS
, PAGE_BREAK
, GNM
, "break", GSF_XML_NO_CONTENT
, &xml_sax_page_break
, NULL
),
3158 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, H_PAGE_BREAKS
, GNM
, "hPageBreaks", GSF_XML_NO_CONTENT
,
3159 FALSE
, FALSE
, &xml_sax_page_breaks_begin
, &xml_sax_page_breaks_end
, 0),
3160 GSF_XML_IN_NODE (H_PAGE_BREAKS
, PAGE_BREAK
, GNM
, "break", GSF_XML_2ND
, NULL
, NULL
),
3162 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_SCALE
, GNM
, "Scale", GSF_XML_CONTENT
, &xml_sax_print_scale
, NULL
),
3163 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_VCENTER
, GNM
, "vcenter", GSF_XML_CONTENT
, &xml_sax_print_vcenter
, NULL
),
3164 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_HCENTER
, GNM
, "hcenter", GSF_XML_CONTENT
, &xml_sax_print_hcenter
, NULL
),
3165 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_GRID
, GNM
, "grid", GSF_XML_NO_CONTENT
, &xml_sax_print_grid
, NULL
),
3166 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
),
3167 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_PRINT_RANGE
, GNM
, "print_range",GSF_XML_NO_CONTENT
, &xml_sax_print_print_range
, NULL
),
3168 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_MONO
, GNM
, "monochrome", GSF_XML_NO_CONTENT
, &xml_sax_monochrome
, NULL
),
3169 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_AS_DRAFT
, GNM
, "draft", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3170 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_COMMENTS
, GNM
, "comments", GSF_XML_CONTENT
, &xml_sax_print_comments_start
, &xml_sax_print_comments_end
),
3171 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ERRORS
, GNM
, "errors", GSF_XML_CONTENT
, &xml_sax_print_errors_start
, &xml_sax_print_errors_end
),
3172 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_TITLES
, GNM
, "titles", GSF_XML_NO_CONTENT
, &xml_sax_print_titles
, NULL
),
3173 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_REPEAT_TOP
, GNM
, "repeat_top", GSF_XML_NO_CONTENT
, &xml_sax_repeat_top
, NULL
),
3174 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_REPEAT_LEFT
,GNM
, "repeat_left", GSF_XML_NO_CONTENT
, &xml_sax_repeat_left
, NULL
),
3175 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, PRINT_FOOTER
, GNM
, "Footer", GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_print_hf
, NULL
, 0),
3176 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, PRINT_HEADER
, GNM
, "Header", GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_print_hf
, NULL
, 1),
3177 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ORDER
, GNM
, "order", GSF_XML_CONTENT
, NULL
, &xml_sax_print_order
),
3178 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_PAPER
, GNM
, "paper", GSF_XML_CONTENT
, NULL
, &xml_sax_paper
),
3179 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_TO_URI
, GNM
, "print-to-uri",GSF_XML_CONTENT
, NULL
, &xml_sax_print_to_uri
),
3180 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ORIENT
, GNM
, "orientation", GSF_XML_CONTENT
, NULL
, &xml_sax_orientation
),
3181 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ONLY_STYLE
, GNM
, "even_if_only_styles", GSF_XML_CONTENT
, &xml_sax_even_if_only_styles
, NULL
),
3183 GSF_XML_IN_NODE (SHEET
, SHEET_STYLES
, GNM
, "Styles", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3184 GSF_XML_IN_NODE (SHEET_STYLES
, STYLE_REGION
, GNM
, "StyleRegion", GSF_XML_NO_CONTENT
, &xml_sax_style_region_start
, &xml_sax_style_region_end
),
3185 GSF_XML_IN_NODE (STYLE_REGION
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, &xml_sax_style_start
, NULL
),
3186 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_FONT
, GNM
, "Font", GSF_XML_CONTENT
, &xml_sax_style_font
, &xml_sax_style_font_end
),
3187 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_BORDER
, GNM
, "StyleBorder", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3188 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_TOP
, GNM
, "Top",
3189 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_TOP
),
3190 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_BOTTOM
, GNM
, "Bottom",
3191 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_BOTTOM
),
3192 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_LEFT
, GNM
, "Left",
3193 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_LEFT
),
3194 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_RIGHT
, GNM
, "Right",
3195 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_RIGHT
),
3196 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_DIAG
, GNM
, "Diagonal",
3197 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_DIAGONAL
),
3198 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_REV_DIAG
,GNM
, "Rev-Diagonal",
3199 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_REV_DIAGONAL
),
3201 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_VALIDATION
, GNM
, "Validation", GSF_XML_NO_CONTENT
, &xml_sax_validation
, &xml_sax_validation_end
),
3202 GSF_XML_IN_NODE_FULL (STYLE_VALIDATION
, STYLE_VALIDATION_EXPR0
, GNM
, "Expression0",
3203 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_validation_expr_end
, 0),
3204 GSF_XML_IN_NODE_FULL (STYLE_VALIDATION
, STYLE_VALIDATION_EXPR1
, GNM
, "Expression1",
3205 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_validation_expr_end
, 1),
3206 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_HYPERLINK
, GNM
, "HyperLink", GSF_XML_NO_CONTENT
, &xml_sax_hlink
, NULL
),
3207 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_INPUT_MSG
, GNM
, "InputMessage", GSF_XML_NO_CONTENT
, &xml_sax_input_msg
, NULL
),
3208 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_CONDITION
, GNM
, "Condition", GSF_XML_NO_CONTENT
, &xml_sax_condition
, &xml_sax_condition_end
),
3209 GSF_XML_IN_NODE_FULL (STYLE_CONDITION
, STYLE_CONDITION_EXPR0
, GNM
, "Expression0",
3210 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_condition_expr_end
, 0),
3211 GSF_XML_IN_NODE_FULL (STYLE_CONDITION
, STYLE_CONDITION_EXPR1
, GNM
, "Expression1",
3212 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_condition_expr_end
, 1),
3213 GSF_XML_IN_NODE (STYLE_CONDITION
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3215 GSF_XML_IN_NODE_FULL (SHEET
, SHEET_COLS
, GNM
, "Cols",
3216 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_cols_rows
, NULL
, TRUE
),
3217 GSF_XML_IN_NODE_FULL (SHEET_COLS
, COL
, GNM
, "ColInfo",
3218 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_colrow
, NULL
, TRUE
),
3220 GSF_XML_IN_NODE_FULL (SHEET
, SHEET_ROWS
, GNM
, "Rows",
3221 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_cols_rows
, NULL
, FALSE
),
3222 GSF_XML_IN_NODE_FULL (SHEET_ROWS
, ROW
, GNM
, "RowInfo",
3223 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_colrow
, NULL
, FALSE
),
3225 GSF_XML_IN_NODE (SHEET
, SHEET_SELECTIONS
, GNM
, "Selections", GSF_XML_NO_CONTENT
, &xml_sax_selection
, &xml_sax_selection_end
),
3226 GSF_XML_IN_NODE (SHEET_SELECTIONS
, SELECTION
, GNM
, "Selection", GSF_XML_NO_CONTENT
, &xml_sax_selection_range
, NULL
),
3228 GSF_XML_IN_NODE (SHEET
, SHEET_CELLS
, GNM
, "Cells", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3229 GSF_XML_IN_NODE (SHEET_CELLS
, CELL
, GNM
, "Cell", GSF_XML_CONTENT
, &xml_sax_cell
, &xml_sax_cell_content
),
3230 GSF_XML_IN_NODE (CELL
, CELL_CONTENT
, GNM
, "Content", GSF_XML_CONTENT
, NULL
, &xml_sax_cell_content
),
3232 GSF_XML_IN_NODE (SHEET
, SHEET_MERGED_REGIONS
, GNM
, "MergedRegions", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3233 GSF_XML_IN_NODE (SHEET_MERGED_REGIONS
, MERGED_REGION
, GNM
, "Merge", GSF_XML_CONTENT
, NULL
, &xml_sax_merge
),
3235 GSF_XML_IN_NODE (SHEET
, SHEET_FILTERS
, GNM
, "Filters", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3236 GSF_XML_IN_NODE (SHEET_FILTERS
, FILTER
, GNM
, "Filter", GSF_XML_NO_CONTENT
, &xml_sax_filter_start
, &xml_sax_filter_end
),
3237 GSF_XML_IN_NODE (FILTER
, FILTER_FIELD
, GNM
, "Field", GSF_XML_NO_CONTENT
, &xml_sax_filter_condition
, NULL
),
3239 GSF_XML_IN_NODE (SHEET
, SHEET_LAYOUT
, GNM
, "SheetLayout", GSF_XML_NO_CONTENT
, &xml_sax_sheet_layout
, NULL
),
3240 GSF_XML_IN_NODE (SHEET_LAYOUT
, SHEET_FREEZEPANES
, GNM
, "FreezePanes", GSF_XML_NO_CONTENT
, &xml_sax_sheet_freezepanes
, NULL
),
3242 GSF_XML_IN_NODE (SHEET
, SHEET_SOLVER
, GNM
, "Solver", GSF_XML_NO_CONTENT
, xml_sax_solver_start
, NULL
),
3243 GSF_XML_IN_NODE (SHEET_SOLVER
, SOLVER_CONSTR
, GNM
, "Constr", GSF_XML_NO_CONTENT
, xml_sax_solver_constr_start
, NULL
),
3244 GSF_XML_IN_NODE (SHEET
, SHEET_SCENARIOS
, GNM
, "Scenarios", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3245 GSF_XML_IN_NODE (SHEET_SCENARIOS
, SHEET_SCENARIO
, GNM
, "Scenario", GSF_XML_NO_CONTENT
, xml_sax_scenario_start
, xml_sax_scenario_end
),
3246 GSF_XML_IN_NODE (SHEET_SCENARIO
, SCENARIO_ITEM
, GNM
, "Item", GSF_XML_CONTENT
, xml_sax_scenario_item_start
, xml_sax_scenario_item_end
),
3248 GSF_XML_IN_NODE (SHEET
, SHEET_OBJECTS
, GNM
, "Objects", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3250 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_RECT
, GNM
, "Rectangle", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3251 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_ELLIPSE
, GNM
, "Ellipse", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3252 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_ARROW
, GNM
, "Arrow", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3253 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_LINE
, GNM
, "Line", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3254 /* Class renamed between 1.0.x and 1.2.x */
3255 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_GRAPH
, GNM
, "GnmGraph", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3256 /* Class renamed in 1.2.2 */
3257 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_COMMENT
, GNM
, "CellComment", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3258 /* Class renamed in 1.3.91 */
3259 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_LINE
, GNM
, "SheetObjectGraphic", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3260 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_FILLED
, GNM
, "SheetObjectFilled", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3261 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_TEXT
, GNM
, "SheetObjectText", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3262 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_GRAPH
, GNM
, "SheetObjectGraph", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3263 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_IMAGE
, GNM
, "SheetObjectImage", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3264 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_COMPONENT
, GNM
, "SheetObjectComponent", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3265 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_PATH
, GNM
, "SheetObjectPath", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3267 GSF_XML_IN_NODE (WB
, WB_GEOMETRY
, GNM
, "Geometry", GSF_XML_NO_CONTENT
, &xml_sax_wb_view
, NULL
),
3268 GSF_XML_IN_NODE (WB
, WB_VIEW
, GNM
, "UIData", GSF_XML_NO_CONTENT
, &xml_sax_wb_view
, NULL
),
3269 GSF_XML_IN_NODE (WB
, WB_CALC
, GNM
, "Calculation", GSF_XML_NO_CONTENT
, &xml_sax_calculation
, NULL
),
3270 GSF_XML_IN_NODE (WB
, WB_DATE
, GNM
, "DateConvention", GSF_XML_CONTENT
, NULL
, &xml_sax_old_dateconvention
),
3271 GSF_XML_IN_NODE (WB
, GODOC
, -1, "GODoc", GSF_XML_NO_CONTENT
, &xml_sax_go_doc
, NULL
),
3272 GSF_XML_IN_NODE (WB
, DOCUMENTMETA
, OO_NS_OFFICE
, "document-meta", GSF_XML_NO_CONTENT
, &xml_sax_document_meta
, NULL
),
3277 xml_sax_clipboardrange_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
3279 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3280 int cols
= -1, rows
= -1, base_col
= -1, base_row
= -1;
3283 cr
= state
->clipboard
= gnm_cell_region_new (state
->sheet
);
3285 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
3286 if (gnm_xml_attr_int (attrs
, "Cols", &cols
) ||
3287 gnm_xml_attr_int (attrs
, "Rows", &rows
) ||
3288 gnm_xml_attr_int (attrs
, "BaseCol", &base_col
) ||
3289 gnm_xml_attr_int (attrs
, "BaseRow", &base_row
) ||
3290 gnm_xml_attr_bool (attrs
, "NotAsContent", &cr
->not_as_contents
))
3292 else if (attr_eq (attrs
[0], "DateConvention")) {
3293 GODateConventions
const *date_conv
=
3294 go_date_conv_from_str (CXML2C (attrs
[1]));
3296 cr
->date_conv
= date_conv
;
3298 g_printerr ("Ignoring invalid date conventions.\n");
3302 if (cols
<= 0 || rows
<= 0 || base_col
< 0 || base_row
< 0) {
3303 g_printerr ("Invalid clipboard contents.\n");
3307 cr
->base
.col
= base_col
;
3308 cr
->base
.row
= base_row
;
3312 static GsfXMLInNode clipboard_dtd
[] = {
3313 GSF_XML_IN_NODE_FULL (START
, START
, -1, NULL
, GSF_XML_NO_CONTENT
, FALSE
, TRUE
, NULL
, NULL
, 0),
3314 GSF_XML_IN_NODE_FULL (START
, CLIPBOARDRANGE
, GNM
, "ClipboardRange", GSF_XML_NO_CONTENT
, TRUE
, TRUE
, xml_sax_clipboardrange_start
, NULL
, 0),
3315 /* We insert "Styles" (etc) */
3320 gnm_xml_in_doc_add_subset (GsfXMLInDoc
*doc
, GsfXMLInNode
*dtd
,
3321 const char *id
, const char *new_parent
)
3323 GHashTable
*parents
= g_hash_table_new (g_str_hash
, g_str_equal
);
3324 GsfXMLInNode end_node
= GSF_XML_IN_NODE_END
;
3325 GArray
*new_dtd
= g_array_new (FALSE
, FALSE
, sizeof (GsfXMLInNode
));
3327 for (; dtd
->id
; dtd
++) {
3328 GsfXMLInNode node
= *dtd
;
3330 if (g_str_equal (id
, dtd
->id
)) {
3331 g_hash_table_insert (parents
,
3335 node
.parent_id
= new_parent
;
3336 } else if (g_hash_table_lookup (parents
, dtd
->parent_id
))
3337 g_hash_table_insert (parents
,
3343 g_array_append_val (new_dtd
, node
);
3346 g_array_append_val (new_dtd
, end_node
);
3348 gsf_xml_in_doc_add_nodes (doc
, (GsfXMLInNode
*)(new_dtd
->data
));
3350 g_array_free (new_dtd
, TRUE
);
3351 g_hash_table_destroy (parents
);
3356 xml_sax_unknown (GsfXMLIn
*xin
, xmlChar
const *elem
, xmlChar
const **attrs
)
3358 g_return_val_if_fail (xin
!= NULL
, FALSE
);
3359 g_return_val_if_fail (xin
->doc
!= NULL
, FALSE
);
3360 g_return_val_if_fail (xin
->node
!= NULL
, FALSE
);
3362 if (GNM
== xin
->node
->ns_id
&&
3363 0 == strcmp (xin
->node
->id
, "SHEET_OBJECTS")) {
3364 char const *type_name
= gsf_xml_in_check_ns (xin
, CXML2C (elem
), GNM
);
3365 if (type_name
!= NULL
) {
3366 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3367 /* This may change xin->user_state. */
3368 xml_sax_read_obj (xin
, TRUE
, type_name
, attrs
);
3369 /* xin->user_state hasn't been restored yet. */
3370 return state
->so
!= NULL
;
3377 read_file_init_state (XMLSaxParseState
*state
,
3378 GOIOContext
*io_context
,
3379 WorkbookView
*wb_view
, Sheet
*sheet
)
3381 state
->context
= io_context
;
3382 state
->wb_view
= wb_view
;
3385 : (wb_view
? wb_view_get_workbook (wb_view
) : NULL
);
3386 state
->sheet
= sheet
;
3387 state
->version
= GNM_XML_UNKNOWN
;
3388 state
->last_progress_update
= 0;
3389 state
->convs
= gnm_xml_io_conventions ();
3390 state
->attribute
.name
= state
->attribute
.value
= NULL
;
3391 state
->name
.name
= state
->name
.value
= state
->name
.position
= NULL
;
3392 state
->style_range_init
= FALSE
;
3393 state
->style
= NULL
;
3394 state
->cell
.row
= state
->cell
.col
= -1;
3395 state
->seen_cell_contents
= FALSE
;
3396 state
->array_rows
= state
->array_cols
= -1;
3397 state
->expr_id
= -1;
3398 state
->value_type
= -1;
3399 state
->value_fmt
= NULL
;
3400 state
->value_result
= NULL
;
3401 state
->scenario
= NULL
;
3402 state
->scenario_range
= NULL
;
3403 state
->filter
= NULL
;
3404 state
->validation
.title
= state
->validation
.msg
= NULL
;
3405 state
->validation
.texpr
[0] = state
->validation
.texpr
[1] = NULL
;
3407 state
->cond_save_style
= NULL
;
3408 state
->expr_map
= g_hash_table_new_full
3409 (g_direct_hash
, g_direct_equal
,
3410 NULL
, (GFreeFunc
)gnm_expr_top_unref
);
3411 state
->delayed_names
= NULL
;
3413 state
->page_breaks
= NULL
;
3414 state
->clipboard
= NULL
;
3415 state
->style_handler
= NULL
;
3416 state
->style_handler_user
= NULL
;
3417 state
->style_handler_doc
= NULL
;
3421 read_file_free_state (XMLSaxParseState
*state
, gboolean self
)
3423 g_hash_table_destroy (state
->expr_map
);
3424 state
->expr_map
= NULL
;
3426 gnm_conventions_unref (state
->convs
);
3427 state
->convs
= NULL
;
3430 * Malformed documents can cause the parser to exit early.
3431 * This cleans up various bits that may be left.
3435 gnm_style_unref (state
->style
);
3436 state
->style
= NULL
;
3439 if (state
->cond_save_style
) {
3440 gnm_style_unref (state
->cond_save_style
);
3441 state
->cond_save_style
= NULL
;
3445 gnm_style_cond_free (state
->cond
);
3449 if (state
->style_handler_doc
) {
3450 gsf_xml_in_doc_free (state
->style_handler_doc
);
3451 state
->style_handler_doc
= NULL
;
3459 read_file_common (ReadFileWhat what
, XMLSaxParseState
*state
,
3460 GOIOContext
*io_context
,
3461 WorkbookView
*wb_view
, Sheet
*sheet
,
3468 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wb_view
), FALSE
);
3469 g_return_val_if_fail (GSF_IS_INPUT (input
), FALSE
);
3471 read_file_init_state (state
, io_context
, wb_view
, sheet
);
3474 case READ_FULL_FILE
:
3475 state
->do_progress
= TRUE
;
3476 doc
= gsf_xml_in_doc_new (gnumeric_1_0_dtd
, content_ns
);
3478 case READ_CLIPBOARD
:
3479 state
->do_progress
= FALSE
;
3480 doc
= gsf_xml_in_doc_new (clipboard_dtd
, content_ns
);
3483 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3486 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3489 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3492 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3495 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3496 "SHEET_MERGED_REGIONS",
3498 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3503 g_assert_not_reached ();
3510 gsf_xml_in_doc_set_unknown_handler (doc
, &xml_sax_unknown
);
3512 go_doc_init_read (GO_DOC (state
->wb
), input
);
3513 gsf_input_seek (input
, 0, G_SEEK_SET
);
3515 if (state
->do_progress
) {
3516 go_io_progress_message (state
->context
,
3517 _("Reading file..."));
3518 go_io_value_progress_set (state
->context
,
3519 gsf_input_size (input
), 0);
3522 locale
= gnm_push_C_locale ();
3523 ok
= gsf_xml_in_doc_parse (doc
, input
, state
);
3524 handle_delayed_names (state
);
3525 gnm_pop_C_locale (locale
);
3527 go_doc_end_read (GO_DOC (state
->wb
));
3529 if (state
->do_progress
)
3530 go_io_progress_unset (state
->context
);
3533 go_io_error_string (state
->context
,
3534 _("XML document not well formed!"));
3537 gsf_xml_in_doc_free (doc
);
3542 /* ------------------------------------------------------------------------- */
3545 maybe_gunzip (GsfInput
*input
)
3547 GsfInput
*gzip
= gsf_input_gzip_new (input
, NULL
);
3549 g_object_unref (input
);
3552 gsf_input_seek (input
, 0, G_SEEK_SET
);
3558 maybe_convert (GsfInput
*input
, gboolean quiet
)
3560 static char const *noencheader
= "<?xml version=\"1.0\"?>";
3561 static char const *encheader
= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
3562 const size_t nelen
= strlen (noencheader
);
3563 const size_t elen
= strlen (encheader
);
3565 gsf_off_t input_size
;
3566 GString the_buffer
, *buffer
= &the_buffer
;
3568 GString
*converted
= NULL
;
3569 char const *encoding
;
3571 gboolean any_numbered
= FALSE
;
3573 input_size
= gsf_input_remaining (input
);
3575 buf
= gsf_input_read (input
, nelen
, NULL
);
3577 strncmp (noencheader
, (const char *)buf
, nelen
) != 0 ||
3578 input_size
>= (gsf_off_t
)(G_MAXINT
- elen
))
3581 input_size
-= nelen
;
3584 the_buffer
.allocated_len
= input_size
+ elen
+ 1;
3585 the_buffer
.str
= g_try_malloc (the_buffer
.allocated_len
);
3586 if (!the_buffer
.str
)
3589 g_string_append (buffer
, encheader
);
3590 ok
= gsf_input_read (input
, input_size
, (guint8
*)buffer
->str
+ elen
) != NULL
;
3591 gsf_input_seek (input
, 0, G_SEEK_SET
);
3593 g_free (buffer
->str
);
3596 buffer
->len
= input_size
+ elen
;
3597 buffer
->str
[buffer
->len
] = 0;
3599 for (ui
= 0; ui
< buffer
->len
; ui
++) {
3600 if (buffer
->str
[ui
] == '&' &&
3601 buffer
->str
[ui
+ 1] == '#' &&
3602 g_ascii_isdigit (buffer
->str
[ui
+ 2])) {
3606 while (g_ascii_isdigit (buffer
->str
[ui
])) {
3607 c
= c
* 10 + (buffer
->str
[ui
] - '0');
3610 if (buffer
->str
[ui
] == ';' && c
>= 128 && c
<= 255) {
3611 buffer
->str
[start
] = c
;
3612 g_string_erase (buffer
, start
+ 1, ui
- start
);
3615 any_numbered
= TRUE
;
3619 encoding
= go_guess_encoding (buffer
->str
, buffer
->len
, NULL
, &converted
, NULL
);
3620 if (encoding
&& !any_numbered
&&
3621 converted
&& buffer
->len
== converted
->len
&&
3622 strcmp (buffer
->str
, converted
->str
) == 0)
3625 g_free (buffer
->str
);
3628 gsize len
= converted
->len
;
3629 g_object_unref (input
);
3631 g_warning ("Converted xml document with no explicit encoding from transliterated %s to UTF-8.",
3633 return gsf_input_memory_new ((void *)g_string_free (converted
, FALSE
), len
, TRUE
);
3636 g_warning ("Failed to convert xml document with no explicit encoding to UTF-8.");
3642 gnm_xml_file_open (G_GNUC_UNUSED GOFileOpener
const *fo
, GOIOContext
*io_context
,
3643 GoView
*view
, GsfInput
*input
)
3645 XMLSaxParseState state
;
3648 g_object_ref (input
);
3649 input
= maybe_gunzip (input
);
3650 input
= maybe_convert (input
, FALSE
);
3652 ok
= read_file_common (READ_FULL_FILE
, &state
,
3653 io_context
, GNM_WORKBOOK_VIEW (view
), NULL
,
3656 g_object_unref (input
);
3659 workbook_queue_all_recalc (state
.wb
);
3661 workbook_set_saveinfo
3664 go_file_saver_for_id ("Gnumeric_XmlIO:sax"));
3667 read_file_free_state (&state
, FALSE
);
3670 /* ------------------------------------------------------------------------- */
3673 gnm_xml_cellregion_read (WorkbookControl
*wbc
, GOIOContext
*io_context
,
3675 const char *buffer
, int length
)
3677 WorkbookView
*wb_view
;
3679 XMLSaxParseState state
;
3680 GnmCellRegion
*result
;
3682 wb_view
= wb_control_view (wbc
);
3683 input
= gsf_input_memory_new (buffer
, length
, FALSE
);
3684 read_file_common (READ_CLIPBOARD
, &state
,
3685 io_context
, wb_view
, sheet
,
3687 g_object_unref (input
);
3689 result
= state
.clipboard
;
3690 state
.clipboard
= NULL
;
3692 read_file_free_state (&state
, FALSE
);
3697 /* ------------------------------------------------------------------------- */
3700 style_parser_done (GsfXMLIn
*xin
, XMLSaxParseState
*old_state
)
3702 GnmStyle
*style
= old_state
->style
;
3703 old_state
->style_handler (xin
, style
, old_state
->style_handler_user
);
3704 read_file_free_state (old_state
, TRUE
);
3708 * gnm_xml_prep_style_parser:
3711 * @handler: (scope async):
3716 gnm_xml_prep_style_parser (GsfXMLIn
*xin
,
3717 xmlChar
const **attrs
,
3718 GnmXmlStyleHandler handler
,
3721 static GsfXMLInNode dtd
[] = {
3722 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, &xml_sax_style_start
, NULL
),
3723 /* Nodes added below. */
3726 GsfXMLInDoc
*doc
= gsf_xml_in_doc_new (dtd
, NULL
);
3727 XMLSaxParseState
*state
= g_new0 (XMLSaxParseState
, 1);
3729 read_file_init_state (state
, NULL
, NULL
, NULL
);
3730 state
->style_handler
= handler
;
3731 state
->style_handler_user
= user
;
3732 state
->style_handler_doc
= doc
;
3733 state
->style
= gnm_style_new_default ();
3735 /* Not a full style, just those parts that do not require a sheet. */
3736 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3739 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3743 gsf_xml_in_push_state (xin
, doc
, state
,
3744 (GsfXMLInExtDtor
)style_parser_done
, attrs
);
3747 /* ------------------------------------------------------------------------- */
3750 gnm_xml_probe_element (const xmlChar
*name
,
3751 G_GNUC_UNUSED
const xmlChar
*prefix
,
3753 G_GNUC_UNUSED
int nb_namespaces
,
3754 G_GNUC_UNUSED
const xmlChar
**namespaces
,
3755 G_GNUC_UNUSED
int nb_attributes
,
3756 G_GNUC_UNUSED
int nb_defaulted
,
3757 G_GNUC_UNUSED
const xmlChar
**attributes
)
3759 return 0 == strcmp (name
, "Workbook") &&
3760 NULL
!= URI
&& NULL
!= strstr (URI
, "gnumeric");
3764 xml_probe (G_GNUC_UNUSED GOFileOpener
const *fo
, GsfInput
*input
, GOFileProbeLevel pl
)
3766 if (pl
== GO_FILE_PROBE_FILE_NAME
) {
3767 char const *name
= gsf_input_name (input
);
3773 len
= strlen (name
);
3774 if (len
>= 7 && !g_ascii_strcasecmp (name
+len
-7, ".xml.gz"))
3777 name
= gsf_extension_pointer (name
);
3779 return (name
!= NULL
&&
3780 (g_ascii_strcasecmp (name
, "gnumeric") == 0 ||
3781 g_ascii_strcasecmp (name
, "xml") == 0));
3783 /* probe by content */
3784 return gsf_xml_probe (input
, &gnm_xml_probe_element
);
3787 #define XML_SAX_ID "Gnumeric_XmlIO:sax"
3790 gnm_xml_sax_read_init (void)
3792 GOFileOpener
*opener
;
3793 GSList
*suffixes
= go_slist_create (g_strdup ("gnumeric"),
3796 GSList
*mimes
= go_slist_create (g_strdup ("application/x-gnumeric"),
3799 opener
= go_file_opener_new
3801 _("Gnumeric XML (*.gnumeric)"),
3803 xml_probe
, gnm_xml_file_open
);
3804 go_file_opener_register (opener
, 50);
3805 g_object_unref (opener
);
3809 gnm_xml_sax_read_shutdown (void)
3811 go_file_opener_unregister
3812 (go_file_opener_for_id (XML_SAX_ID
));