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 /*****************************************************************************/
305 GOIOContext
*context
; /* The IOcontext managing things */
306 WorkbookView
*wb_view
; /* View for the new workbook */
307 Workbook
*wb
; /* The new workbook */
308 GnumericXMLVersion version
;
309 gsf_off_t last_progress_update
;
310 GnmConventions
*convs
;
311 gboolean do_progress
;
316 /* Only valid while parsing attributes */
322 /* Only valid when parsing wb or sheet names */
332 GnmExprTop
const *texpr
[2];
333 ValidationStyle style
;
336 gboolean allow_blank
;
337 gboolean use_dropdown
;
341 GnmStyle
*cond_save_style
;
343 gboolean style_range_init
;
344 GnmRange style_range
;
348 gboolean seen_cell_contents
;
349 int expr_id
, array_rows
, array_cols
;
353 GnmScenario
*scenario
;
354 GnmValue
*scenario_range
;
358 int display_formulas
;
363 int display_outlines
;
364 int outline_symbols_below
;
365 int outline_symbols_right
;
368 char *expr_conv_name
;
369 GnmSheetVisibility visibility
;
371 GnmColor
*tab_text_color
;
372 GnmColor
*grid_color
;
374 /* expressions with ref > 1 a map from index -> expr pointer */
375 GHashTable
*expr_map
;
376 GList
*delayed_names
;
379 int sheet_rows
, sheet_cols
;
380 GnmSheetType sheet_type
;
382 GnmPageBreaks
*page_breaks
;
384 GnmCellRegion
*clipboard
;
386 GnmXmlStyleHandler style_handler
;
387 gpointer style_handler_user
;
388 GsfXMLInDoc
*style_handler_doc
;
392 maybe_update_progress (GsfXMLIn
*xin
)
394 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
395 GsfInput
*input
= gsf_xml_in_get_input (xin
);
396 gsf_off_t pos
= gsf_input_tell (input
);
398 if (state
->do_progress
&& pos
>= state
->last_progress_update
+ 10000) {
399 go_io_value_progress_update (state
->context
, pos
);
400 state
->last_progress_update
= pos
;
405 * gnm_xml_in_cur_obj:
408 * Returns: (transfer none): the current sheet object.
411 gnm_xml_in_cur_obj (GsfXMLIn
const *xin
)
413 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
418 * gnm_xml_in_cur_sheet:
421 * Returns: (transfer none): the current sheet.
424 gnm_xml_in_cur_sheet (GsfXMLIn
const *xin
)
426 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
431 gnm_xml_finish_obj (GsfXMLIn
*xin
, XMLSaxParseState
*state
)
433 GnmCellRegion
*cr
= state
->clipboard
;
436 cr
->objects
= g_slist_prepend (cr
->objects
, state
->so
);
438 sheet_object_set_sheet (state
->so
, state
->sheet
);
439 g_object_unref (state
->so
);
445 /****************************************************************************/
448 unknown_attr (GsfXMLIn
*xin
, xmlChar
const * const *attrs
)
450 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
452 if (state
->version
== GNM_XML_LATEST
)
453 go_io_warning (state
->context
,
454 _("Unexpected attribute %s::%s == '%s'."),
455 (NULL
!= xin
->node
&&
456 NULL
!= xin
->node
->name
) ?
457 xin
->node
->name
: "<unknown name>",
462 xml_sax_wb (GsfXMLIn
*xin
, xmlChar
const **attrs
)
464 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
467 * NOTE: If we read a file with a dtd that is newer, i.e., from the
468 * future, then we will not get here! For that reason we also muck
469 * with ->version in xml_sax_version.
471 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
472 if (strcmp (CXML2C (attrs
[0]), "xmlns:gmr") == 0 ||
473 strcmp (CXML2C (attrs
[0]), "xmlns:gnm") == 0) {
475 char const * const id
;
476 GnumericXMLVersion
const version
;
477 } const GnumericVersions
[] = {
478 { "http://www.gnumeric.org/v14.dtd", GNM_XML_V14
}, /* 1.12.21 */
479 { "http://www.gnumeric.org/v13.dtd", GNM_XML_V13
}, /* 1.7.7 */
480 { "http://www.gnumeric.org/v12.dtd", GNM_XML_V12
}, /* 1.7.3 */
481 { "http://www.gnumeric.org/v11.dtd", GNM_XML_V11
}, /* 1.7.0 */
482 { "http://www.gnumeric.org/v10.dtd", GNM_XML_V10
}, /* 1.0.3 */
483 { "http://www.gnumeric.org/v9.dtd", GNM_XML_V9
}, /* 0.73 */
484 { "http://www.gnumeric.org/v8.dtd", GNM_XML_V8
}, /* 0.71 */
485 { "http://www.gnome.org/gnumeric/v7", GNM_XML_V7
}, /* 0.66 */
486 { "http://www.gnome.org/gnumeric/v6", GNM_XML_V6
}, /* 0.62 */
487 { "http://www.gnome.org/gnumeric/v5", GNM_XML_V5
},
488 { "http://www.gnome.org/gnumeric/v4", GNM_XML_V4
},
489 { "http://www.gnome.org/gnumeric/v3", GNM_XML_V3
},
490 { "http://www.gnome.org/gnumeric/v2", GNM_XML_V2
},
491 { "http://www.gnome.org/gnumeric/", GNM_XML_V1
},
495 for (i
= 0 ; GnumericVersions
[i
].id
!= NULL
; ++i
)
496 if (strcmp (CXML2C (attrs
[1]), GnumericVersions
[i
].id
) == 0) {
497 if (state
->version
!= GNM_XML_UNKNOWN
)
498 go_io_warning (state
->context
,
499 _("Multiple version specifications. Assuming %d"),
502 state
->version
= GnumericVersions
[i
].version
;
506 } else if (attr_eq (attrs
[0], "xmlns:xsi")) {
507 } else if (attr_eq (attrs
[0], "xsi:schemaLocation")) {
509 unknown_attr (xin
, attrs
);
514 xml_sax_document_meta (GsfXMLIn
*xin
, G_GNUC_UNUSED xmlChar
const **attrs
)
516 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
518 gsf_doc_meta_data_odf_subtree (go_doc_get_meta_data (GO_DOC (state
->wb
)), xin
);
524 xml_sax_version (GsfXMLIn
*xin
, xmlChar
const **attrs
)
526 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
532 state
->version
= GNM_XML_V11
;
533 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
534 if (gnm_xml_attr_int (attrs
, "Epoch", &epoch
))
536 else if (gnm_xml_attr_int (attrs
, "Major", &major
))
538 else if (gnm_xml_attr_int (attrs
, "Minor", &minor
))
542 version
= (epoch
* 100 + major
) * 100 + minor
;
543 if (state
->version
== GNM_XML_UNKNOWN
&& version
>= 10700) {
544 if (version
>= 11221)
545 state
->version
= GNM_XML_V14
;
546 else if (version
>= 10707)
547 state
->version
= GNM_XML_V13
;
548 else if (version
>= 10705)
549 state
->version
= GNM_XML_V12
;
550 else if (version
>= 10700)
551 state
->version
= GNM_XML_V11
;
556 xml_sax_wb_sheetsize (GsfXMLIn
*xin
, xmlChar
const **attrs
)
558 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
560 /* Defaults for legacy files. */
561 state
->sheet_cols
= 256;
562 state
->sheet_rows
= 65536;
563 state
->sheet_type
= GNM_SHEET_DATA
;
565 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
566 if (gnm_xml_attr_int (attrs
, "gnm:Cols", &state
->sheet_cols
))
568 else if (gnm_xml_attr_int (attrs
, "gnm:Rows", &state
->sheet_rows
))
570 else if (!strcmp (CXML2C (attrs
[0]), "gnm:SheetType") &&
571 !strcmp (CXML2C (attrs
[1]), "object"))
572 state
->sheet_type
= GNM_SHEET_OBJECT
;
574 unknown_attr (xin
, attrs
);
579 xml_sax_wb_sheetname (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
581 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
582 char const *name
= xin
->content
->str
;
583 Workbook
*wb
= state
->wb
;
585 g_return_if_fail (name
!= NULL
);
587 if (NULL
== workbook_sheet_by_name (wb
, name
)) {
590 if (!gnm_sheet_valid_size (state
->sheet_cols
,
591 state
->sheet_rows
)) {
592 gnm_sheet_suggest_size (&state
->sheet_cols
,
596 sheet
= sheet_new_with_type (wb
, name
,
600 workbook_sheet_attach (wb
, sheet
);
605 xml_sax_wb_view (GsfXMLIn
*xin
, xmlChar
const **attrs
)
607 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
610 int width
= -1, height
= -1;
612 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
613 if (gnm_xml_attr_int (attrs
, "SelectedTab", &sheet_index
)) {
614 Sheet
*sheet
= workbook_sheet_by_index (state
->wb
,
617 wb_view_sheet_focus (state
->wb_view
, sheet
);
619 else if (gnm_xml_attr_int (attrs
, "Width", &width
)) ;
620 else if (gnm_xml_attr_int (attrs
, "Height", &height
)) ;
622 unknown_attr (xin
, attrs
);
624 if (width
> 0 && height
> 0)
625 wb_view_preferred_size (state
->wb_view
, width
, height
);
628 xml_sax_calculation (GsfXMLIn
*xin
, xmlChar
const **attrs
)
630 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
635 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
636 if (gnm_xml_attr_bool (attrs
, "ManualRecalc", &b
))
637 workbook_set_recalcmode (state
->wb
, !b
);
638 else if (gnm_xml_attr_bool (attrs
, "EnableIteration", &b
))
639 workbook_iteration_enabled (state
->wb
, b
);
640 else if (gnm_xml_attr_int (attrs
, "MaxIterations", &i
))
641 workbook_iteration_max_number (state
->wb
, i
);
642 else if (gnm_xml_attr_double (attrs
, "IterationTolerance", &d
))
643 workbook_iteration_tolerance (state
->wb
, d
);
644 else if (strcmp (CXML2C (attrs
[0]), "DateConvention") == 0) {
645 GODateConventions
const *date_conv
=
646 go_date_conv_from_str (CXML2C (attrs
[1]));
648 workbook_set_date_conv (state
->wb
, date_conv
);
650 g_printerr ("Ignoring invalid date conventions.\n");
652 unknown_attr (xin
, attrs
);
656 xml_sax_old_dateconvention (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
658 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
659 workbook_set_1904 (state
->wb
, strcmp (xin
->content
->str
, "1904") == 0);
663 xml_sax_finish_parse_wb_attr (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
665 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
667 if (state
->attribute
.name
&& state
->attribute
.value
) {
668 wb_view_set_attribute (state
->wb_view
,
669 state
->attribute
.name
,
670 state
->attribute
.value
);
672 xml_sax_barf (G_STRFUNC
, _("workbook view attribute is incomplete"));
675 g_free (state
->attribute
.value
); state
->attribute
.value
= NULL
;
676 g_free (state
->attribute
.name
); state
->attribute
.name
= NULL
;
680 xml_sax_attr_elem (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
682 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
684 char const *content
= xin
->content
->str
;
685 int const len
= xin
->content
->len
;
687 switch (xin
->node
->user_data
.v_int
) {
689 g_return_if_fail (state
->attribute
.name
== NULL
);
690 state
->attribute
.name
= g_strndup (content
, len
);
694 g_return_if_fail (state
->attribute
.value
== NULL
);
695 state
->attribute
.value
= g_strndup (content
, len
);
699 g_assert_not_reached ();
704 xml_sax_sheet_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
706 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
710 GnmColor
*color
= NULL
;
712 state
->hide_col_header
= state
->hide_row_header
=
713 state
->display_formulas
= state
->hide_zero
=
714 state
->hide_grid
= state
->display_outlines
=
715 state
->outline_symbols_below
= state
->outline_symbols_right
=
716 state
->text_is_rtl
= state
->is_protected
= -1;
717 state
->expr_conv_name
= NULL
;
718 state
->visibility
= GNM_SHEET_VISIBILITY_VISIBLE
;
719 state
->tab_color
= NULL
;
720 state
->tab_text_color
= NULL
;
721 state
->grid_color
= NULL
;
722 state
->sheet_zoom
= 1.; /* default */
724 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
725 if (gnm_xml_attr_bool (attrs
, "DisplayFormulas", &tmp
))
726 state
->display_formulas
= tmp
;
727 else if (gnm_xml_attr_bool (attrs
, "HideZero", &tmp
))
728 state
->hide_zero
= tmp
;
729 else if (gnm_xml_attr_bool (attrs
, "HideGrid", &tmp
))
730 state
->hide_grid
= tmp
;
731 else if (gnm_xml_attr_bool (attrs
, "HideColHeader", &tmp
))
732 state
->hide_col_header
= tmp
;
733 else if (gnm_xml_attr_bool (attrs
, "HideRowHeader", &tmp
))
734 state
->hide_row_header
= tmp
;
735 else if (gnm_xml_attr_bool (attrs
, "DisplayOutlines", &tmp
))
736 state
->display_outlines
= tmp
;
737 else if (gnm_xml_attr_bool (attrs
, "OutlineSymbolsBelow", &tmp
))
738 state
->outline_symbols_below
= tmp
;
739 else if (gnm_xml_attr_bool (attrs
, "OutlineSymbolsRight", &tmp
))
740 state
->outline_symbols_right
= tmp
;
741 else if (xml_sax_attr_enum (attrs
, "Visibility", GNM_SHEET_VISIBILITY_TYPE
, &tmpi
))
742 state
->visibility
= tmpi
;
743 else if (gnm_xml_attr_bool (attrs
, "RTL_Layout", &tmp
))
744 state
->text_is_rtl
= tmp
;
745 else if (gnm_xml_attr_bool (attrs
, "Protected", &tmp
))
746 state
->is_protected
= tmp
;
747 else if (strcmp (CXML2C (attrs
[0]), "ExprConvention") == 0)
748 state
->expr_conv_name
= g_strdup (attrs
[1]);
749 else if (xml_sax_attr_color (attrs
, "TabColor", &color
))
750 state
->tab_color
= color
;
751 else if (xml_sax_attr_color (attrs
, "TabTextColor", &color
))
752 state
->tab_text_color
= color
;
753 else if (xml_sax_attr_color (attrs
, "GridColor", &color
))
754 state
->grid_color
= color
;
756 unknown_attr (xin
, attrs
);
760 xml_sax_must_have_sheet (XMLSaxParseState
*state
)
766 xml_sax_barf (G_STRFUNC
, "sheet should have been named");
768 state
->sheet
= workbook_sheet_add (state
->wb
, -1,
776 xml_sax_must_have_style (XMLSaxParseState
*state
)
779 xml_sax_barf (G_STRFUNC
, "style should have been started");
780 state
->style
= (state
->version
>= GNM_XML_V6
||
781 state
->version
<= GNM_XML_V2
)
782 ? gnm_style_new_default ()
791 xml_sax_sheet_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
793 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
795 xml_sax_must_have_sheet (state
);
797 /* Init ColRowInfo's size_pixels and force a full respan */
798 g_object_set (state
->sheet
, "zoom-factor", state
->sheet_zoom
, NULL
);
799 sheet_flag_recompute_spans (state
->sheet
);
804 xml_sax_sheet_name (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
806 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
811 char const * content
= xin
->content
->str
;
812 g_return_if_fail (state
->sheet
== NULL
);
814 /* * FIXME: Pull this out at some point, so we don't
815 * have to support < GNM_XML_V7 anymore
817 if (state
->version
>= GNM_XML_V7
) {
818 sheet
= workbook_sheet_by_name (state
->wb
, content
);
820 go_io_error_string (state
->context
,
821 _("File has inconsistent SheetNameIndex element."));
822 sheet
= sheet_new (state
->wb
, content
,
824 workbook_sheet_attach (state
->wb
, sheet
);
827 sheet
= sheet_new (state
->wb
, content
, columns
, rows
);
828 workbook_sheet_attach (state
->wb
, sheet
);
830 state
->sheet
= sheet
;
832 if (state
->display_formulas
>= 0)
833 g_object_set (sheet
, "display-formulas", state
->display_formulas
, NULL
);
834 if (state
->hide_zero
>= 0)
835 g_object_set (sheet
, "display-zeros", !state
->hide_zero
, NULL
);
836 if (state
->hide_grid
>= 0)
837 g_object_set (sheet
, "display-grid", !state
->hide_grid
, NULL
);
838 if (state
->hide_col_header
>= 0)
839 g_object_set (sheet
, "display-column-header", !state
->hide_col_header
, NULL
);
840 if (state
->hide_row_header
>= 0)
841 g_object_set (sheet
, "display-row-header", !state
->hide_row_header
, NULL
);
842 if (state
->display_outlines
>= 0)
843 g_object_set (sheet
, "display-outlines", state
->display_outlines
, NULL
);
844 if (state
->outline_symbols_below
>= 0)
845 g_object_set (sheet
, "display-outlines-below", state
->outline_symbols_below
, NULL
);
846 if (state
->outline_symbols_right
>= 0)
847 g_object_set (sheet
, "display-outlines-right", state
->outline_symbols_right
, NULL
);
848 if (state
->text_is_rtl
>= 0)
849 g_object_set (sheet
, "text-is-rtl", state
->text_is_rtl
, NULL
);
850 if (state
->is_protected
>= 0)
851 g_object_set (sheet
, "protected", state
->is_protected
, NULL
);
852 if (state
->expr_conv_name
!= NULL
) {
853 GnmConventions
const *convs
= gnm_conventions_default
;
854 if (0 == strcmp (state
->expr_conv_name
, "gnumeric:R1C1"))
855 convs
= gnm_conventions_xls_r1c1
;
856 g_object_set (sheet
, "conventions", convs
, NULL
);
858 g_free (state
->expr_conv_name
);
859 state
->expr_conv_name
= NULL
;
861 g_object_set (sheet
, "visibility", state
->visibility
, NULL
);
862 sheet
->tab_color
= state
->tab_color
;
863 sheet
->tab_text_color
= state
->tab_text_color
;
864 if (state
->grid_color
)
865 sheet_style_set_auto_pattern_color (sheet
, state
->grid_color
);
869 xml_sax_sheet_zoom (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
871 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
873 char const * content
= xin
->content
->str
;
876 xml_sax_must_have_sheet (state
);
878 if (xml_sax_double ((xmlChar
*)content
, &zoom
))
879 state
->sheet_zoom
= zoom
;
883 xml_sax_print_margins_unit (GsfXMLIn
*xin
, xmlChar
const **attrs
,
884 double *points
, GtkUnit
*desired_display
)
886 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
888 if (gnm_xml_attr_double (attrs
, "Points", &pts
)) {
890 } else if (attr_eq (attrs
[0], "PrefUnit")) {
891 *desired_display
= unit_name_to_unit (CXML2C (attrs
[1]));
893 unknown_attr (xin
, attrs
);
898 xml_sax_print_margins (GsfXMLIn
*xin
, xmlChar
const **attrs
)
900 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
902 GnmPrintInformation
*pi
;
905 xml_sax_must_have_sheet (state
);
907 pi
= state
->sheet
->print_info
;
908 switch (xin
->node
->user_data
.v_int
) {
910 xml_sax_print_margins_unit (xin
, attrs
,
912 &pi
->desired_display
.header
);
914 print_info_set_edge_to_below_header (pi
, points
);
917 xml_sax_print_margins_unit (xin
, attrs
,
919 &pi
->desired_display
.footer
);
921 print_info_set_edge_to_above_footer (pi
, points
);
924 xml_sax_print_margins_unit (xin
, attrs
,
925 &points
, &pi
->desired_display
.left
);
927 print_info_set_margin_left (pi
, points
);
930 xml_sax_print_margins_unit (xin
, attrs
,
931 &points
, &pi
->desired_display
.right
);
933 print_info_set_margin_right (pi
, points
);
936 xml_sax_print_margins_unit (xin
, attrs
,
937 &points
, &pi
->desired_display
.top
);
939 print_info_set_margin_header (pi
, points
);
942 xml_sax_print_margins_unit (xin
, attrs
,
943 &points
, &pi
->desired_display
.bottom
);
945 print_info_set_margin_footer (pi
, points
);
954 xml_sax_page_break (GsfXMLIn
*xin
, xmlChar
const **attrs
)
956 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
957 GnmPageBreakType type
= GNM_PAGE_BREAK_NONE
;
960 if (NULL
== state
->page_breaks
)
963 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
964 if (gnm_xml_attr_int (attrs
, "pos", &pos
)) ;
965 else if (!strcmp (CXML2C (attrs
[0]), "type"))
966 type
= gnm_page_break_type_from_str (CXML2C (attrs
[1]));
968 /* drops invalid positions */
969 gnm_page_breaks_append_break (state
->page_breaks
, pos
, type
);
973 xml_sax_page_breaks_begin (GsfXMLIn
*xin
, G_GNUC_UNUSED xmlChar
const **attrs
)
975 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
976 xml_sax_must_have_sheet (state
);
977 g_return_if_fail (state
->page_breaks
== NULL
);
978 state
->page_breaks
= gnm_page_breaks_new (xin
->node
->user_data
.v_int
);
982 xml_sax_page_breaks_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
984 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
986 if (NULL
!= state
->page_breaks
) {
987 print_info_set_breaks (state
->sheet
->print_info
,
989 state
->page_breaks
= NULL
;
994 xml_sax_print_scale (GsfXMLIn
*xin
, xmlChar
const **attrs
)
996 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
998 GnmPrintInformation
*pi
;
1002 xml_sax_must_have_sheet (state
);
1004 pi
= state
->sheet
->print_info
;
1005 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1006 if (attr_eq (attrs
[0], "type"))
1007 pi
->scaling
.type
= !strcmp (CXML2C (attrs
[1]), "percentage")
1008 ? PRINT_SCALE_PERCENTAGE
: PRINT_SCALE_FIT_PAGES
;
1009 else if (gnm_xml_attr_double (attrs
, "percentage", &percentage
))
1010 pi
->scaling
.percentage
.x
= pi
->scaling
.percentage
.y
= percentage
;
1011 else if (gnm_xml_attr_int (attrs
, "cols", &cols
))
1012 pi
->scaling
.dim
.cols
= cols
;
1013 else if (gnm_xml_attr_int (attrs
, "rows", &rows
))
1014 pi
->scaling
.dim
.rows
= rows
;
1019 xml_sax_print_vcenter (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1021 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1022 GnmPrintInformation
*pi
;
1025 xml_sax_must_have_sheet (state
);
1027 pi
= state
->sheet
->print_info
;
1029 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1030 if (gnm_xml_attr_int (attrs
, "value", &val
))
1031 pi
->center_vertically
= val
;
1035 xml_sax_print_hcenter (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1037 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1038 GnmPrintInformation
*pi
;
1041 xml_sax_must_have_sheet (state
);
1043 pi
= state
->sheet
->print_info
;
1045 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1046 if (gnm_xml_attr_int (attrs
, "value", &val
))
1047 pi
->center_horizontally
= val
;
1051 xml_sax_print_grid (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1053 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1054 GnmPrintInformation
*pi
;
1057 xml_sax_must_have_sheet (state
);
1059 pi
= state
->sheet
->print_info
;
1061 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1062 if (gnm_xml_attr_int (attrs
, "value", &val
))
1063 pi
->print_grid_lines
= val
;
1067 xml_sax_print_do_not_print (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1069 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1070 GnmPrintInformation
*pi
;
1073 xml_sax_must_have_sheet (state
);
1075 pi
= state
->sheet
->print_info
;
1077 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1078 if (gnm_xml_attr_int (attrs
, "value", &val
))
1079 pi
->do_not_print
= val
;
1083 xml_sax_print_print_range (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1085 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1086 GnmPrintInformation
*pi
;
1089 xml_sax_must_have_sheet (state
);
1091 pi
= state
->sheet
->print_info
;
1093 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1094 if (xml_sax_attr_enum (attrs
, "value", GNM_PRINT_RANGE_TYPE
,
1096 print_info_set_printrange (pi
, val
);
1102 xml_sax_monochrome (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1104 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1105 GnmPrintInformation
*pi
;
1108 xml_sax_must_have_sheet (state
);
1110 pi
= state
->sheet
->print_info
;
1112 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1113 if (gnm_xml_attr_int (attrs
, "value", &val
))
1114 pi
->print_black_and_white
= val
;
1118 xml_sax_print_titles (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1120 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1121 GnmPrintInformation
*pi
;
1124 xml_sax_must_have_sheet (state
);
1126 pi
= state
->sheet
->print_info
;
1128 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1129 if (gnm_xml_attr_int (attrs
, "value", &val
))
1130 pi
->print_titles
= val
;
1134 xml_sax_repeat_top (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1136 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1137 GnmPrintInformation
*pi
;
1139 xml_sax_must_have_sheet (state
);
1141 pi
= state
->sheet
->print_info
;
1143 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1144 if (!strcmp (CXML2C (attrs
[0]), "value")) {
1145 g_free (pi
->repeat_top
);
1146 pi
->repeat_top
= g_strdup (CXML2C (attrs
[1]));
1152 xml_sax_repeat_left (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1154 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1155 GnmPrintInformation
*pi
;
1157 xml_sax_must_have_sheet (state
);
1159 pi
= state
->sheet
->print_info
;
1161 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1162 if (!strcmp (CXML2C (attrs
[0]), "value")) {
1163 g_free (pi
->repeat_left
);
1164 pi
->repeat_left
= g_strdup (CXML2C (attrs
[1]));
1170 xml_sax_print_hf (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1172 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1173 GnmPrintInformation
*pi
;
1176 xml_sax_must_have_sheet (state
);
1178 pi
= state
->sheet
->print_info
;
1180 switch (xin
->node
->user_data
.v_int
) {
1191 g_return_if_fail (hf
!= NULL
);
1193 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1194 if ( attr_eq (attrs
[0], "Left")) {
1195 g_free (hf
->left_format
);
1196 hf
->left_format
= g_strdup (CXML2C (attrs
[1]));
1197 } else if (attr_eq (attrs
[0], "Middle")) {
1198 g_free (hf
->middle_format
);
1199 hf
->middle_format
= g_strdup (CXML2C (attrs
[1]));
1200 } else if (attr_eq (attrs
[0], "Right")) {
1201 g_free (hf
->right_format
);
1202 hf
->right_format
= g_strdup (CXML2C (attrs
[1]));
1204 unknown_attr (xin
, attrs
);
1210 xml_sax_even_if_only_styles (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1212 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1213 GnmPrintInformation
*pi
;
1216 xml_sax_must_have_sheet (state
);
1218 pi
= state
->sheet
->print_info
;
1220 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1221 if (gnm_xml_attr_int (attrs
, "value", &val
))
1222 pi
->print_even_if_only_styles
= val
;
1229 xml_sax_selection_range (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1231 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1234 xml_sax_must_have_sheet (state
);
1235 if (xml_sax_attr_range (attrs
, &r
))
1236 sv_selection_add_range (
1237 sheet_get_view (state
->sheet
, state
->wb_view
), &r
);
1241 xml_sax_selection (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1243 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1244 Sheet
*sheet
= xml_sax_must_have_sheet (state
);
1245 int col
= -1, row
= -1;
1247 sv_selection_reset (sheet_get_view (sheet
, state
->wb_view
));
1249 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1250 if (gnm_xml_attr_int (attrs
, "CursorCol", &col
)) ;
1251 else if (gnm_xml_attr_int (attrs
, "CursorRow", &row
)) ;
1253 unknown_attr (xin
, attrs
);
1255 XML_CHECK (state
->cell
.col
< 0);
1256 XML_CHECK (state
->cell
.row
< 0);
1258 /* Default in case of error. */
1259 state
->cell
.col
= 0;
1260 state
->cell
.row
= 0;
1262 XML_CHECK (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
));
1263 XML_CHECK (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
));
1265 state
->cell
.col
= col
;
1266 state
->cell
.row
= row
;
1270 xml_sax_selection_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1272 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1274 GnmCellPos
const pos
= state
->cell
;
1275 state
->cell
.col
= state
->cell
.row
= -1;
1276 sv_set_edit_pos (sheet_get_view (state
->sheet
, state
->wb_view
), &pos
);
1280 xml_sax_sheet_layout (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1282 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1285 xml_sax_must_have_sheet (state
);
1287 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1288 if (xml_sax_attr_cellpos (attrs
, "TopLeft", &tmp
, state
->sheet
))
1289 sv_set_initial_top_left (
1290 sheet_get_view (state
->sheet
, state
->wb_view
),
1293 unknown_attr (xin
, attrs
);
1297 xml_sax_sheet_freezepanes (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1299 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1300 GnmCellPos frozen_tl
, unfrozen_tl
;
1303 xml_sax_must_have_sheet (state
);
1305 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1306 if (xml_sax_attr_cellpos (attrs
, "FrozenTopLeft", &frozen_tl
, state
->sheet
))
1308 else if (xml_sax_attr_cellpos (attrs
, "UnfrozenTopLeft", &unfrozen_tl
, state
->sheet
))
1311 unknown_attr (xin
, attrs
);
1314 sv_freeze_panes (sheet_get_view (state
->sheet
, state
->wb_view
),
1315 &frozen_tl
, &unfrozen_tl
);
1319 xml_sax_cols_rows (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1321 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1323 gboolean
const is_col
= xin
->node
->user_data
.v_bool
;
1325 xml_sax_must_have_sheet (state
);
1327 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
1328 if (gnm_xml_attr_double (attrs
, "DefaultSizePts", &def_size
)) {
1330 sheet_col_set_default_size_pts (state
->sheet
, def_size
);
1332 sheet_row_set_default_size_pts (state
->sheet
, def_size
);
1337 xml_sax_colrow (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1339 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1341 ColRowInfo
*cri
= NULL
;
1344 int hidden
= 0, hard_size
= 0, is_collapsed
= 0, outline_level
= 0;
1346 gboolean
const is_col
= xin
->node
->user_data
.v_bool
;
1347 Sheet
*sheet
= xml_sax_must_have_sheet (state
);
1349 maybe_update_progress (xin
);
1351 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1352 if (gnm_xml_attr_int (attrs
, "No", &pos
)) ;
1353 else if (gnm_xml_attr_double (attrs
, "Unit", &size
)) ;
1354 else if (gnm_xml_attr_int (attrs
, "Count", &count
)) ;
1355 else if (gnm_xml_attr_int (attrs
, "HardSize", &hard_size
)) ;
1356 else if (gnm_xml_attr_int (attrs
, "Hidden", &hidden
)) ;
1357 else if (gnm_xml_attr_int (attrs
, "Collapsed", &is_collapsed
)) ;
1358 else if (gnm_xml_attr_int (attrs
, "OutlineLevel", &outline_level
)) ;
1359 else if (gnm_xml_attr_int (attrs
, "MarginA", &val
))
1360 ; /* deprecated in 1.7.1 */
1361 else if (gnm_xml_attr_int (attrs
, "MarginB", &val
))
1362 ; /* deprecated in 1.7.1 */
1364 unknown_attr (xin
, attrs
);
1367 XML_CHECK (size
> -1);
1368 XML_CHECK (pos
>= 0 && pos
< colrow_max (is_col
, sheet
));
1369 XML_CHECK (count
>= 1);
1370 XML_CHECK (count
<= colrow_max (is_col
, sheet
) - pos
);
1373 ? sheet_col_fetch (state
->sheet
, pos
)
1374 : sheet_row_fetch (state
->sheet
, pos
);
1375 cri
->hard_size
= hard_size
;
1376 cri
->visible
= !hidden
;
1377 cri
->is_collapsed
= is_collapsed
;
1378 cri
->outline_level
= outline_level
;
1381 sheet_col_set_size_pts (state
->sheet
, pos
, size
, cri
->hard_size
);
1382 if (state
->sheet
->cols
.max_outline_level
< cri
->outline_level
)
1383 state
->sheet
->cols
.max_outline_level
= cri
->outline_level
;
1384 /* resize flags are already set only need to copy the sizes */
1386 colrow_copy (sheet_col_fetch (state
->sheet
, ++pos
), cri
);
1388 sheet_row_set_size_pts (state
->sheet
, pos
, size
, cri
->hard_size
);
1389 if (state
->sheet
->rows
.max_outline_level
< cri
->outline_level
)
1390 state
->sheet
->rows
.max_outline_level
= cri
->outline_level
;
1391 /* resize flags are already set only need to copy the sizes */
1393 colrow_copy (sheet_row_fetch (state
->sheet
, ++pos
), cri
);
1398 xml_sax_style_region_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1400 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1402 g_return_if_fail (state
->style_range_init
== FALSE
);
1403 g_return_if_fail (state
->style
== NULL
);
1405 if (attrs
== NULL
) {
1406 g_warning ("Invalid tag: gnm:StyleRegion start tag without attributes");
1410 state
->style
= (state
->version
>= GNM_XML_V6
||
1411 state
->version
<= GNM_XML_V2
)
1412 ? gnm_style_new_default ()
1415 state
->style_range_init
=
1416 xml_sax_attr_range (attrs
, &state
->style_range
);
1420 xml_sax_style_region_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1422 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1424 if (!state
->style_range_init
) {
1425 xml_sax_barf (G_STRFUNC
, "style region must have range");
1426 range_init (&state
->style_range
, 0, 0, 0, 0);
1427 state
->style_range_init
= TRUE
;
1430 xml_sax_must_have_style (state
);
1431 xml_sax_must_have_sheet (state
);
1433 if (state
->clipboard
) {
1434 GnmCellRegion
*cr
= state
->clipboard
;
1435 GnmStyleRegion
*sr
= g_new (GnmStyleRegion
, 1);
1437 sr
->range
= state
->style_range
;
1438 sr
->style
= state
->style
;
1440 cr
->styles
= g_slist_prepend (cr
->styles
, sr
);
1441 } else if (state
->version
>= GNM_XML_V6
|| state
->version
<= GNM_XML_V2
)
1442 sheet_style_set_range (state
->sheet
, &state
->style_range
,
1445 sheet_style_apply_range (state
->sheet
, &state
->style_range
,
1448 state
->style_range_init
= FALSE
;
1449 state
->style
= NULL
;
1451 maybe_update_progress (xin
);
1455 xml_sax_style_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1457 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1462 xml_sax_must_have_style (state
);
1464 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1465 if (xml_sax_attr_enum (attrs
, "HAlign", GNM_ALIGN_H_TYPE
, &val
))
1466 gnm_style_set_align_h (state
->style
, val
);
1467 else if (xml_sax_attr_enum (attrs
, "VAlign", GNM_ALIGN_V_TYPE
, &val
))
1468 gnm_style_set_align_v (state
->style
, val
);
1470 /* Pre version V6 */
1471 else if (gnm_xml_attr_int (attrs
, "Fit", &val
))
1472 gnm_style_set_wrap_text (state
->style
, val
);
1474 else if (gnm_xml_attr_int (attrs
, "WrapText", &val
))
1475 gnm_style_set_wrap_text (state
->style
, val
);
1476 else if (gnm_xml_attr_bool (attrs
, "ShrinkToFit", &val
))
1477 gnm_style_set_shrink_to_fit (state
->style
, val
);
1478 else if (gnm_xml_attr_int (attrs
, "Rotation", &val
)) {
1479 /* Work around a bug pre 1.5.1 that would allow
1480 * negative rotations. -1 == vertical, map everything
1481 * else back onto 0..359 */
1484 gnm_style_set_rotation (state
->style
, val
);
1485 } else if (gnm_xml_attr_int (attrs
, "Shade", &val
))
1486 gnm_style_set_pattern (state
->style
, val
);
1487 else if (gnm_xml_attr_int (attrs
, "Indent", &val
))
1488 gnm_style_set_indent (state
->style
, val
);
1489 else if (xml_sax_attr_color (attrs
, "Fore", &colour
))
1490 gnm_style_set_font_color (state
->style
, colour
);
1491 else if (xml_sax_attr_color (attrs
, "Back", &colour
))
1492 gnm_style_set_back_color (state
->style
, colour
);
1493 else if (xml_sax_attr_color (attrs
, "PatternColor", &colour
))
1494 gnm_style_set_pattern_color (state
->style
, colour
);
1495 else if (attr_eq (attrs
[0], "Format")) {
1496 GOFormat
*fmt
= make_format (CXML2C (attrs
[1]));
1498 gnm_style_set_format (state
->style
, fmt
);
1499 go_format_unref (fmt
);
1502 else if (gnm_xml_attr_int (attrs
, "Hidden", &val
))
1503 gnm_style_set_contents_hidden (state
->style
, val
);
1504 else if (gnm_xml_attr_int (attrs
, "Locked", &val
))
1505 gnm_style_set_contents_locked (state
->style
, val
);
1506 else if (gnm_xml_attr_int (attrs
, "Orient", &val
))
1507 ; /* ignore old useless attribute */
1509 unknown_attr (xin
, attrs
);
1514 xml_sax_style_font (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1516 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1518 double size_pts
= 10.;
1521 xml_sax_must_have_style (state
);
1523 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1524 if (gnm_xml_attr_double (attrs
, "Unit", &size_pts
)) {
1525 if (!(size_pts
>= 1.0))
1526 xml_sax_barf (G_STRFUNC
, "size_pts >= 1");
1528 gnm_style_set_font_size (state
->style
, size_pts
);
1529 } else if (gnm_xml_attr_int (attrs
, "Bold", &val
))
1530 gnm_style_set_font_bold (state
->style
, val
);
1531 else if (gnm_xml_attr_int (attrs
, "Italic", &val
))
1532 gnm_style_set_font_italic (state
->style
, val
);
1533 else if (gnm_xml_attr_int (attrs
, "Underline", &val
))
1534 gnm_style_set_font_uline (state
->style
, (GnmUnderline
)val
);
1535 else if (gnm_xml_attr_int (attrs
, "StrikeThrough", &val
))
1536 gnm_style_set_font_strike (state
->style
, val
);
1537 else if (gnm_xml_attr_int (attrs
, "Script", &val
)) {
1539 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_STANDARD
);
1541 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_SUB
);
1543 gnm_style_set_font_script (state
->style
, GO_FONT_SCRIPT_SUPER
);
1545 unknown_attr (xin
, attrs
);
1550 font_component (char const *fontname
, int idx
)
1553 char const *p
= fontname
;
1555 for (; *p
&& i
< idx
; p
++) {
1566 * style_font_read_from_x11:
1567 * @mstyle: the style to setup to this font.
1568 * @fontname: an X11-like font name.
1570 * Tries to guess the fontname, the weight and italization parameters
1573 * Returns: A valid style font.
1576 style_font_read_from_x11 (GnmStyle
*mstyle
, char const *fontname
)
1580 /* FIXME: we should do something about the typeface instead
1581 * of hardcoding it to helvetica.
1583 c
= font_component (fontname
, 2);
1584 if (strncmp (c
, "bold", 4) == 0)
1585 gnm_style_set_font_bold (mstyle
, TRUE
);
1587 c
= font_component (fontname
, 3);
1588 if (strncmp (c
, "o", 1) == 0)
1589 gnm_style_set_font_italic (mstyle
, TRUE
);
1591 if (strncmp (c
, "i", 1) == 0)
1592 gnm_style_set_font_italic (mstyle
, TRUE
);
1596 xml_sax_style_font_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1598 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1600 xml_sax_must_have_style (state
);
1602 if (xin
->content
->len
> 0) {
1603 char const * content
= xin
->content
->str
;
1604 if (*content
== '-')
1605 style_font_read_from_x11 (state
->style
, content
);
1607 gnm_style_set_font_name (state
->style
, content
);
1612 xml_sax_validation (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1614 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1619 g_return_if_fail (state
->validation
.title
== NULL
);
1620 g_return_if_fail (state
->validation
.msg
== NULL
);
1621 g_return_if_fail (state
->validation
.texpr
[0] == NULL
);
1622 g_return_if_fail (state
->validation
.texpr
[1] == NULL
);
1624 state
->validation
.style
= GNM_VALIDATION_STYLE_NONE
;
1625 state
->validation
.type
= GNM_VALIDATION_TYPE_ANY
;
1626 state
->validation
.op
= GNM_VALIDATION_OP_NONE
;
1627 state
->validation
.allow_blank
= TRUE
;
1628 state
->validation
.use_dropdown
= FALSE
;
1630 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1631 if (xml_sax_attr_enum (attrs
, "Style",
1632 GNM_VALIDATION_STYLE_TYPE
,
1634 state
->validation
.style
= dummy
;
1635 } else if (xml_sax_attr_enum (attrs
, "Type",
1636 GNM_VALIDATION_TYPE_TYPE
,
1638 state
->validation
.type
= dummy
;
1639 } else if (xml_sax_attr_enum (attrs
, "Operator",
1640 GNM_VALIDATION_OP_TYPE
,
1642 state
->validation
.op
= dummy
;
1643 } else if (attr_eq (attrs
[0], "Title")) {
1644 state
->validation
.title
= g_strdup (CXML2C (attrs
[1]));
1645 } else if (attr_eq (attrs
[0], "Message")) {
1646 state
->validation
.msg
= g_strdup (CXML2C (attrs
[1]));
1647 } else if (gnm_xml_attr_bool (attrs
, "AllowBlank", &b_dummy
)) {
1648 state
->validation
.allow_blank
= b_dummy
;
1649 } else if (gnm_xml_attr_bool (attrs
, "UseDropdown", &b_dummy
)) {
1650 state
->validation
.use_dropdown
= b_dummy
;
1652 unknown_attr (xin
, attrs
);
1657 xml_sax_validation_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1659 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1661 xml_sax_must_have_style (state
);
1663 gnm_style_set_validation (state
->style
,
1664 gnm_validation_new (state
->validation
.style
,
1665 state
->validation
.type
,
1666 state
->validation
.op
,
1668 state
->validation
.title
,
1669 state
->validation
.msg
,
1670 state
->validation
.texpr
[0],
1671 state
->validation
.texpr
[1],
1672 state
->validation
.allow_blank
,
1673 state
->validation
.use_dropdown
));
1675 g_free (state
->validation
.title
);
1676 state
->validation
.title
= NULL
;
1677 g_free (state
->validation
.msg
);
1678 state
->validation
.msg
= NULL
;
1679 state
->validation
.texpr
[0] = state
->validation
.texpr
[1] = NULL
;
1683 xml_sax_validation_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1685 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1687 int const i
= xin
->node
->user_data
.v_int
;
1688 GnmExprTop
const *texpr
;
1691 g_return_if_fail (state
->validation
.texpr
[i
] == NULL
);
1693 texpr
= gnm_expr_parse_str (xin
->content
->str
,
1694 parse_pos_init_sheet (&pos
, state
->sheet
),
1695 GNM_EXPR_PARSE_DEFAULT
,
1699 g_return_if_fail (texpr
!= NULL
);
1701 state
->validation
.texpr
[i
] = texpr
;
1705 xml_sax_condition (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1707 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1708 GnmStyleCondOp op
= GNM_STYLE_COND_CUSTOM
;
1710 g_return_if_fail (state
->cond
== NULL
);
1711 g_return_if_fail (state
->cond_save_style
== NULL
);
1713 xml_sax_must_have_style (state
);
1715 state
->cond_save_style
= state
->style
;
1716 state
->style
= gnm_style_new ();
1718 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1721 if (gnm_xml_attr_int (attrs
, "Operator", &dummy
))
1724 unknown_attr (xin
, attrs
);
1727 state
->cond
= gnm_style_cond_new (op
, state
->sheet
);
1731 xml_sax_condition_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1733 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1734 GnmStyleConditions
*sc
;
1736 xml_sax_must_have_style (state
);
1737 g_return_if_fail (state
->cond_save_style
!= NULL
);
1738 g_return_if_fail (state
->cond
!= NULL
);
1740 gnm_style_cond_set_overlay (state
->cond
, state
->style
);
1741 gnm_style_unref (state
->style
);
1742 state
->style
= state
->cond_save_style
;
1743 state
->cond_save_style
= NULL
;
1745 if (!gnm_style_is_element_set (state
->style
, MSTYLE_CONDITIONS
) ||
1746 NULL
== (sc
= gnm_style_get_conditions (state
->style
)))
1747 gnm_style_set_conditions (state
->style
,
1748 (sc
= gnm_style_conditions_new (state
->sheet
)));
1749 gnm_style_conditions_insert (sc
, state
->cond
, -1);
1751 gnm_style_cond_free (state
->cond
);
1756 * We have been saving expressions relative to A1. This means that when we
1757 * read, we see a relative reference to a cell above as R[65535]C. This
1758 * function patches that to R[-1]C.
1760 * We ought to fix the format, but then old Gnumerics couldn't read new
1761 * files. In fact, if we just added a "Position" attribute then we would
1762 * get silent corruption.
1764 static GnmExpr
const *
1765 cond_patchup (GnmExpr
const *expr
, GnmExprWalk
*data
)
1767 XMLSaxParseState
*state
= data
->user
;
1768 GnmCellPos
const *pos
= &state
->style_range
.start
;
1769 GnmCellRef
const *oref
= gnm_expr_get_cellref (expr
);
1770 GnmValue
const *ocst
= gnm_expr_get_constant (expr
);
1774 GnmCellRef tref
= *oref
;
1775 gnm_cellpos_init_cellref (&tpos
, oref
, pos
, state
->sheet
);
1776 if (tref
.col_relative
)
1777 tref
.col
= tpos
.col
- pos
->col
;
1778 if (tref
.row_relative
)
1779 tref
.row
= tpos
.row
- pos
->row
;
1780 if (gnm_cellref_equal (&tref
, oref
))
1782 return gnm_expr_new_cellref (&tref
);
1785 if (ocst
&& VALUE_IS_CELLRANGE (ocst
)) {
1786 GnmRangeRef
const *oref
= value_get_rangeref (ocst
);
1787 GnmRangeRef tref
= *oref
;
1789 Sheet
*start_sheet
, *end_sheet
;
1792 eval_pos_init_pos (&ep
, state
->sheet
, pos
);
1793 gnm_rangeref_normalize (oref
, &ep
, &start_sheet
, &end_sheet
,
1795 if (tref
.a
.col_relative
)
1796 tref
.a
.col
= trange
.start
.col
- pos
->col
;
1797 if (tref
.a
.row_relative
)
1798 tref
.a
.row
= trange
.start
.row
- pos
->row
;
1799 if (tref
.b
.col_relative
)
1800 tref
.b
.col
= trange
.end
.col
- pos
->col
;
1801 if (tref
.b
.row_relative
)
1802 tref
.b
.row
= trange
.end
.row
- pos
->row
;
1803 if (gnm_rangeref_equal (&tref
, oref
))
1805 return gnm_expr_new_constant (value_new_cellrange_unsafe (&tref
.a
, &tref
.b
));
1812 xml_sax_condition_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
1814 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1816 int const i
= xin
->node
->user_data
.v_int
;
1817 GnmExprTop
const *texpr
;
1819 GnmExpr
const *patched_expr
;
1821 g_return_if_fail (gnm_style_cond_get_expr (state
->cond
, i
) == NULL
);
1823 parse_pos_init_sheet (&pos
, state
->sheet
);
1824 texpr
= gnm_expr_parse_str (xin
->content
->str
,
1826 GNM_EXPR_PARSE_DEFAULT
,
1829 g_return_if_fail (texpr
!= NULL
);
1831 patched_expr
= gnm_expr_walk (texpr
->expr
, cond_patchup
, state
);
1833 gnm_expr_top_unref (texpr
);
1834 texpr
= gnm_expr_top_new (patched_expr
);
1837 gnm_style_cond_set_expr (state
->cond
, texpr
, i
);
1838 gnm_expr_top_unref (texpr
);
1842 xml_sax_hlink (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1844 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1846 char *target
= NULL
;
1849 xml_sax_must_have_style (state
);
1851 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1852 if (attr_eq (attrs
[0], "type"))
1853 type
= g_strdup (CXML2C (attrs
[1]));
1854 else if (attr_eq (attrs
[0], "target"))
1855 target
= g_strdup (CXML2C (attrs
[1]));
1856 else if (attr_eq (attrs
[0], "tip"))
1857 tip
= g_strdup (CXML2C (attrs
[1]));
1859 unknown_attr (xin
, attrs
);
1862 if (NULL
!= type
&& NULL
!= target
) {
1863 GType typ
= g_type_from_name (type
);
1864 GnmHLink
*lnk
= gnm_hlink_new (typ
, state
->sheet
);
1865 gnm_hlink_set_target (lnk
, target
);
1866 gnm_hlink_set_tip (lnk
, tip
);
1867 gnm_style_set_hlink (state
->style
, lnk
);
1876 xml_sax_input_msg (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1878 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1882 xml_sax_must_have_style (state
);
1884 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1885 if (attr_eq (attrs
[0], "Title"))
1886 title
= g_strdup (CXML2C (attrs
[1]));
1887 else if (attr_eq (attrs
[0], "Message"))
1888 msg
= g_strdup (CXML2C (attrs
[1]));
1890 unknown_attr (xin
, attrs
);
1893 if (NULL
!= title
|| NULL
!= msg
)
1894 gnm_style_set_input_msg (state
->style
,
1895 gnm_input_msg_new (msg
, title
));
1901 xml_sax_style_border (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1903 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1906 GnmColor
*colour
= NULL
;
1908 xml_sax_must_have_style (state
);
1910 /* Colour is optional */
1911 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1912 if (xml_sax_attr_color (attrs
, "Color", &colour
)) ;
1913 else if (gnm_xml_attr_int (attrs
, "Style", &pattern
)) ;
1915 unknown_attr (xin
, attrs
);
1918 if (pattern
>= GNM_STYLE_BORDER_NONE
) {
1919 GnmStyleElement
const type
= xin
->node
->user_data
.v_int
;
1920 GnmStyleBorderLocation
const loc
=
1921 GNM_STYLE_BORDER_TOP
+ (int)(type
- MSTYLE_BORDER_TOP
);
1925 * Make sure we have a colour to prevent trouble further
1929 colour
= gnm_color_new_go (GO_COLOR_BLACK
);
1931 border
= gnm_style_border_fetch
1932 ((GnmStyleBorderType
)pattern
, colour
,
1933 gnm_style_border_get_orientation (loc
));
1934 gnm_style_set_border (state
->style
, type
, border
);
1939 xml_sax_cell (GsfXMLIn
*xin
, xmlChar
const **attrs
)
1941 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
1942 Sheet
*sheet
= state
->sheet
;
1944 int row
= -1, col
= -1;
1945 int rows
= -1, cols
= -1;
1946 int value_type
= -1;
1947 GOFormat
*value_fmt
= NULL
;
1950 g_return_if_fail (state
->cell
.row
== -1);
1951 g_return_if_fail (state
->cell
.col
== -1);
1952 g_return_if_fail (state
->array_rows
== -1);
1953 g_return_if_fail (state
->array_cols
== -1);
1954 g_return_if_fail (state
->expr_id
== -1);
1955 g_return_if_fail (state
->value_type
== -1);
1957 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
1958 if (gnm_xml_attr_int (attrs
, "Col", &col
)) ;
1959 else if (gnm_xml_attr_int (attrs
, "Row", &row
)) ;
1960 else if (gnm_xml_attr_int (attrs
, "Cols", &cols
)) ;
1961 else if (gnm_xml_attr_int (attrs
, "Rows", &rows
)) ;
1962 else if (gnm_xml_attr_int (attrs
, "ExprID", &expr_id
)) ;
1963 else if (gnm_xml_attr_int (attrs
, "ValueType", &value_type
)) ;
1964 else if (attr_eq (attrs
[0], "ValueFormat"))
1965 value_fmt
= make_format (CXML2C (attrs
[1]));
1967 unknown_attr (xin
, attrs
);
1970 XML_CHECK2 (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
),
1971 go_format_unref (value_fmt
));
1972 XML_CHECK2 (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
),
1973 go_format_unref (value_fmt
));
1975 if (cols
> 0 || rows
> 0) {
1976 /* Both must be valid */
1977 XML_CHECK2 (cols
> 0 && rows
> 0,
1978 go_format_unref (value_fmt
));
1980 state
->array_cols
= cols
;
1981 state
->array_rows
= rows
;
1984 state
->cell
.row
= row
;
1985 state
->cell
.col
= col
;
1986 state
->expr_id
= expr_id
;
1987 state
->value_type
= value_type
;
1988 state
->value_fmt
= value_fmt
;
1992 * xml_cell_set_array_expr : Utility routine to parse an expression
1993 * and store it as an array.
1995 * @cell: The upper left hand corner of the array.
1996 * @text: The text to parse.
1997 * @rows: The number of rows.
1998 * @cols: The number of columns.
2001 xml_cell_set_array_expr (XMLSaxParseState
*state
,
2002 GnmCell
*cell
, GnmCellCopy
*cc
, char const *text
,
2003 int const cols
, int const rows
)
2006 GnmExprTop
const *texpr
=
2007 gnm_expr_parse_str (text
,
2008 parse_pos_init_cell (&pp
, cell
),
2009 GNM_EXPR_PARSE_DEFAULT
,
2014 g_return_if_fail (texpr
!= NULL
);
2021 r
.start
= r
.end
= cell
->pos
;
2022 r
.end
.col
+= (cols
- 1);
2023 r
.end
.row
+= (rows
- 1);
2025 if (!gnm_cell_set_array (cell
->base
.sheet
, &r
, texpr
)) {
2026 xml_sax_barf (G_STRFUNC
, "target area empty");
2029 gnm_expr_top_unref (texpr
);
2033 * xml_not_used_old_array_spec : See if the string corresponds to
2034 * a pre-0.53 style array expression.
2035 * If it is the upper left corner - assign it.
2036 * If it is a member of an array - ignore it; the corner will assign it.
2037 * If it is not a member of an array return TRUE.
2040 xml_not_used_old_array_spec (XMLSaxParseState
*state
,
2041 GnmCell
*cell
, GnmCellCopy
*cc
,
2042 char const *content
)
2044 long rows
, cols
, row
, col
;
2045 char *end
, *expr_end
, *ptr
;
2047 /* This is the syntax we are trying to parse: "{%s}(%d,%d)[%d][%d]" */
2049 if (content
[0] != '=' || content
[1] != '{')
2052 expr_end
= strrchr (content
, '}');
2053 if (expr_end
== NULL
|| expr_end
[1] != '(')
2056 rows
= strtol (ptr
= expr_end
+ 2, &end
, 10);
2057 if (end
== ptr
|| *end
!= ',')
2059 cols
= strtol (ptr
= end
+ 1, &end
, 10);
2060 if (end
== ptr
|| end
[0] != ')' || end
[1] != '[')
2062 row
= strtol (ptr
= end
+ 2, &end
, 10);
2063 if (end
== ptr
|| end
[0] != ']' || end
[1] != '[')
2065 col
= strtol (ptr
= end
+ 2, &end
, 10);
2066 if (end
== ptr
|| end
[0] != ']' || end
[1] != '\0')
2069 if (row
== 0 && col
== 0) {
2071 xml_cell_set_array_expr (state
, cell
, cc
,
2072 content
+ 2, rows
, cols
);
2079 xml_sax_cell_content (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2081 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2082 Sheet
*sheet
= state
->sheet
;
2084 gboolean is_new_cell
= FALSE
, is_post_52_array
= FALSE
;
2087 GnmCell
*cell
= NULL
; /* Regular case */
2088 GnmCellCopy
*cc
= NULL
; /* Clipboard case */
2089 GnmCellRegion
*cr
= state
->clipboard
;
2091 int const col
= state
->cell
.col
;
2092 int const row
= state
->cell
.row
;
2093 int const array_cols
= state
->array_cols
;
2094 int const array_rows
= state
->array_rows
;
2095 int const expr_id
= state
->expr_id
;
2096 int const value_type
= state
->value_type
;
2097 gboolean
const seen_contents
= state
->seen_cell_contents
;
2098 GOFormat
*value_fmt
= state
->value_fmt
;
2100 /* Clean out the state before any error checking */
2101 state
->cell
.row
= state
->cell
.col
= -1;
2102 state
->array_rows
= state
->array_cols
= -1;
2103 state
->expr_id
= -1;
2104 state
->value_type
= -1;
2105 state
->value_fmt
= NULL
;
2106 state
->seen_cell_contents
= strcmp (xin
->node
->id
, "CELL_CONTENT") == 0;
2111 XML_CHECK (col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
));
2112 XML_CHECK (row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
));
2114 maybe_update_progress (xin
);
2117 cc
= gnm_cell_copy_new (cr
,
2119 row
- cr
->base
.row
);
2120 parse_pos_init (&pos
, NULL
, sheet
, col
, row
);
2122 cell
= sheet_cell_get (sheet
, col
, row
);
2123 is_new_cell
= (cell
== NULL
);
2125 cell
= sheet_cell_create (sheet
, col
, row
);
2129 parse_pos_init_cell (&pos
, cell
);
2132 is_post_52_array
= (array_cols
> 0) && (array_rows
> 0);
2134 if (xin
->content
->len
> 0) {
2135 char const * content
= xin
->content
->str
;
2137 if (is_post_52_array
) {
2138 g_return_if_fail (content
[0] == '=');
2140 xml_cell_set_array_expr (state
, cell
, cc
, content
+1,
2141 array_cols
, array_rows
);
2142 } else if (state
->version
>= GNM_XML_V3
||
2143 xml_not_used_old_array_spec (state
, cell
, cc
, content
)) {
2144 if (value_type
> 0) {
2145 GnmValue
*v
= value_new_from_string (value_type
, content
, value_fmt
, FALSE
);
2147 char *msg
= g_strdup_printf
2148 ("Parsing \"%s\" as type 0x%x",
2149 content
, value_type
);
2150 xml_sax_barf (G_STRFUNC
, msg
);
2152 v
= value_new_string (content
);
2155 gnm_cell_set_value (cell
, v
);
2159 const char *expr_start
= gnm_expr_char_start_p (content
);
2160 if (expr_start
&& *expr_start
) {
2162 GnmExprTop
const *texpr
;
2164 parse_error_init (&perr
);
2165 texpr
= gnm_expr_parse_str (expr_start
,
2167 GNM_EXPR_PARSE_DEFAULT
,
2171 g_warning ("Unparsable expression for %s: %s (%s)\n",
2172 cell
? cell_name (cell
) : "-",
2175 texpr
= gnm_expr_top_new_constant (value_new_string (expr_start
));
2178 gnm_cell_set_expr (cell
, texpr
);
2179 gnm_expr_top_unref (texpr
);
2182 parse_error_free (&perr
);
2184 gnm_cell_set_text (cell
, content
);
2186 cc
->val
= value_new_string (content
);
2191 gpointer id
= GINT_TO_POINTER (expr_id
);
2192 GnmExprTop
const *texpr
=
2193 g_hash_table_lookup (state
->expr_map
, id
);
2194 if (texpr
== NULL
) {
2197 else if (gnm_cell_has_expr (cell
)) {
2198 texpr
= cell
->base
.texpr
;
2200 g_warning ("XML-IO : Shared expression with no expression ??");
2202 gnm_expr_top_ref (texpr
);
2203 g_hash_table_insert (state
->expr_map
,
2207 } else if (!is_post_52_array
)
2208 g_warning ("XML-IO : Duplicate shared expression");
2210 } else if (expr_id
> 0) {
2211 GnmExprTop
const *texpr
= g_hash_table_lookup (state
->expr_map
,
2212 GINT_TO_POINTER (expr_id
));
2215 char *msg
= g_strdup_printf
2216 ("Looking up shared expression id %d",
2218 char *s
= g_strdup_printf ("<shared expression %d>", expr_id
);
2219 xml_sax_barf (G_STRFUNC
, msg
);
2222 texpr
= gnm_expr_top_new_constant (value_new_string_nocopy (s
));
2223 g_hash_table_insert (state
->expr_map
,
2224 GINT_TO_POINTER (expr_id
),
2229 gnm_cell_set_expr (cell
, texpr
);
2232 gnm_expr_top_ref (texpr
);
2234 } else if (is_new_cell
) {
2238 * Only set to empty if this is a new cell.
2239 * If it was created by a previous array
2240 * we do not want to erase it.
2242 v
= value_new_from_string (value_type
, "", NULL
, FALSE
);
2244 xml_sax_barf (G_STRFUNC
, "v != NULL");
2245 v
= value_new_empty ();
2248 gnm_cell_set_value (cell
, v
);
2250 cc
->val
= value_new_empty ();
2253 go_format_unref (value_fmt
);
2257 xml_sax_merge (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2259 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2260 GnmCellRegion
*cr
= state
->clipboard
;
2261 Sheet
*sheet
= state
->sheet
;
2264 g_return_if_fail (xin
->content
->len
> 0);
2266 if (range_parse (&r
, xin
->content
->str
, gnm_sheet_get_size (sheet
))) {
2268 cr
->merged
= g_slist_prepend (cr
->merged
,
2269 gnm_range_dup (&r
));
2271 gnm_sheet_merge_add (sheet
, &r
, FALSE
,
2272 GO_CMD_CONTEXT (state
->context
));
2278 xml_sax_filter_operator (XMLSaxParseState
*state
,
2279 GnmFilterOp
*op
, xmlChar
const *str
)
2281 static char const *filter_cond_name
[] = { "eq", "gt", "lt", "gte", "lte", "ne" };
2284 for (i
= G_N_ELEMENTS (filter_cond_name
); i
-- ; )
2285 if (0 == g_ascii_strcasecmp (CXML2C (str
), filter_cond_name
[i
])) {
2290 go_io_warning (state
->context
, _("Unknown filter operator \"%s\""), str
);
2294 xml_sax_filter_condition (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2296 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2297 char const *type
= NULL
;
2298 char const *val0
= NULL
;
2299 char const *val1
= NULL
;
2300 GnmValueType vtype0
= VALUE_EMPTY
, vtype1
= VALUE_EMPTY
;
2301 GnmFilterOp op0
= GNM_FILTER_UNUSED
, op1
= GNM_FILTER_UNUSED
;
2302 GnmFilterCondition
*cond
= NULL
;
2303 gboolean top
= TRUE
, items
= TRUE
, is_and
= FALSE
;
2304 int i
, tmp
, cond_num
= 0;
2305 double bucket_count
= 10.;
2307 if (NULL
== state
->filter
) return;
2309 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2) {
2310 if (attr_eq (attrs
[i
], "Type")) type
= CXML2C (attrs
[i
+ 1]);
2311 else if (gnm_xml_attr_int (attrs
+i
, "Index", &cond_num
)) ;
2312 else if (gnm_xml_attr_bool (attrs
, "Top", &top
)) ;
2313 else if (gnm_xml_attr_bool (attrs
, "Items", &items
)) ;
2314 else if (gnm_xml_attr_double (attrs
, "Count", &bucket_count
)) ;
2315 else if (gnm_xml_attr_bool (attrs
, "IsAnd", &is_and
)) ;
2316 else if (attr_eq (attrs
[i
], "Op0")) xml_sax_filter_operator (state
, &op0
, attrs
[i
+ 1]);
2317 else if (attr_eq (attrs
[i
], "Op1")) xml_sax_filter_operator (state
, &op1
, attrs
[i
+ 1]);
2319 * WARNING WARNING WARING
2320 * Value and ValueType are _reversed_ !!!
2321 * An error in the DOM exporter was propogated to the SAX
2322 * exporter and fixing this reversal would break all old files.
2324 else if (attr_eq (attrs
[i
], "ValueType0")) val0
= CXML2C (attrs
[i
+ 1]);
2325 else if (attr_eq (attrs
[i
], "ValueType1")) val1
= CXML2C (attrs
[i
+ 1]);
2326 else if (gnm_xml_attr_int (attrs
+i
, "Value0", &tmp
)) vtype0
= tmp
;
2327 else if (gnm_xml_attr_int (attrs
+i
, "Value1", &tmp
)) vtype1
= tmp
;
2331 go_io_warning (state
->context
, _("Missing filter type"));
2332 } else if (0 == g_ascii_strcasecmp (type
, "expr")) {
2333 GnmValue
*v0
= NULL
, *v1
= NULL
;
2334 if (val0
&& vtype0
!= VALUE_EMPTY
&& op0
!= GNM_FILTER_UNUSED
)
2335 v0
= value_new_from_string (vtype0
, val0
, NULL
, FALSE
);
2336 if (val1
&& vtype1
!= VALUE_EMPTY
&& op1
!= GNM_FILTER_UNUSED
)
2337 v1
= value_new_from_string (vtype1
, val1
, NULL
, FALSE
);
2339 cond
= gnm_filter_condition_new_double (
2340 op0
, v0
, is_and
, op1
, v1
);
2342 cond
= gnm_filter_condition_new_single (op0
, v0
);
2344 go_io_warning (state
->context
, _("Malformed sheet filter condition"));
2348 } else if (0 == g_ascii_strcasecmp (type
, "blanks")) {
2349 cond
= gnm_filter_condition_new_single (
2350 GNM_FILTER_OP_BLANKS
, NULL
);
2351 } else if (0 == g_ascii_strcasecmp (type
, "noblanks")) {
2352 cond
= gnm_filter_condition_new_single (
2353 GNM_FILTER_OP_NON_BLANKS
, NULL
);
2354 } else if (0 == g_ascii_strcasecmp (type
, "bucket")) {
2355 cond
= gnm_filter_condition_new_bucket
2356 (top
, items
, TRUE
, bucket_count
);
2358 go_io_warning (state
->context
, _("Unknown filter type \"%s\""), type
);
2361 gnm_filter_set_condition (state
->filter
, cond_num
, cond
, FALSE
);
2365 xml_sax_filter_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2367 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2371 xml_sax_must_have_sheet (state
);
2372 g_return_if_fail (state
->filter
== NULL
);
2374 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2)
2375 if (attr_eq (attrs
[i
], "Area") &&
2376 range_parse (&r
, CXML2C (attrs
[i
+ 1]), gnm_sheet_get_size (state
->sheet
)))
2377 state
->filter
= gnm_filter_new (state
->sheet
, &r
);
2378 if (NULL
== state
->filter
)
2379 go_io_warning (state
->context
, _("Invalid filter, missing Area"));
2383 xml_sax_filter_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2385 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2386 state
->filter
= NULL
;
2390 xml_sax_read_obj (GsfXMLIn
*xin
, gboolean needs_cleanup
,
2391 char const *type_name
, xmlChar
const **attrs
)
2393 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2396 SheetObjectClass
*klass
;
2398 GODrawingAnchorDir anchor_dir
;
2399 GnmSOAnchorMode anchor_mode
;
2400 SheetObjectAnchor anchor
;
2401 double f_tmp
[4], *anchor_offset
= NULL
;
2403 g_return_if_fail (state
->so
== NULL
);
2406 if (!strcmp (type_name
, "Rectangle"))
2407 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2408 else if (!strcmp (type_name
, "Ellipse"))
2409 so
= g_object_new (GNM_SO_FILLED_TYPE
, "is-oval", TRUE
, NULL
);
2410 else if (!strcmp (type_name
, "Line"))
2411 so
= g_object_new (GNM_SO_LINE_TYPE
, NULL
);
2412 else if (!strcmp (type_name
, "Arrow")) {
2414 go_arrow_init_kite (&arrow
, 8., 10., 3.);
2415 so
= g_object_new (GNM_SO_LINE_TYPE
,
2416 "end-arrow", &arrow
,
2420 /* Class renamed between 1.0.x and 1.2.x */
2421 else if (!strcmp (type_name
, "GnmGraph"))
2422 so
= sheet_object_graph_new (NULL
);
2424 /* Class renamed in 1.2.2 */
2425 else if (!strcmp (type_name
, "CellComment"))
2426 so
= g_object_new (cell_comment_get_type (), NULL
);
2428 /* Class renamed in 1.3.91 */
2429 else if (!strcmp (type_name
, "SheetObjectGraphic"))
2430 so
= g_object_new (GNM_SO_LINE_TYPE
, NULL
);
2431 else if (!strcmp (type_name
, "SheetObjectFilled"))
2432 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2433 else if (!strcmp (type_name
, "SheetObjectText"))
2434 so
= g_object_new (GNM_SO_FILLED_TYPE
, NULL
);
2435 else if (!strcmp (type_name
, "SheetObjectComponent"))
2436 so
= sheet_object_component_new (NULL
);
2437 else if (!strcmp (type_name
, "SheetObjectPath"))
2438 so
= g_object_new (GNM_SO_PATH_TYPE
, NULL
);
2441 GType type
= g_type_from_name (type_name
);
2443 if (type
== 0 || !g_type_is_a (type
, GNM_SO_TYPE
)) {
2444 char *str
= g_strdup_printf (_("Unsupported object type '%s'"),
2446 go_io_warning_unsupported_feature (state
->context
, str
);
2451 so
= g_object_new (type
, NULL
);
2456 g_return_if_fail (so
!= NULL
);
2457 klass
= GNM_SO_CLASS (G_OBJECT_GET_CLASS (so
));
2458 g_return_if_fail (klass
!= NULL
);
2462 anchor_dir
= GOD_ANCHOR_DIR_UNKNOWN
;
2463 anchor_mode
= GNM_SO_ANCHOR_TWO_CELLS
;
2464 /* Provide a default. */
2465 anchor_r
= sheet_object_get_anchor (so
)->cell_bound
;
2467 for (i
= 0; attrs
!= NULL
&& attrs
[i
] && attrs
[i
+ 1] ; i
+= 2) {
2468 if (attr_eq (attrs
[i
], "Name"))
2469 sheet_object_set_name (so
, CXML2C (attrs
[i
+ 1]));
2470 else if (xml_sax_attr_enum (attrs
+ i
, "AnchorMode", GNM_SHEET_OBJECT_ANCHOR_MODE_TYPE
, &tmp_int
))
2471 anchor_mode
= tmp_int
;
2472 else if (attr_eq (attrs
[i
], "ObjectBound"))
2473 range_parse (&anchor_r
, CXML2C (attrs
[i
+ 1]), gnm_sheet_get_size (state
->sheet
));
2474 else if (attr_eq (attrs
[i
], "ObjectOffset") &&
2475 4 == sscanf (CXML2C (attrs
[i
+ 1]), "%lg %lg %lg %lg",
2476 f_tmp
+ 0, f_tmp
+ 1, f_tmp
+ 2, f_tmp
+ 3))
2477 anchor_offset
= f_tmp
;
2478 else if (gnm_xml_attr_int (attrs
+i
, "Direction", &tmp_int
))
2479 anchor_dir
= tmp_int
;
2480 else if (gnm_xml_attr_int (attrs
+i
, "Print", &tmp_int
)) {
2481 gboolean b
= (tmp_int
!= 0);
2482 sheet_object_set_print_flag (so
, &b
);
2486 /* Patch problems introduced in some 1.7.x versions that stored
2487 * comments in merged cells with the full rectangle of the merged cell
2488 * rather than just the top left corner */
2489 if (G_OBJECT_TYPE (so
) == GNM_CELL_COMMENT_TYPE
)
2490 anchor_r
.end
= anchor_r
.start
;
2492 sheet_object_anchor_init (&anchor
, &anchor_r
, anchor_offset
, anchor_dir
, anchor_mode
);
2493 sheet_object_set_anchor (so
, &anchor
);
2495 if (NULL
!= klass
->prep_sax_parser
)
2496 (klass
->prep_sax_parser
) (so
, xin
, attrs
, state
->convs
);
2497 if (needs_cleanup
) {
2498 /* Put in something to get gnm_xml_finish_obj called */
2499 static GsfXMLInNode
const dtd
[] = {
2500 GSF_XML_IN_NODE (STYLE
, STYLE
, -1, "", GSF_XML_NO_CONTENT
, NULL
, NULL
),
2503 static GsfXMLInDoc
*doc
= NULL
;
2505 doc
= gsf_xml_in_doc_new (dtd
, NULL
);
2506 gnm_xml_in_doc_dispose_on_exit (&doc
);
2508 /* we need to pas state there because xin->user_state might have
2509 changed, see #751217 */
2510 gsf_xml_in_push_state (xin
, doc
, state
,
2511 (GsfXMLInExtDtor
) gnm_xml_finish_obj
, attrs
);
2516 xml_sax_object_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2518 char const *type_name
= xin
->node
->name
;
2519 maybe_update_progress (xin
);
2520 xml_sax_read_obj (xin
, FALSE
, type_name
, attrs
);
2524 xml_sax_object_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2526 gnm_xml_finish_obj (xin
, xin
->user_state
);
2528 * WARNING: the object is not completely finished at this
2529 * time. Any handler installed by gog_object_sax_push_parser
2530 * has not yet been called. As a consequence, we cannot
2531 * update the GUI here.
2536 parse_constraint_side (const char *s
, const GnmParsePos
*pp
)
2538 GODateConventions
const *date_conv
=
2539 workbook_date_conv (pp
->sheet
->workbook
);
2540 GnmValue
*v
= format_match_number (s
, NULL
, date_conv
);
2543 GnmExprParseFlags flags
= GNM_EXPR_PARSE_DEFAULT
;
2544 v
= value_new_cellrange_parsepos_str (pp
, s
, flags
);
2551 xml_sax_solver_constr_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2554 GnmSolverConstraint
*c
;
2555 Sheet
*sheet
= gnm_xml_in_cur_sheet (xin
);
2556 GnmSolverParameters
*sp
= sheet
->solver_parameters
;
2557 int lhs_col
= 0, lhs_row
= 0, rhs_col
= 0, rhs_row
= 0;
2558 int cols
= 1, rows
= 1;
2559 gboolean old
= FALSE
;
2562 c
= gnm_solver_constraint_new (sheet
);
2564 parse_pos_init_sheet (&pp
, sheet
);
2566 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2567 if (gnm_xml_attr_int (attrs
, "Lcol", &lhs_col
) ||
2568 gnm_xml_attr_int (attrs
, "Lrow", &lhs_row
) ||
2569 gnm_xml_attr_int (attrs
, "Rcol", &rhs_col
) ||
2570 gnm_xml_attr_int (attrs
, "Rrow", &rhs_row
) ||
2571 gnm_xml_attr_int (attrs
, "Cols", &cols
) ||
2572 gnm_xml_attr_int (attrs
, "Rows", &rows
))
2574 else if (gnm_xml_attr_int (attrs
, "Type", &type
))
2576 else if (attr_eq (attrs
[0], "lhs")) {
2577 GnmValue
*v
= parse_constraint_side (CXML2C (attrs
[1]),
2579 gnm_solver_constraint_set_lhs (c
, v
);
2580 } else if (attr_eq (attrs
[0], "rhs")) {
2581 GnmValue
*v
= parse_constraint_side (CXML2C (attrs
[1]),
2583 gnm_solver_constraint_set_rhs (c
, v
);
2589 case 1: c
->type
= GNM_SOLVER_LE
; break;
2590 case 2: c
->type
= GNM_SOLVER_GE
; break;
2591 case 4: c
->type
= GNM_SOLVER_EQ
; break;
2592 case 8: c
->type
= GNM_SOLVER_INTEGER
; break;
2593 case 16: c
->type
= GNM_SOLVER_BOOLEAN
; break;
2597 gnm_solver_constraint_set_old (c
, c
->type
,
2602 sp
->constraints
= g_slist_append (sp
->constraints
, c
);
2606 xml_sax_solver_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2608 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2610 GnmSolverParameters
*sp
;
2611 int col
= -1, row
= -1;
2614 gboolean old
= FALSE
;
2616 xml_sax_must_have_sheet (state
);
2617 sheet
= gnm_xml_in_cur_sheet (xin
);
2618 sp
= sheet
->solver_parameters
;
2620 parse_pos_init_sheet (&pp
, sheet
);
2622 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2623 if (gnm_xml_attr_int (attrs
, "ModelType", &mtype
)) {
2624 sp
->options
.model_type
= (GnmSolverModelType
)mtype
;
2625 } else if (gnm_xml_attr_int (attrs
, "ProblemType", &ptype
)) {
2626 sp
->problem_type
= (GnmSolverProblemType
)ptype
;
2627 } else if (attr_eq (attrs
[0], "Inputs")) {
2628 GnmValue
*v
= value_new_cellrange_parsepos_str
2631 GNM_EXPR_PARSE_DEFAULT
);
2632 gnm_solver_param_set_input (sp
, v
);
2633 } else if (gnm_xml_attr_int (attrs
, "TargetCol", &col
) ||
2634 gnm_xml_attr_int (attrs
, "TargetRow", &row
)) {
2636 } else if (attr_eq (attrs
[0], "Target")) {
2637 GnmValue
*v
= value_new_cellrange_parsepos_str
2640 GNM_EXPR_PARSE_DEFAULT
);
2646 (gnm_sheet_range_from_value (&sr
, v
), !range_is_singleton (&sr
.range
)));
2652 gnm_cellref_init (&cr
, sr
.sheet
,
2656 gnm_solver_param_set_target (sp
, &cr
);
2657 } else if (gnm_xml_attr_int (attrs
, "MaxTime", &(sp
->options
.max_time_sec
)) ||
2658 gnm_xml_attr_int (attrs
, "MaxIter", &(sp
->options
.max_iter
)) ||
2659 gnm_xml_attr_bool (attrs
, "NonNeg", &(sp
->options
.assume_non_negative
)) ||
2660 gnm_xml_attr_bool (attrs
, "Discr", &(sp
->options
.assume_discrete
)) ||
2661 gnm_xml_attr_bool (attrs
, "AutoScale", &(sp
->options
.automatic_scaling
)) ||
2662 gnm_xml_attr_bool (attrs
, "ProgramR", &(sp
->options
.program_report
)) ||
2663 gnm_xml_attr_bool (attrs
, "SensitivityR", &(sp
->options
.sensitivity_report
)))
2668 col
>= 0 && col
< gnm_sheet_get_max_cols (sheet
) &&
2669 row
>= 0 && row
< gnm_sheet_get_max_rows (sheet
)) {
2671 gnm_cellref_init (&cr
, NULL
, col
, row
, TRUE
);
2672 gnm_solver_param_set_target (sp
, &cr
);
2677 xml_sax_scenario_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2679 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2680 const char *name
= "scenario";
2681 const char *comment
= NULL
;
2683 xml_sax_must_have_sheet (state
);
2685 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2686 if (attr_eq (attrs
[0], "Name")) {
2687 name
= CXML2C (attrs
[1]);
2688 } else if (attr_eq (attrs
[0], "Comment")) {
2689 comment
= CXML2C (attrs
[1]);
2693 state
->scenario
= gnm_sheet_scenario_new (state
->sheet
, name
);
2695 gnm_scenario_set_comment (state
->scenario
, comment
);
2699 xml_sax_scenario_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2701 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2702 GnmScenario
*sc
= state
->scenario
;
2703 sc
->items
= g_slist_reverse (sc
->items
);
2704 gnm_sheet_scenario_add (state
->sheet
, sc
);
2705 state
->scenario
= NULL
;
2709 xml_sax_scenario_item_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2711 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2712 const char *rtxt
= NULL
;
2715 for (; attrs
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
2716 if (attr_eq (attrs
[0], "Range")) {
2717 rtxt
= CXML2C (attrs
[1]);
2718 } else if (gnm_xml_attr_int (attrs
, "ValueType",
2719 &state
->value_type
))
2721 else if (attr_eq (attrs
[0], "ValueFormat"))
2722 state
->value_fmt
= make_format (CXML2C (attrs
[1]));
2725 parse_pos_init_sheet (&pp
, state
->sheet
);
2726 state
->scenario_range
= rtxt
2727 ? value_new_cellrange_parsepos_str (&pp
, rtxt
, GNM_EXPR_PARSE_DEFAULT
)
2732 xml_sax_scenario_item_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2734 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2735 char const * content
= xin
->content
->str
;
2736 int const len
= xin
->content
->len
;
2737 GnmScenarioItem
*sci
= NULL
;
2738 GnmScenario
*sc
= state
->scenario
;
2741 if (!state
->scenario_range
)
2744 gnm_sheet_range_from_value (&sr
, state
->scenario_range
);
2745 sci
= gnm_scenario_item_new (sc
->sheet
);
2746 gnm_scenario_item_set_range (sci
, &sr
);
2749 GnmValue
*v
= value_new_from_string (state
->value_type
,
2755 gnm_scenario_item_set_value (sci
, v
);
2759 sc
->items
= g_slist_prepend (sc
->items
, sci
);
2763 g_warning ("Ignoring invalid scenario item");
2765 gnm_scenario_item_free (sci
);
2768 state
->value_type
= -1;
2769 go_format_unref (state
->value_fmt
);
2770 state
->value_fmt
= NULL
;
2771 value_release (state
->scenario_range
);
2772 state
->scenario_range
= NULL
;
2776 xml_sax_named_expr_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2778 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2780 GnmNamedExpr
*nexpr
;
2782 g_return_if_fail (state
->name
.name
!= NULL
);
2783 g_return_if_fail (state
->name
.value
!= NULL
);
2785 /*For the next while we have to ignore Print_areas that look like a whole sheet */
2786 if (0 == strcmp (state
->name
.name
, "Print_Area")
2787 && g_str_has_suffix (state
->name
.value
, "$A$1:$IV$65536")) {
2788 g_free (state
->name
.value
);
2789 state
->name
.value
= NULL
;
2790 g_free (state
->name
.position
);
2791 state
->name
.position
= NULL
;
2793 parse_pos_init (&pp
, state
->wb
, state
->sheet
, 0, 0);
2794 nexpr
= expr_name_add (&pp
, state
->name
.name
,
2795 gnm_expr_top_new_constant (value_new_empty ()),
2800 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->sheet
);
2801 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->name
.value
);
2802 state
->name
.value
= NULL
;
2803 state
->delayed_names
= g_list_prepend (state
->delayed_names
, state
->name
.position
);
2804 state
->name
.position
= NULL
;
2805 state
->delayed_names
= g_list_prepend (state
->delayed_names
, nexpr
);
2807 g_warning ("Strangeness with defined name: %s",
2809 g_free (state
->name
.value
);
2810 state
->name
.value
= NULL
;
2811 g_free (state
->name
.position
);
2812 state
->name
.position
= NULL
;
2816 g_free (state
->name
.name
);
2817 state
->name
.name
= NULL
;
2821 xml_sax_named_expr_prop (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2823 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2825 char const * content
= xin
->content
->str
;
2826 int const len
= xin
->content
->len
;
2828 switch (xin
->node
->user_data
.v_int
) {
2830 g_return_if_fail (state
->name
.name
== NULL
);
2831 state
->name
.name
= g_strndup (content
, len
);
2834 g_return_if_fail (state
->name
.value
== NULL
);
2835 state
->name
.value
= g_strndup (content
, len
);
2838 g_return_if_fail (state
->name
.position
== NULL
);
2839 state
->name
.position
= g_strndup (content
, len
);
2847 xml_sax_print_order (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2849 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2851 xml_sax_must_have_sheet (state
);
2853 state
->sheet
->print_info
->print_across_then_down
=
2854 (strcmp (xin
->content
->str
, "r_then_d") == 0);
2858 xml_sax_print_comments_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2860 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2863 xml_sax_must_have_sheet (state
);
2865 /* In 1.11.x and later this is saved as an enum value */
2866 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
2867 if (xml_sax_attr_enum (attrs
, "placement", GNM_PRINT_COMMENT_PLACEMENT_TYPE
, &tmpi
))
2868 state
->sheet
->print_info
->comment_placement
= tmpi
;
2872 xml_sax_print_comments_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2874 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2876 if (xin
->content
->str
== NULL
|| *xin
->content
->str
== 0)
2877 /* 1.11.x or later file */
2880 xml_sax_must_have_sheet (state
);
2882 if (strcmp (xin
->content
->str
, "in_place") == 0)
2883 state
->sheet
->print_info
->comment_placement
=
2884 GNM_PRINT_COMMENTS_IN_PLACE
;
2885 else if (strcmp (xin
->content
->str
, "at_end") == 0)
2886 state
->sheet
->print_info
->comment_placement
=
2887 GNM_PRINT_COMMENTS_AT_END
;
2889 state
->sheet
->print_info
->comment_placement
=
2890 GNM_PRINT_COMMENTS_NONE
;
2894 xml_sax_print_errors_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
2896 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2899 xml_sax_must_have_sheet (state
);
2901 /* In 1.11.x and later this is saved as an enum value */
2902 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2)
2903 if (xml_sax_attr_enum (attrs
, "PrintErrorsAs", GNM_PRINT_ERRORS_TYPE
, &tmpi
))
2904 state
->sheet
->print_info
->error_display
= tmpi
;
2909 xml_sax_print_errors_end (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2911 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2913 if (xin
->content
->str
== NULL
|| *xin
->content
->str
== 0)
2914 /* 1.11.x or later file */
2917 xml_sax_must_have_sheet (state
);
2919 if (strcmp (xin
->content
->str
, "as_blank") == 0)
2920 state
->sheet
->print_info
->error_display
=
2921 GNM_PRINT_ERRORS_AS_BLANK
;
2922 else if (strcmp (xin
->content
->str
, "as_dashes") == 0)
2923 state
->sheet
->print_info
->error_display
=
2924 GNM_PRINT_ERRORS_AS_DASHES
;
2925 else if (strcmp (xin
->content
->str
, "as_na") == 0)
2926 state
->sheet
->print_info
->error_display
=
2927 GNM_PRINT_ERRORS_AS_NA
;
2929 state
->sheet
->print_info
->error_display
=
2930 GNM_PRINT_ERRORS_AS_DISPLAYED
;
2935 xml_sax_orientation (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2937 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2938 GnmPrintInformation
*pi
;
2939 GtkPageOrientation orient
= GTK_PAGE_ORIENTATION_PORTRAIT
;
2941 xml_sax_must_have_sheet (state
);
2943 pi
= state
->sheet
->print_info
;
2945 #warning TODO: we should also handle inversion
2946 if (strcmp (xin
->content
->str
, "portrait") == 0)
2947 orient
= GTK_PAGE_ORIENTATION_PORTRAIT
;
2948 else if (strcmp (xin
->content
->str
, "landscape") == 0)
2949 orient
= GTK_PAGE_ORIENTATION_LANDSCAPE
;
2951 print_info_set_paper_orientation (pi
, orient
);
2955 xml_sax_paper (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2957 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2959 xml_sax_must_have_sheet (state
);
2961 print_info_set_paper (state
->sheet
->print_info
, xin
->content
->str
);
2965 xml_sax_print_to_uri (GsfXMLIn
*xin
, G_GNUC_UNUSED GsfXMLBlob
*blob
)
2967 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
2969 xml_sax_must_have_sheet (state
);
2971 print_info_set_printtofile_uri (state
->sheet
->print_info
,
2976 handle_delayed_names (XMLSaxParseState
*state
)
2980 for (l
= state
->delayed_names
; l
; l
= l
->next
->next
->next
->next
) {
2981 GnmNamedExpr
*nexpr
= l
->data
;
2982 char *pos_str
= l
->next
->data
;
2983 char *expr_str
= l
->next
->next
->data
;
2984 Sheet
*sheet
= l
->next
->next
->next
->data
;
2986 GnmExprTop
const *texpr
;
2989 parse_pos_init (&pp
, state
->wb
, sheet
, 0, 0);
2993 GnmSheetSize
const *ss
=
2994 gnm_sheet_get_size2 (sheet
, state
->wb
);
2995 rest
= cellref_parse (&tmp
, ss
, pos_str
, &pp
.eval
);
2996 if (rest
!= NULL
&& *rest
== '\0') {
2997 pp
.eval
.col
= tmp
.col
;
2998 pp
.eval
.row
= tmp
.row
;
3002 parse_error_init (&perr
);
3003 texpr
= gnm_expr_parse_str (expr_str
, &pp
,
3004 GNM_EXPR_PARSE_DEFAULT
,
3008 go_io_warning (state
->context
, "%s", perr
.err
->message
);
3009 } else if (expr_name_check_for_loop (expr_name_name (nexpr
), texpr
)) {
3010 g_printerr ("Ignoring would-be circular definition of %s\n",
3011 expr_name_name (nexpr
));
3012 gnm_expr_top_unref (texpr
);
3014 nexpr
->pos
.eval
= pp
.eval
;
3015 expr_name_set_expr (nexpr
, texpr
);
3018 parse_error_free (&perr
);
3023 g_list_free (state
->delayed_names
);
3024 state
->delayed_names
= NULL
;
3028 xml_sax_go_doc (GsfXMLIn
*xin
, xmlChar
const **attrs
)
3030 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3031 go_doc_read (GO_DOC (state
->wb
), xin
, attrs
);
3034 /****************************************************************************/
3036 static GsfXMLInNS
const content_ns
[] = {
3037 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v14.dtd"), /* future */
3038 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v13.dtd"),
3039 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v12.dtd"),
3040 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v11.dtd"),
3041 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v10.dtd"),
3042 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v9.dtd"),
3043 GSF_XML_IN_NS (GNM
, "http://www.gnumeric.org/v8.dtd"),
3044 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v7"),
3045 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v6"),
3046 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v5"),
3047 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v4"),
3048 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v3"),
3049 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/v2"),
3050 GSF_XML_IN_NS (GNM
, "http://www.gnome.org/gnumeric/"),
3051 /* The next items are from libgsf, there is no obvious way of adding them automatically */
3052 GSF_XML_IN_NS (OO_NS_XSI
, "http://www.w3.org/2001/XMLSchema-instance"),
3053 GSF_XML_IN_NS (OO_NS_OFFICE
, "urn:oasis:names:tc:opendocument:xmlns:office:1.0"),
3054 GSF_XML_IN_NS (OO_NS_OOO
, "http://openoffice.org/2004/office"),
3055 GSF_XML_IN_NS (OO_NS_DC
, "http://purl.org/dc/elements/1.1/"),
3056 GSF_XML_IN_NS (OO_NS_XLINK
, "http://www.w3.org/1999/xlink"),
3057 GSF_XML_IN_NS (OO_NS_META
, "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"),
3061 static GsfXMLInNode gnumeric_1_0_dtd
[] = {
3062 GSF_XML_IN_NODE_FULL (START
, START
, -1, NULL
, GSF_XML_NO_CONTENT
, FALSE
, TRUE
, NULL
, NULL
, 0),
3063 GSF_XML_IN_NODE_FULL (START
, WB
, GNM
, "Workbook", GSF_XML_NO_CONTENT
, TRUE
, TRUE
, &xml_sax_wb
, NULL
, 0),
3064 GSF_XML_IN_NODE (WB
, WB_VERSION
, GNM
, "Version", GSF_XML_NO_CONTENT
, &xml_sax_version
, NULL
),
3065 GSF_XML_IN_NODE (WB
, WB_ATTRIBUTES
, GNM
, "Attributes", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3066 GSF_XML_IN_NODE (WB_ATTRIBUTES
, WB_ATTRIBUTE
, GNM
, "Attribute", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_finish_parse_wb_attr
),
3067 GSF_XML_IN_NODE_FULL (WB_ATTRIBUTE
, WB_ATTRIBUTE_NAME
, GNM
, "name", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_attr_elem
, 0),
3068 GSF_XML_IN_NODE_FULL (WB_ATTRIBUTE
, WB_ATTRIBUTE_VALUE
, GNM
, "value", GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_attr_elem
, 1),
3069 GSF_XML_IN_NODE (WB_ATTRIBUTE
, WB_ATTRIBUTE_TYPE
, GNM
, "type", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3071 /* The old 'SummaryItem' Metadata. Removed in 1.7.x */
3072 GSF_XML_IN_NODE (WB
, WB_SUMMARY
, GNM
, "Summary", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3073 GSF_XML_IN_NODE (WB_SUMMARY
, WB_SUMMARY_ITEM
, GNM
, "Item", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3074 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_NAME
, GNM
, "name", GSF_XML_CONTENT
, NULL
, NULL
),
3075 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_VALUE_STR
, GNM
, "val-string", GSF_XML_CONTENT
, NULL
, NULL
),
3076 GSF_XML_IN_NODE (WB_SUMMARY_ITEM
, WB_SUMMARY_ITEM_VALUE_INT
, GNM
, "val-int", GSF_XML_CONTENT
, NULL
, NULL
),
3078 GSF_XML_IN_NODE (WB
, WB_SHEETNAME_INDEX
, GNM
, "SheetNameIndex", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3079 GSF_XML_IN_NODE (WB_SHEETNAME_INDEX
, WB_SHEETNAME
, GNM
, "SheetName", GSF_XML_CONTENT
, &xml_sax_wb_sheetsize
, &xml_sax_wb_sheetname
),
3081 GSF_XML_IN_NODE (WB
, WB_NAMED_EXPRS
, GNM
, "Names", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3082 GSF_XML_IN_NODE (WB_NAMED_EXPRS
, WB_NAMED_EXPR
, GNM
, "Name", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_named_expr_end
),
3083 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),
3084 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),
3085 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),
3086 /* sometimes not namespaced */
3087 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),
3088 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),
3089 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),
3091 GSF_XML_IN_NODE (WB
, WB_SHEETS
, GNM
, "Sheets", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3092 GSF_XML_IN_NODE (WB_SHEETS
, SHEET
, GNM
, "Sheet", GSF_XML_NO_CONTENT
, &xml_sax_sheet_start
, &xml_sax_sheet_end
),
3093 GSF_XML_IN_NODE (SHEET
, SHEET_NAME
, GNM
, "Name", GSF_XML_CONTENT
, NULL
, &xml_sax_sheet_name
),
3094 GSF_XML_IN_NODE (SHEET
, SHEET_MAXCOL
, GNM
, "MaxCol", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3095 GSF_XML_IN_NODE (SHEET
, SHEET_MAXROW
, GNM
, "MaxRow", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3096 GSF_XML_IN_NODE (SHEET
, SHEET_ZOOM
, GNM
, "Zoom", GSF_XML_CONTENT
, NULL
, &xml_sax_sheet_zoom
),
3097 GSF_XML_IN_NODE (SHEET
, SHEET_NAMED_EXPRS
, GNM
, "Names", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3098 GSF_XML_IN_NODE (SHEET_NAMED_EXPRS
, SHEET_NAMED_EXPR
, GNM
, "Name", GSF_XML_NO_CONTENT
, NULL
, &xml_sax_named_expr_end
),
3099 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),
3100 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),
3101 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),
3103 GSF_XML_IN_NODE (SHEET
, SHEET_PRINTINFO
, GNM
, "PrintInformation", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3104 GSF_XML_IN_NODE (SHEET_PRINTINFO
, SHEET_PRINTUNIT
, GNM
, "PrintUnit", GSF_XML_NO_CONTENT
, NULL
, NULL
), /* ignore ancient field */
3105 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_MARGINS
, GNM
, "Margins", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3106 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_TOP
, GNM
, "top", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 0),
3107 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_BOTTOM
, GNM
, "bottom",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 1),
3108 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_LEFT
, GNM
, "left", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 2),
3109 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_RIGHT
, GNM
, "right", GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 3),
3110 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_HEADER
, GNM
, "header",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 4),
3111 GSF_XML_IN_NODE_FULL (PRINT_MARGINS
, PRINT_MARGIN_FOOTER
, GNM
, "footer",GSF_XML_CONTENT
, FALSE
, FALSE
, &xml_sax_print_margins
, NULL
, 5),
3112 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, V_PAGE_BREAKS
, GNM
, "vPageBreaks", GSF_XML_NO_CONTENT
,
3113 FALSE
, FALSE
, &xml_sax_page_breaks_begin
, &xml_sax_page_breaks_end
, 1),
3114 GSF_XML_IN_NODE (V_PAGE_BREAKS
, PAGE_BREAK
, GNM
, "break", GSF_XML_NO_CONTENT
, &xml_sax_page_break
, NULL
),
3115 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, H_PAGE_BREAKS
, GNM
, "hPageBreaks", GSF_XML_NO_CONTENT
,
3116 FALSE
, FALSE
, &xml_sax_page_breaks_begin
, &xml_sax_page_breaks_end
, 0),
3117 GSF_XML_IN_NODE (H_PAGE_BREAKS
, PAGE_BREAK
, GNM
, "break", GSF_XML_2ND
, NULL
, NULL
),
3119 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_SCALE
, GNM
, "Scale", GSF_XML_CONTENT
, &xml_sax_print_scale
, NULL
),
3120 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_VCENTER
, GNM
, "vcenter", GSF_XML_CONTENT
, &xml_sax_print_vcenter
, NULL
),
3121 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_HCENTER
, GNM
, "hcenter", GSF_XML_CONTENT
, &xml_sax_print_hcenter
, NULL
),
3122 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_GRID
, GNM
, "grid", GSF_XML_NO_CONTENT
, &xml_sax_print_grid
, NULL
),
3123 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
),
3124 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_PRINT_RANGE
, GNM
, "print_range",GSF_XML_NO_CONTENT
, &xml_sax_print_print_range
, NULL
),
3125 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_MONO
, GNM
, "monochrome", GSF_XML_NO_CONTENT
, &xml_sax_monochrome
, NULL
),
3126 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_AS_DRAFT
, GNM
, "draft", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3127 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_COMMENTS
, GNM
, "comments", GSF_XML_CONTENT
, &xml_sax_print_comments_start
, &xml_sax_print_comments_end
),
3128 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ERRORS
, GNM
, "errors", GSF_XML_CONTENT
, &xml_sax_print_errors_start
, &xml_sax_print_errors_end
),
3129 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_TITLES
, GNM
, "titles", GSF_XML_NO_CONTENT
, &xml_sax_print_titles
, NULL
),
3130 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_REPEAT_TOP
, GNM
, "repeat_top", GSF_XML_NO_CONTENT
, &xml_sax_repeat_top
, NULL
),
3131 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_REPEAT_LEFT
,GNM
, "repeat_left", GSF_XML_NO_CONTENT
, &xml_sax_repeat_left
, NULL
),
3132 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, PRINT_FOOTER
, GNM
, "Footer", GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_print_hf
, NULL
, 0),
3133 GSF_XML_IN_NODE_FULL (SHEET_PRINTINFO
, PRINT_HEADER
, GNM
, "Header", GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_print_hf
, NULL
, 1),
3134 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ORDER
, GNM
, "order", GSF_XML_CONTENT
, NULL
, &xml_sax_print_order
),
3135 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_PAPER
, GNM
, "paper", GSF_XML_CONTENT
, NULL
, &xml_sax_paper
),
3136 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_TO_URI
, GNM
, "print-to-uri",GSF_XML_CONTENT
, NULL
, &xml_sax_print_to_uri
),
3137 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ORIENT
, GNM
, "orientation", GSF_XML_CONTENT
, NULL
, &xml_sax_orientation
),
3138 GSF_XML_IN_NODE (SHEET_PRINTINFO
, PRINT_ONLY_STYLE
, GNM
, "even_if_only_styles", GSF_XML_CONTENT
, &xml_sax_even_if_only_styles
, NULL
),
3140 GSF_XML_IN_NODE (SHEET
, SHEET_STYLES
, GNM
, "Styles", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3141 GSF_XML_IN_NODE (SHEET_STYLES
, STYLE_REGION
, GNM
, "StyleRegion", GSF_XML_NO_CONTENT
, &xml_sax_style_region_start
, &xml_sax_style_region_end
),
3142 GSF_XML_IN_NODE (STYLE_REGION
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, &xml_sax_style_start
, NULL
),
3143 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_FONT
, GNM
, "Font", GSF_XML_CONTENT
, &xml_sax_style_font
, &xml_sax_style_font_end
),
3144 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_BORDER
, GNM
, "StyleBorder", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3145 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_TOP
, GNM
, "Top",
3146 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_TOP
),
3147 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_BOTTOM
, GNM
, "Bottom",
3148 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_BOTTOM
),
3149 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_LEFT
, GNM
, "Left",
3150 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_LEFT
),
3151 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_RIGHT
, GNM
, "Right",
3152 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_RIGHT
),
3153 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_DIAG
, GNM
, "Diagonal",
3154 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_DIAGONAL
),
3155 GSF_XML_IN_NODE_FULL (STYLE_BORDER
, BORDER_REV_DIAG
,GNM
, "Rev-Diagonal",
3156 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_style_border
, NULL
, MSTYLE_BORDER_REV_DIAGONAL
),
3158 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_VALIDATION
, GNM
, "Validation", GSF_XML_NO_CONTENT
, &xml_sax_validation
, &xml_sax_validation_end
),
3159 GSF_XML_IN_NODE_FULL (STYLE_VALIDATION
, STYLE_VALIDATION_EXPR0
, GNM
, "Expression0",
3160 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_validation_expr_end
, 0),
3161 GSF_XML_IN_NODE_FULL (STYLE_VALIDATION
, STYLE_VALIDATION_EXPR1
, GNM
, "Expression1",
3162 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_validation_expr_end
, 1),
3163 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_HYPERLINK
, GNM
, "HyperLink", GSF_XML_NO_CONTENT
, &xml_sax_hlink
, NULL
),
3164 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_INPUT_MSG
, GNM
, "InputMessage", GSF_XML_NO_CONTENT
, &xml_sax_input_msg
, NULL
),
3165 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_CONDITION
, GNM
, "Condition", GSF_XML_NO_CONTENT
, &xml_sax_condition
, &xml_sax_condition_end
),
3166 GSF_XML_IN_NODE_FULL (STYLE_CONDITION
, STYLE_CONDITION_EXPR0
, GNM
, "Expression0",
3167 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_condition_expr_end
, 0),
3168 GSF_XML_IN_NODE_FULL (STYLE_CONDITION
, STYLE_CONDITION_EXPR1
, GNM
, "Expression1",
3169 GSF_XML_CONTENT
, FALSE
, FALSE
, NULL
, &xml_sax_condition_expr_end
, 1),
3170 GSF_XML_IN_NODE (STYLE_CONDITION
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3172 GSF_XML_IN_NODE_FULL (SHEET
, SHEET_COLS
, GNM
, "Cols",
3173 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_cols_rows
, NULL
, TRUE
),
3174 GSF_XML_IN_NODE_FULL (SHEET_COLS
, COL
, GNM
, "ColInfo",
3175 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_colrow
, NULL
, TRUE
),
3177 GSF_XML_IN_NODE_FULL (SHEET
, SHEET_ROWS
, GNM
, "Rows",
3178 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_cols_rows
, NULL
, FALSE
),
3179 GSF_XML_IN_NODE_FULL (SHEET_ROWS
, ROW
, GNM
, "RowInfo",
3180 GSF_XML_NO_CONTENT
, FALSE
, FALSE
, &xml_sax_colrow
, NULL
, FALSE
),
3182 GSF_XML_IN_NODE (SHEET
, SHEET_SELECTIONS
, GNM
, "Selections", GSF_XML_NO_CONTENT
, &xml_sax_selection
, &xml_sax_selection_end
),
3183 GSF_XML_IN_NODE (SHEET_SELECTIONS
, SELECTION
, GNM
, "Selection", GSF_XML_NO_CONTENT
, &xml_sax_selection_range
, NULL
),
3185 GSF_XML_IN_NODE (SHEET
, SHEET_CELLS
, GNM
, "Cells", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3186 GSF_XML_IN_NODE (SHEET_CELLS
, CELL
, GNM
, "Cell", GSF_XML_CONTENT
, &xml_sax_cell
, &xml_sax_cell_content
),
3187 GSF_XML_IN_NODE (CELL
, CELL_CONTENT
, GNM
, "Content", GSF_XML_CONTENT
, NULL
, &xml_sax_cell_content
),
3189 GSF_XML_IN_NODE (SHEET
, SHEET_MERGED_REGIONS
, GNM
, "MergedRegions", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3190 GSF_XML_IN_NODE (SHEET_MERGED_REGIONS
, MERGED_REGION
, GNM
, "Merge", GSF_XML_CONTENT
, NULL
, &xml_sax_merge
),
3192 GSF_XML_IN_NODE (SHEET
, SHEET_FILTERS
, GNM
, "Filters", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3193 GSF_XML_IN_NODE (SHEET_FILTERS
, FILTER
, GNM
, "Filter", GSF_XML_NO_CONTENT
, &xml_sax_filter_start
, &xml_sax_filter_end
),
3194 GSF_XML_IN_NODE (FILTER
, FILTER_FIELD
, GNM
, "Field", GSF_XML_NO_CONTENT
, &xml_sax_filter_condition
, NULL
),
3196 GSF_XML_IN_NODE (SHEET
, SHEET_LAYOUT
, GNM
, "SheetLayout", GSF_XML_NO_CONTENT
, &xml_sax_sheet_layout
, NULL
),
3197 GSF_XML_IN_NODE (SHEET_LAYOUT
, SHEET_FREEZEPANES
, GNM
, "FreezePanes", GSF_XML_NO_CONTENT
, &xml_sax_sheet_freezepanes
, NULL
),
3199 GSF_XML_IN_NODE (SHEET
, SHEET_SOLVER
, GNM
, "Solver", GSF_XML_NO_CONTENT
, xml_sax_solver_start
, NULL
),
3200 GSF_XML_IN_NODE (SHEET_SOLVER
, SOLVER_CONSTR
, GNM
, "Constr", GSF_XML_NO_CONTENT
, xml_sax_solver_constr_start
, NULL
),
3201 GSF_XML_IN_NODE (SHEET
, SHEET_SCENARIOS
, GNM
, "Scenarios", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3202 GSF_XML_IN_NODE (SHEET_SCENARIOS
, SHEET_SCENARIO
, GNM
, "Scenario", GSF_XML_NO_CONTENT
, xml_sax_scenario_start
, xml_sax_scenario_end
),
3203 GSF_XML_IN_NODE (SHEET_SCENARIO
, SCENARIO_ITEM
, GNM
, "Item", GSF_XML_CONTENT
, xml_sax_scenario_item_start
, xml_sax_scenario_item_end
),
3205 GSF_XML_IN_NODE (SHEET
, SHEET_OBJECTS
, GNM
, "Objects", GSF_XML_NO_CONTENT
, NULL
, NULL
),
3207 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_RECT
, GNM
, "Rectangle", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3208 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_ELLIPSE
, GNM
, "Ellipse", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3209 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_ARROW
, GNM
, "Arrow", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3210 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_ANCIENT_LINE
, GNM
, "Line", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3211 /* Class renamed between 1.0.x and 1.2.x */
3212 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_GRAPH
, GNM
, "GnmGraph", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3213 /* Class renamed in 1.2.2 */
3214 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_COMMENT
, GNM
, "CellComment", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3215 /* Class renamed in 1.3.91 */
3216 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_LINE
, GNM
, "SheetObjectGraphic", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3217 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_FILLED
, GNM
, "SheetObjectFilled", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3218 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_OLD_TEXT
, GNM
, "SheetObjectText", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3219 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_GRAPH
, GNM
, "SheetObjectGraph", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3220 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_IMAGE
, GNM
, "SheetObjectImage", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3221 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_COMPONENT
, GNM
, "SheetObjectComponent", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3222 GSF_XML_IN_NODE (SHEET_OBJECTS
, OBJECT_PATH
, GNM
, "SheetObjectPath", GSF_XML_NO_CONTENT
, &xml_sax_object_start
, &xml_sax_object_end
),
3224 GSF_XML_IN_NODE (WB
, WB_GEOMETRY
, GNM
, "Geometry", GSF_XML_NO_CONTENT
, &xml_sax_wb_view
, NULL
),
3225 GSF_XML_IN_NODE (WB
, WB_VIEW
, GNM
, "UIData", GSF_XML_NO_CONTENT
, &xml_sax_wb_view
, NULL
),
3226 GSF_XML_IN_NODE (WB
, WB_CALC
, GNM
, "Calculation", GSF_XML_NO_CONTENT
, &xml_sax_calculation
, NULL
),
3227 GSF_XML_IN_NODE (WB
, WB_DATE
, GNM
, "DateConvention", GSF_XML_CONTENT
, NULL
, &xml_sax_old_dateconvention
),
3228 GSF_XML_IN_NODE (WB
, GODOC
, -1, "GODoc", GSF_XML_NO_CONTENT
, &xml_sax_go_doc
, NULL
),
3229 GSF_XML_IN_NODE (WB
, DOCUMENTMETA
, OO_NS_OFFICE
, "document-meta", GSF_XML_NO_CONTENT
, &xml_sax_document_meta
, NULL
),
3234 xml_sax_clipboardrange_start (GsfXMLIn
*xin
, xmlChar
const **attrs
)
3236 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3237 int cols
= -1, rows
= -1, base_col
= -1, base_row
= -1;
3240 cr
= state
->clipboard
= gnm_cell_region_new (state
->sheet
);
3242 for (; attrs
!= NULL
&& attrs
[0] && attrs
[1] ; attrs
+= 2) {
3243 if (gnm_xml_attr_int (attrs
, "Cols", &cols
) ||
3244 gnm_xml_attr_int (attrs
, "Rows", &rows
) ||
3245 gnm_xml_attr_int (attrs
, "BaseCol", &base_col
) ||
3246 gnm_xml_attr_int (attrs
, "BaseRow", &base_row
) ||
3247 gnm_xml_attr_bool (attrs
, "NotAsContent", &cr
->not_as_contents
))
3249 else if (attr_eq (attrs
[0], "DateConvention")) {
3250 GODateConventions
const *date_conv
=
3251 go_date_conv_from_str (CXML2C (attrs
[1]));
3253 cr
->date_conv
= date_conv
;
3255 g_printerr ("Ignoring invalid date conventions.\n");
3259 if (cols
<= 0 || rows
<= 0 || base_col
< 0 || base_row
< 0) {
3260 g_printerr ("Invalid clipboard contents.\n");
3264 cr
->base
.col
= base_col
;
3265 cr
->base
.row
= base_row
;
3269 static GsfXMLInNode clipboard_dtd
[] = {
3270 GSF_XML_IN_NODE_FULL (START
, START
, -1, NULL
, GSF_XML_NO_CONTENT
, FALSE
, TRUE
, NULL
, NULL
, 0),
3271 GSF_XML_IN_NODE_FULL (START
, CLIPBOARDRANGE
, GNM
, "ClipboardRange", GSF_XML_NO_CONTENT
, TRUE
, TRUE
, xml_sax_clipboardrange_start
, NULL
, 0),
3272 /* We insert "Styles" (etc) */
3277 gnm_xml_in_doc_add_subset (GsfXMLInDoc
*doc
, GsfXMLInNode
*dtd
,
3278 const char *id
, const char *new_parent
)
3280 GHashTable
*parents
= g_hash_table_new (g_str_hash
, g_str_equal
);
3281 GsfXMLInNode end_node
= GSF_XML_IN_NODE_END
;
3282 GArray
*new_dtd
= g_array_new (FALSE
, FALSE
, sizeof (GsfXMLInNode
));
3284 for (; dtd
->id
; dtd
++) {
3285 GsfXMLInNode node
= *dtd
;
3287 if (g_str_equal (id
, dtd
->id
)) {
3288 g_hash_table_insert (parents
,
3292 node
.parent_id
= new_parent
;
3293 } else if (g_hash_table_lookup (parents
, dtd
->parent_id
))
3294 g_hash_table_insert (parents
,
3300 g_array_append_val (new_dtd
, node
);
3303 g_array_append_val (new_dtd
, end_node
);
3305 gsf_xml_in_doc_add_nodes (doc
, (GsfXMLInNode
*)(new_dtd
->data
));
3307 g_array_free (new_dtd
, TRUE
);
3308 g_hash_table_destroy (parents
);
3313 xml_sax_unknown (GsfXMLIn
*xin
, xmlChar
const *elem
, xmlChar
const **attrs
)
3315 g_return_val_if_fail (xin
!= NULL
, FALSE
);
3316 g_return_val_if_fail (xin
->doc
!= NULL
, FALSE
);
3317 g_return_val_if_fail (xin
->node
!= NULL
, FALSE
);
3319 if (GNM
== xin
->node
->ns_id
&&
3320 0 == strcmp (xin
->node
->id
, "SHEET_OBJECTS")) {
3321 char const *type_name
= gsf_xml_in_check_ns (xin
, CXML2C (elem
), GNM
);
3322 if (type_name
!= NULL
) {
3323 XMLSaxParseState
*state
= (XMLSaxParseState
*)xin
->user_state
;
3324 /* This may change xin->user_state. */
3325 xml_sax_read_obj (xin
, TRUE
, type_name
, attrs
);
3326 /* xin->user_state hasn't been restored yet. */
3327 return state
->so
!= NULL
;
3334 read_file_init_state (XMLSaxParseState
*state
,
3335 GOIOContext
*io_context
,
3336 WorkbookView
*wb_view
, Sheet
*sheet
)
3338 state
->context
= io_context
;
3339 state
->wb_view
= wb_view
;
3342 : (wb_view
? wb_view_get_workbook (wb_view
) : NULL
);
3343 state
->sheet
= sheet
;
3344 state
->version
= GNM_XML_UNKNOWN
;
3345 state
->last_progress_update
= 0;
3346 state
->convs
= gnm_xml_io_conventions ();
3347 state
->attribute
.name
= state
->attribute
.value
= NULL
;
3348 state
->name
.name
= state
->name
.value
= state
->name
.position
= NULL
;
3349 state
->style_range_init
= FALSE
;
3350 state
->style
= NULL
;
3351 state
->cell
.row
= state
->cell
.col
= -1;
3352 state
->seen_cell_contents
= FALSE
;
3353 state
->array_rows
= state
->array_cols
= -1;
3354 state
->expr_id
= -1;
3355 state
->value_type
= -1;
3356 state
->value_fmt
= NULL
;
3357 state
->scenario
= NULL
;
3358 state
->scenario_range
= NULL
;
3359 state
->filter
= NULL
;
3360 state
->validation
.title
= state
->validation
.msg
= NULL
;
3361 state
->validation
.texpr
[0] = state
->validation
.texpr
[1] = NULL
;
3363 state
->cond_save_style
= NULL
;
3364 state
->expr_map
= g_hash_table_new_full
3365 (g_direct_hash
, g_direct_equal
,
3366 NULL
, (GFreeFunc
)gnm_expr_top_unref
);
3367 state
->delayed_names
= NULL
;
3369 state
->page_breaks
= NULL
;
3370 state
->clipboard
= NULL
;
3371 state
->style_handler
= NULL
;
3372 state
->style_handler_user
= NULL
;
3373 state
->style_handler_doc
= NULL
;
3377 read_file_free_state (XMLSaxParseState
*state
, gboolean self
)
3379 g_hash_table_destroy (state
->expr_map
);
3380 state
->expr_map
= NULL
;
3382 gnm_conventions_unref (state
->convs
);
3383 state
->convs
= NULL
;
3386 * Malformed documents can cause the parser to exit early.
3387 * This cleans up various bits that may be left.
3391 gnm_style_unref (state
->style
);
3392 state
->style
= NULL
;
3395 if (state
->cond_save_style
) {
3396 gnm_style_unref (state
->cond_save_style
);
3397 state
->cond_save_style
= NULL
;
3401 gnm_style_cond_free (state
->cond
);
3405 if (state
->style_handler_doc
) {
3406 gsf_xml_in_doc_free (state
->style_handler_doc
);
3407 state
->style_handler_doc
= NULL
;
3420 read_file_common (ReadFileWhat what
, XMLSaxParseState
*state
,
3421 GOIOContext
*io_context
,
3422 WorkbookView
*wb_view
, Sheet
*sheet
,
3429 g_return_val_if_fail (GNM_IS_WORKBOOK_VIEW (wb_view
), FALSE
);
3430 g_return_val_if_fail (GSF_IS_INPUT (input
), FALSE
);
3432 read_file_init_state (state
, io_context
, wb_view
, sheet
);
3435 case READ_FULL_FILE
:
3436 state
->do_progress
= TRUE
;
3437 doc
= gsf_xml_in_doc_new (gnumeric_1_0_dtd
, content_ns
);
3439 case READ_CLIPBOARD
:
3440 state
->do_progress
= FALSE
;
3441 doc
= gsf_xml_in_doc_new (clipboard_dtd
, content_ns
);
3444 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3447 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3450 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3451 "SHEET_MERGED_REGIONS",
3453 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3458 g_assert_not_reached ();
3465 gsf_xml_in_doc_set_unknown_handler (doc
, &xml_sax_unknown
);
3467 go_doc_init_read (GO_DOC (state
->wb
), input
);
3468 gsf_input_seek (input
, 0, G_SEEK_SET
);
3470 if (state
->do_progress
) {
3471 go_io_progress_message (state
->context
,
3472 _("Reading file..."));
3473 go_io_value_progress_set (state
->context
,
3474 gsf_input_size (input
), 0);
3477 locale
= gnm_push_C_locale ();
3478 ok
= gsf_xml_in_doc_parse (doc
, input
, state
);
3479 handle_delayed_names (state
);
3480 gnm_pop_C_locale (locale
);
3482 go_doc_end_read (GO_DOC (state
->wb
));
3484 if (state
->do_progress
)
3485 go_io_progress_unset (state
->context
);
3488 go_io_error_string (state
->context
,
3489 _("XML document not well formed!"));
3492 gsf_xml_in_doc_free (doc
);
3497 /* ------------------------------------------------------------------------- */
3500 maybe_gunzip (GsfInput
*input
)
3502 GsfInput
*gzip
= gsf_input_gzip_new (input
, NULL
);
3504 g_object_unref (input
);
3507 gsf_input_seek (input
, 0, G_SEEK_SET
);
3513 maybe_convert (GsfInput
*input
, gboolean quiet
)
3515 static char const *noencheader
= "<?xml version=\"1.0\"?>";
3516 static char const *encheader
= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
3517 const size_t nelen
= strlen (noencheader
);
3518 const size_t elen
= strlen (encheader
);
3520 gsf_off_t input_size
;
3521 GString the_buffer
, *buffer
= &the_buffer
;
3523 GString
*converted
= NULL
;
3524 char const *encoding
;
3526 gboolean any_numbered
= FALSE
;
3528 input_size
= gsf_input_remaining (input
);
3530 buf
= gsf_input_read (input
, nelen
, NULL
);
3532 strncmp (noencheader
, (const char *)buf
, nelen
) != 0 ||
3533 input_size
>= (gsf_off_t
)(G_MAXINT
- elen
))
3536 input_size
-= nelen
;
3539 the_buffer
.allocated_len
= input_size
+ elen
+ 1;
3540 the_buffer
.str
= g_try_malloc (the_buffer
.allocated_len
);
3541 if (!the_buffer
.str
)
3544 g_string_append (buffer
, encheader
);
3545 ok
= gsf_input_read (input
, input_size
, (guint8
*)buffer
->str
+ elen
) != NULL
;
3546 gsf_input_seek (input
, 0, G_SEEK_SET
);
3548 g_free (buffer
->str
);
3551 buffer
->len
= input_size
+ elen
;
3552 buffer
->str
[buffer
->len
] = 0;
3554 for (ui
= 0; ui
< buffer
->len
; ui
++) {
3555 if (buffer
->str
[ui
] == '&' &&
3556 buffer
->str
[ui
+ 1] == '#' &&
3557 g_ascii_isdigit (buffer
->str
[ui
+ 2])) {
3561 while (g_ascii_isdigit (buffer
->str
[ui
])) {
3562 c
= c
* 10 + (buffer
->str
[ui
] - '0');
3565 if (buffer
->str
[ui
] == ';' && c
>= 128 && c
<= 255) {
3566 buffer
->str
[start
] = c
;
3567 g_string_erase (buffer
, start
+ 1, ui
- start
);
3570 any_numbered
= TRUE
;
3574 encoding
= go_guess_encoding (buffer
->str
, buffer
->len
, NULL
, &converted
, NULL
);
3575 if (encoding
&& !any_numbered
&&
3576 converted
&& buffer
->len
== converted
->len
&&
3577 strcmp (buffer
->str
, converted
->str
) == 0)
3580 g_free (buffer
->str
);
3583 gsize len
= converted
->len
;
3584 g_object_unref (input
);
3586 g_warning ("Converted xml document with no explicit encoding from transliterated %s to UTF-8.",
3588 return gsf_input_memory_new ((void *)g_string_free (converted
, FALSE
), len
, TRUE
);
3591 g_warning ("Failed to convert xml document with no explicit encoding to UTF-8.");
3597 gnm_xml_file_open (G_GNUC_UNUSED GOFileOpener
const *fo
, GOIOContext
*io_context
,
3598 GoView
*view
, GsfInput
*input
)
3600 XMLSaxParseState state
;
3603 g_object_ref (input
);
3604 input
= maybe_gunzip (input
);
3605 input
= maybe_convert (input
, FALSE
);
3607 ok
= read_file_common (READ_FULL_FILE
, &state
,
3608 io_context
, GNM_WORKBOOK_VIEW (view
), NULL
,
3611 g_object_unref (input
);
3614 workbook_queue_all_recalc (state
.wb
);
3616 workbook_set_saveinfo
3619 go_file_saver_for_id ("Gnumeric_XmlIO:sax"));
3622 read_file_free_state (&state
, FALSE
);
3625 /* ------------------------------------------------------------------------- */
3628 gnm_xml_cellregion_read (WorkbookControl
*wbc
, GOIOContext
*io_context
,
3630 const char *buffer
, int length
)
3632 WorkbookView
*wb_view
;
3634 XMLSaxParseState state
;
3635 GnmCellRegion
*result
;
3637 wb_view
= wb_control_view (wbc
);
3638 input
= gsf_input_memory_new (buffer
, length
, FALSE
);
3639 read_file_common (READ_CLIPBOARD
, &state
,
3640 io_context
, wb_view
, sheet
,
3642 g_object_unref (input
);
3644 result
= state
.clipboard
;
3645 state
.clipboard
= NULL
;
3647 read_file_free_state (&state
, FALSE
);
3652 /* ------------------------------------------------------------------------- */
3655 style_parser_done (GsfXMLIn
*xin
, XMLSaxParseState
*old_state
)
3657 GnmStyle
*style
= old_state
->style
;
3658 old_state
->style_handler (xin
, style
, old_state
->style_handler_user
);
3659 read_file_free_state (old_state
, TRUE
);
3663 * gnm_xml_prep_style_parser:
3666 * @handler: (scope call):
3671 gnm_xml_prep_style_parser (GsfXMLIn
*xin
,
3672 xmlChar
const **attrs
,
3673 GnmXmlStyleHandler handler
,
3676 static GsfXMLInNode dtd
[] = {
3677 GSF_XML_IN_NODE (STYLE_STYLE
, STYLE_STYLE
, GNM
, "Style", GSF_XML_NO_CONTENT
, &xml_sax_style_start
, NULL
),
3678 /* Nodes added below. */
3681 GsfXMLInDoc
*doc
= gsf_xml_in_doc_new (dtd
, NULL
);
3682 XMLSaxParseState
*state
= g_new0 (XMLSaxParseState
, 1);
3684 read_file_init_state (state
, NULL
, NULL
, NULL
);
3685 state
->style_handler
= handler
;
3686 state
->style_handler_user
= user
;
3687 state
->style_handler_doc
= doc
;
3688 state
->style
= gnm_style_new_default ();
3690 /* Not a full style, just those parts that do not require a sheet. */
3691 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3694 gnm_xml_in_doc_add_subset (doc
, gnumeric_1_0_dtd
,
3698 gsf_xml_in_push_state (xin
, doc
, state
,
3699 (GsfXMLInExtDtor
)style_parser_done
, attrs
);
3702 /* ------------------------------------------------------------------------- */
3705 gnm_xml_probe_element (const xmlChar
*name
,
3706 G_GNUC_UNUSED
const xmlChar
*prefix
,
3708 G_GNUC_UNUSED
int nb_namespaces
,
3709 G_GNUC_UNUSED
const xmlChar
**namespaces
,
3710 G_GNUC_UNUSED
int nb_attributes
,
3711 G_GNUC_UNUSED
int nb_defaulted
,
3712 G_GNUC_UNUSED
const xmlChar
**attributes
)
3714 return 0 == strcmp (name
, "Workbook") &&
3715 NULL
!= URI
&& NULL
!= strstr (URI
, "gnumeric");
3719 xml_probe (G_GNUC_UNUSED GOFileOpener
const *fo
, GsfInput
*input
, GOFileProbeLevel pl
)
3721 if (pl
== GO_FILE_PROBE_FILE_NAME
) {
3722 char const *name
= gsf_input_name (input
);
3728 len
= strlen (name
);
3729 if (len
>= 7 && !g_ascii_strcasecmp (name
+len
-7, ".xml.gz"))
3732 name
= gsf_extension_pointer (name
);
3734 return (name
!= NULL
&&
3735 (g_ascii_strcasecmp (name
, "gnumeric") == 0 ||
3736 g_ascii_strcasecmp (name
, "xml") == 0));
3738 /* probe by content */
3739 return gsf_xml_probe (input
, &gnm_xml_probe_element
);
3742 #define XML_SAX_ID "Gnumeric_XmlIO:sax"
3745 gnm_xml_sax_read_init (void)
3747 GOFileOpener
*opener
;
3748 GSList
*suffixes
= go_slist_create (g_strdup ("gnumeric"),
3751 GSList
*mimes
= go_slist_create (g_strdup ("application/x-gnumeric"),
3754 opener
= go_file_opener_new
3756 _("Gnumeric XML (*.gnumeric)"),
3758 xml_probe
, gnm_xml_file_open
);
3759 go_file_opener_register (opener
, 50);
3760 g_object_unref (opener
);
3764 gnm_xml_sax_read_shutdown (void)
3766 go_file_opener_unregister
3767 (go_file_opener_for_id (XML_SAX_ID
));