Make graphs (and images) not resize with cells by default. [#684450]
[gnumeric.git] / plugins / excel / xlsx-read-drawing.c
blobd557e7e9d39c8ea146287836e42cace45215d316
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * xlsx-drawing-read.c : import MS Office Open xlsx drawings and charts.
5 * Copyright (C) 2006-2007 Jody Goldberg (jody@gnome.org)
6 * Copyright (C) 2011 Jean Brefort (jean.brefort@normalesup.org)
7 * Copyright (C) 2015 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
22 * USA
25 #include "sheet-object-widget.h"
27 #undef DEBUG_AXIS
28 #undef DEBUG_COLOR
30 /*****************************************************************************
31 * Various functions common to at least charts and user shapes *
32 *****************************************************************************/
34 static void
35 xlsx_chart_push_obj (XLSXReadState *state, GogObject *obj)
37 state->obj_stack = g_slist_prepend (state->obj_stack, state->cur_obj);
38 state->cur_obj = obj;
39 state->style_stack = g_slist_prepend (state->style_stack, state->cur_style);
40 state->cur_style = GO_IS_STYLED_OBJECT (obj)? go_style_dup (go_styled_object_get_style (GO_STYLED_OBJECT (obj))): NULL;
41 #if 0
42 g_print ("push %s\n", G_OBJECT_TYPE_NAME (obj));
43 #endif
45 if (obj) {
46 const char *name = gog_object_get_name (obj);
47 go_debug_check_finalized (obj, name);
49 if (state->cur_style) {
50 go_debug_check_finalized (state->cur_style, "Anonymous style");
54 static void
55 xlsx_chart_pop_obj (XLSXReadState *state)
57 GSList *obj_stack = state->obj_stack;
58 g_return_if_fail (obj_stack != NULL);
60 #if 0
61 g_print ("pop %s\n", G_OBJECT_TYPE_NAME (state->cur_obj));
62 #endif
64 if (state->cur_style) {
65 if (state->cur_obj)
66 g_object_set (G_OBJECT (state->cur_obj), "style", state->cur_style, NULL);
67 g_object_unref (state->cur_style);
69 state->cur_obj = obj_stack->data;
70 state->obj_stack = g_slist_remove (state->obj_stack, state->cur_obj);
71 state->cur_style = state->style_stack->data;
72 state->style_stack = g_slist_remove (state->style_stack, state->cur_style);
75 static void
76 xlsx_reset_chart_pos (XLSXReadState *state)
78 int i;
79 for (i = 0; i < 4; i++) {
80 state->chart_pos[i] = go_nan;
81 state->chart_pos_mode[i] = FALSE;
83 state->chart_pos_target = FALSE;
87 static void
88 xlsx_push_text_object (XLSXReadState *state, const char *name)
90 GogObject *label = gog_object_add_by_name (state->cur_obj, name, NULL);
91 state->sp_type |= GO_STYLE_FONT;
92 g_object_set (G_OBJECT (label), "allow-wrap", TRUE, "justification", "center", NULL);
93 xlsx_chart_push_obj (state, label);
97 typedef enum {
98 XLSX_CS_NONE = 0,
99 XLSX_CS_FONT = 1,
100 XLSX_CS_LINE = 2,
101 XLSX_CS_FILL_BACK = 3,
102 XLSX_CS_FILL_FORE = 4,
103 XLSX_CS_MARKER = 5,
104 XLSX_CS_MARKER_OUTLINE = 6,
105 XLSX_CS_ANY = 7 /* for pop */
106 } XLSXColorState;
108 static void
109 xlsx_chart_push_color_state (XLSXReadState *state, XLSXColorState s)
111 /* We need only a few levels. */
112 state->chart_color_state = (state->chart_color_state << 3) | s;
115 static void
116 xlsx_chart_pop_color_state (XLSXReadState *state, XLSXColorState s)
118 XLSXColorState s0 = (state->chart_color_state & 7);
119 state->chart_color_state = (state->chart_color_state >> 3);
120 if (s != XLSX_CS_ANY)
121 g_return_if_fail (s == s0);
126 static void
127 xlsx_tx_pr (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
129 XLSXReadState *state = (XLSXReadState *)xin->user_state;
130 state->sp_type |= GO_STYLE_FONT;
131 xlsx_chart_push_color_state (state, XLSX_CS_FONT);
134 static void
135 xlsx_tx_pr_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
137 XLSXReadState *state = (XLSXReadState *)xin->user_state;
138 state->sp_type &= ~GO_STYLE_FONT;
139 xlsx_chart_pop_color_state (state, XLSX_CS_FONT);
142 static void
143 xlsx_chart_text_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
145 XLSXReadState *state = (XLSXReadState *)xin->user_state;
146 if (!GOG_IS_LABEL (state->cur_obj) && GNM_IS_SO_GRAPH (state->so) && NULL == state->series) { /* Hmm, why? */
147 xlsx_push_text_object (state, "Label");
151 static void
152 xlsx_chart_text (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
154 XLSXReadState *state = (XLSXReadState *)xin->user_state;
156 if (GNM_IS_SO_FILLED (state->so))
157 g_object_set (G_OBJECT (state->so), "text", state->chart_tx, NULL);
158 else if (NULL == state->series) {
159 if (GOG_IS_LABEL (state->cur_obj)) {
160 if (state->chart_tx) {
161 GnmValue *value = value_new_string_nocopy (state->chart_tx);
162 GnmExprTop const *texpr = gnm_expr_top_new_constant (value);
163 gog_dataset_set_dim (GOG_DATASET (state->cur_obj), 0,
164 gnm_go_data_scalar_new_expr (state->sheet, texpr), NULL);
165 state->chart_tx = NULL;
166 } else if (state->texpr) {
167 gog_dataset_set_dim (GOG_DATASET (state->cur_obj), 0,
168 gnm_go_data_scalar_new_expr (state->sheet, state->texpr), NULL);
169 state->texpr = NULL;
171 if (go_finite (state->chart_pos[0])) {
172 GogViewAllocation alloc;
173 alloc.x = state->chart_pos[0];
174 alloc.w = state->chart_pos[1] - alloc.x;
175 alloc.y = state->chart_pos[2];
176 alloc.h = state->chart_pos[3] - alloc.y;
177 xlsx_reset_chart_pos (state);
178 gog_object_set_position_flags (state->cur_obj, GOG_POSITION_MANUAL, GOG_POSITION_ANY_MANUAL);
179 gog_object_set_manual_position (state->cur_obj, &alloc);
181 if (!state->inhibit_text_pop)
182 xlsx_chart_pop_obj (state);
185 g_free (state->chart_tx);
186 state->chart_tx = NULL;
187 state->sp_type &= ~GO_STYLE_FONT;
190 static void
191 xlsx_chart_title_start (GsfXMLIn *xin, xmlChar const **attrs)
193 XLSXReadState *state = (XLSXReadState *)xin->user_state;
195 if (state->cur_obj == (GogObject *)state->chart) {
196 xlsx_push_text_object (state, "Title");
197 } else {
198 xlsx_push_text_object (state, "Label");
200 state->inhibit_text_pop = TRUE;
201 state->sp_type |= GO_STYLE_LINE;
204 static void
205 xlsx_chart_title_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
207 XLSXReadState *state = (XLSXReadState *)xin->user_state;
208 state->inhibit_text_pop = FALSE;
209 if (GOG_IS_CHART (state->cur_obj)) {
210 xlsx_chart_text (xin, blob);
211 } else {
212 xlsx_chart_pop_obj (state);
214 state->sp_type &= ~GO_STYLE_LINE;
218 static void
219 xlsx_chart_p_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
221 XLSXReadState *state = (XLSXReadState *)xin->user_state;
222 if (state->texpr)
223 return;
224 if (state->chart_tx) {
225 char *buf = g_strconcat (state->chart_tx, "\n", NULL);
226 g_free (state->chart_tx);
227 state->chart_tx = buf;
231 static void
232 xlsx_chart_text_content (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
234 XLSXReadState *state = (XLSXReadState *)xin->user_state;
235 /* a rich node can contain several t children, if this happens, concatenate
236 the contents */
237 if (state->texpr)
238 return;
239 if (*xin->content->str) {
240 if (state->chart_tx) {
241 char *buf = g_strconcat (state->chart_tx, xin->content->str, NULL);
242 g_free (state->chart_tx);
243 state->chart_tx = buf;
244 } else
245 state->chart_tx = g_strdup (xin->content->str);
249 static void
250 xlsx_draw_text_run_props (GsfXMLIn *xin, xmlChar const **attrs)
252 XLSXReadState *state = (XLSXReadState *)xin->user_state;
253 PangoFontDescription *desc;
254 GOStyle *style = state->cur_style;
255 gboolean auto_font;
257 if (!GO_IS_STYLED_OBJECT (state->cur_obj) || !style)
258 return;
260 /* FIXME: this should be for a text run, not for the full style */
262 if (style->font.font) {
263 desc = pango_font_description_copy (style->font.font->desc);
264 auto_font = style->font.auto_font;
265 } else {
266 desc = pango_font_description_new ();
267 pango_font_description_set_family (desc, "Calibri");
268 pango_font_description_set_size (desc, 10 * PANGO_SCALE);
269 auto_font = TRUE;
272 for (; attrs && *attrs; attrs += 2) {
273 int i;
274 if (attr_int (xin, attrs, "sz", &i)) {
275 int psize = i * PANGO_SCALE / 100;
276 if (psize != pango_font_description_get_size (desc)) {
277 auto_font = FALSE;
278 pango_font_description_set_size (desc, psize);
280 } else if (attr_int (xin, attrs, "b", &i)) {
281 PangoWeight pw = i ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL;
282 if (pw != pango_font_description_get_weight (desc)) {
283 pango_font_description_set_weight (desc, pw);
284 auto_font = FALSE;
286 } else if (attr_int (xin, attrs, "i", &i)) {
287 PangoStyle ps = i ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL;
288 if (ps != pango_font_description_get_style (desc)) {
289 pango_font_description_set_style (desc, ps);
290 auto_font = FALSE;
295 style->font.auto_font = auto_font;
296 if (auto_font)
297 pango_font_description_free (desc);
298 else
299 go_style_set_font (style, go_font_new_by_desc (desc));
302 static void
303 xlsx_rpr_latin (GsfXMLIn *xin, xmlChar const **attrs)
305 XLSXReadState *state = (XLSXReadState *)xin->user_state;
306 GOStyle *style = state->cur_style;
308 for (; attrs && *attrs; attrs += 2) {
309 if (strcmp (attrs[0], "typeface") == 0) {
310 PangoFontDescription *desc = pango_font_description_copy (style->font.font->desc);
311 pango_font_description_set_family (desc, attrs[1]);
312 style->font.auto_font = FALSE;
313 go_style_set_font (style, go_font_new_by_desc (desc));
318 static void
319 xlsx_body_pr (GsfXMLIn *xin, xmlChar const **attrs)
321 XLSXReadState *state = (XLSXReadState *)xin->user_state;
322 static EnumVal const wrap_types[] = {
323 { "none", 0 },
324 { "square", 1 },
325 { NULL, 0 }
328 if (GO_IS_STYLED_OBJECT (state->cur_obj) && state->cur_style) {
329 for (; attrs && *attrs; attrs += 2) {
330 int val;
332 if (attr_enum (xin, attrs, "wrap", wrap_types, &val)) {
333 g_object_set (state->cur_obj, "allow-wrap", val, NULL);
334 } else if (!strcmp (attrs[0], "rot")) {
335 /* FIXME: be careful if the "vert" property exists (not yet supported) */
336 int rotation;
337 if (attr_int (xin, attrs, "rot", &rotation)) {
338 state->cur_style->text_layout.auto_angle = FALSE;
339 state->cur_style->text_layout.angle = -rotation / 60000.0;
346 /*****************************************************************************
347 * User shapes *
348 *****************************************************************************/
350 static void
351 xlsx_rel_size_anchor_start (G_GNUC_UNUSED GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
355 static void
356 xlsx_rel_size_anchor (G_GNUC_UNUSED GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
360 static void
361 xlsx_user_shape_pos (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
363 XLSXReadState *state = (XLSXReadState *)xin->user_state;
364 char *end;
365 double tmp = gnm_strto (xin->content->str, &end);
366 if (*end) {
367 xlsx_warning (xin,
368 _("Invalid number '%s' for node %s"),
369 xin->content->str, xin->node->name);
370 return;
372 state->chart_pos[xin->node->user_data.v_int] = tmp;
375 static void
376 xlsx_user_shape (GsfXMLIn *xin, xmlChar const **attrs)
378 XLSXReadState *state = (XLSXReadState *)xin->user_state;
380 for (; *attrs; attrs += 2)
381 if (!strcmp (attrs[0], "textlink") && *attrs[1]) {
382 GnmParsePos pp;
383 state->texpr = xlsx_parse_expr (xin, attrs[1],
384 parse_pos_init_sheet (&pp, state->sheet));
388 static void
389 xlsx_user_shape_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
391 XLSXReadState *state = (XLSXReadState *)xin->user_state;
392 if (state->texpr) {
393 /* this should not happen if we import everything */
394 g_warning ("unused expression %p.",state->texpr);
395 gnm_expr_top_unref (state->texpr);
396 state->texpr = NULL;
401 static void
402 xlsx_sppr_xfrm (GsfXMLIn *xin, xmlChar const **attrs)
404 XLSXReadState *state = (XLSXReadState *)xin->user_state;
405 int rot = 0, flipH = 0, flipV = 0;
407 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
408 if (attr_int (xin, attrs, "rot", &rot) ||
409 attr_bool (xin, attrs, "flipH", &flipH) ||
410 attr_bool (xin, attrs, "flipV", &flipV))
411 ; /* Nothing */
414 rot = rot % (360 * 60000);
415 if (rot < 0) rot += 360 * 60000;
417 if (state->marker) {
418 if (go_marker_get_shape (state->marker) == GO_MARKER_TRIANGLE_UP) {
419 switch ((rot + 45 * 60000) / (90 * 60000)) {
420 case 1:
421 go_marker_set_shape (state->marker, GO_MARKER_TRIANGLE_RIGHT);
422 break;
423 case 2:
424 go_marker_set_shape (state->marker, GO_MARKER_TRIANGLE_DOWN);
425 break;
426 case 3:
427 go_marker_set_shape (state->marker, GO_MARKER_TRIANGLE_LEFT);
428 break;
429 default:
430 break;
434 if (flipH) {
435 if (go_marker_get_shape (state->marker) == GO_MARKER_HALF_BAR) {
436 go_marker_set_shape (state->marker, GO_MARKER_LEFT_HALF_BAR);
439 return;
442 if (flipH)
443 state->so_direction ^= GOD_ANCHOR_DIR_RIGHT;
444 if (flipV)
445 state->so_direction ^= GOD_ANCHOR_DIR_DOWN;
449 static GsfXMLInNode const xlsx_chart_drawing_dtd[] =
451 GSF_XML_IN_NODE_FULL (START, START, -1, NULL, GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
452 GSF_XML_IN_NODE_FULL (START, USER_SHAPES, XL_NS_CHART, "userShapes", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
453 GSF_XML_IN_NODE (USER_SHAPES, REL_SIZE_ANCHOR, XL_NS_CHART_DRAW, "relSizeAnchor", GSF_XML_NO_CONTENT, &xlsx_rel_size_anchor_start, &xlsx_rel_size_anchor),
454 GSF_XML_IN_NODE (REL_SIZE_ANCHOR, FROM, XL_NS_CHART_DRAW, "from", GSF_XML_NO_CONTENT, NULL, NULL),
455 GSF_XML_IN_NODE_FULL (FROM, FROM_X, XL_NS_CHART_DRAW, "x", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_user_shape_pos, 0),
456 GSF_XML_IN_NODE_FULL (FROM, FROM_Y, XL_NS_CHART_DRAW, "y", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_user_shape_pos, 2),
457 GSF_XML_IN_NODE (REL_SIZE_ANCHOR, TO, XL_NS_CHART_DRAW, "to", GSF_XML_NO_CONTENT, NULL, NULL),
458 GSF_XML_IN_NODE_FULL (TO, TO_X, XL_NS_CHART_DRAW, "x", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_user_shape_pos, 1),
459 GSF_XML_IN_NODE_FULL (TO, TO_Y, XL_NS_CHART_DRAW, "y", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_user_shape_pos, 3),
460 GSF_XML_IN_NODE (REL_SIZE_ANCHOR, SHAPE, XL_NS_CHART_DRAW, "sp", GSF_XML_NO_CONTENT, &xlsx_user_shape, &xlsx_user_shape_end),
461 GSF_XML_IN_NODE (SHAPE, NV_SP_PR, XL_NS_CHART_DRAW, "nvSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
462 GSF_XML_IN_NODE (NV_SP_PR, C_NV_PR, XL_NS_CHART_DRAW, "cNvPr", GSF_XML_NO_CONTENT, NULL, NULL),
463 GSF_XML_IN_NODE (NV_SP_PR, C_NV_SP_PR, XL_NS_CHART_DRAW, "cNvSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
464 GSF_XML_IN_NODE_FULL (SHAPE, SHAPE_PR, XL_NS_CHART_DRAW, "spPr", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
465 GSF_XML_IN_NODE (SHAPE_PR, SP_PR_PRST_GEOM, XL_NS_DRAW, "prstGeom", GSF_XML_NO_CONTENT, NULL, NULL),
466 GSF_XML_IN_NODE (SP_PR_PRST_GEOM, AV_LST, XL_NS_DRAW, "avLst", GSF_XML_NO_CONTENT, NULL, NULL),
467 GSF_XML_IN_NODE (SHAPE_PR, SP_PR_XFRM, XL_NS_DRAW, "xfrm", GSF_XML_NO_CONTENT, &xlsx_sppr_xfrm, NULL),
468 GSF_XML_IN_NODE (SP_PR_XFRM, SP_XFRM_OFF, XL_NS_DRAW, "off", GSF_XML_NO_CONTENT, NULL, NULL),
469 GSF_XML_IN_NODE (SP_PR_XFRM, SP_XFRM_EXT, XL_NS_DRAW, "ext", GSF_XML_NO_CONTENT, NULL, NULL),
470 GSF_XML_IN_NODE (SHAPE_PR, FILL_GRAD, XL_NS_DRAW, "gradFill", GSF_XML_NO_CONTENT, NULL, NULL),
471 GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIST, XL_NS_DRAW, "gsLst", GSF_XML_NO_CONTENT, NULL, NULL),
472 GSF_XML_IN_NODE (GRAD_LIST, GRAD_LIST_ITEM, XL_NS_DRAW, "gs", GSF_XML_NO_CONTENT, NULL, NULL),
473 GSF_XML_IN_NODE (GRAD_LIST_ITEM, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL),
474 GSF_XML_IN_NODE (GRAD_LIST_ITEM, COLOR_SYS, XL_NS_DRAW, "sysClr", GSF_XML_NO_CONTENT, NULL, NULL),
475 GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIN, XL_NS_DRAW, "lin", GSF_XML_NO_CONTENT, NULL, NULL),
476 GSF_XML_IN_NODE (FILL_GRAD, GRAD_TILE, XL_NS_DRAW, "tileRect", GSF_XML_NO_CONTENT, NULL, NULL),
477 GSF_XML_IN_NODE (SHAPE, TX_BODY, XL_NS_CHART_DRAW, "txBody", GSF_XML_NO_CONTENT, NULL, NULL),
478 GSF_XML_IN_NODE (TX_BODY, LST_STYLE, XL_NS_DRAW, "lstStyle", GSF_XML_NO_CONTENT, NULL, NULL),
479 GSF_XML_IN_NODE (LST_STYLE, DEF_P_PR, XL_NS_DRAW, "defPPr", GSF_XML_NO_CONTENT, NULL, NULL),
480 GSF_XML_IN_NODE (LST_STYLE, EXTLST, XL_NS_DRAW, "extLst", GSF_XML_NO_CONTENT, NULL, NULL),
481 GSF_XML_IN_NODE (LST_STYLE, LVL1_P_PR, XL_NS_DRAW, "lvl1pPr", GSF_XML_NO_CONTENT, NULL, NULL),
482 GSF_XML_IN_NODE (LVL1_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
483 GSF_XML_IN_NODE (DEF_R_PR, CS, XL_NS_DRAW, "cs", GSF_XML_NO_CONTENT, NULL, NULL),
484 GSF_XML_IN_NODE (DEF_R_PR, EA, XL_NS_DRAW, "ea", GSF_XML_NO_CONTENT, NULL, NULL),
485 GSF_XML_IN_NODE (DEF_R_PR, LATIN, XL_NS_DRAW, "latin", GSF_XML_NO_CONTENT, NULL, NULL),
486 GSF_XML_IN_NODE (LST_STYLE, LVL2_P_PR, XL_NS_DRAW, "lvl2pPr", GSF_XML_NO_CONTENT, NULL, NULL),
487 GSF_XML_IN_NODE (LVL2_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
488 GSF_XML_IN_NODE (LST_STYLE, LVL3_P_PR, XL_NS_DRAW, "lvl3pPr", GSF_XML_NO_CONTENT, NULL, NULL),
489 GSF_XML_IN_NODE (LVL3_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
490 GSF_XML_IN_NODE (LST_STYLE, LVL4_P_PR, XL_NS_DRAW, "lvl4pPr", GSF_XML_NO_CONTENT, NULL, NULL),
491 GSF_XML_IN_NODE (LVL4_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
492 GSF_XML_IN_NODE (LST_STYLE, LVL5_P_PR, XL_NS_DRAW, "lvl5pPr", GSF_XML_NO_CONTENT, NULL, NULL),
493 GSF_XML_IN_NODE (LVL5_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
494 GSF_XML_IN_NODE (LST_STYLE, LVL6_P_PR, XL_NS_DRAW, "lvl6pPr", GSF_XML_NO_CONTENT, NULL, NULL),
495 GSF_XML_IN_NODE (LVL6_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
496 GSF_XML_IN_NODE (LST_STYLE, LVL7_P_PR, XL_NS_DRAW, "lvl7pPr", GSF_XML_NO_CONTENT, NULL, NULL),
497 GSF_XML_IN_NODE (LVL7_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
498 GSF_XML_IN_NODE (LST_STYLE, LVL8_P_PR, XL_NS_DRAW, "lvl8pPr", GSF_XML_NO_CONTENT, NULL, NULL),
499 GSF_XML_IN_NODE (LVL8_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
500 GSF_XML_IN_NODE (LST_STYLE, LVL9_P_PR, XL_NS_DRAW, "lvl9pPr", GSF_XML_NO_CONTENT, NULL, NULL),
501 GSF_XML_IN_NODE (LVL9_P_PR, DEF_R_PR, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
502 GSF_XML_IN_NODE (TX_BODY, TX_BODY_PR, XL_NS_DRAW, "bodyPr", GSF_XML_NO_CONTENT, NULL, NULL),
503 GSF_XML_IN_NODE (TX_BODY, TEXT_PR_P, XL_NS_DRAW, "p", GSF_XML_NO_CONTENT, &xlsx_chart_p_start, NULL),
504 GSF_XML_IN_NODE (TEXT_PR_P, TX_RICH_FLD, XL_NS_DRAW, "fld", GSF_XML_NO_CONTENT, NULL, NULL),
505 GSF_XML_IN_NODE (TX_RICH_FLD, TX_RICH_R_PR, XL_NS_DRAW, "rPr", GSF_XML_NO_CONTENT, &xlsx_draw_text_run_props, NULL),
506 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_CS, XL_NS_DRAW, "cs", GSF_XML_NO_CONTENT, NULL, NULL),
507 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_EA, XL_NS_DRAW, "ea", GSF_XML_NO_CONTENT, NULL, NULL),
508 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_LATIN, XL_NS_DRAW, "latin", GSF_XML_NO_CONTENT, NULL, NULL),
509 GSF_XML_IN_NODE (TX_RICH_R_PR, TEXT_FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL),
510 GSF_XML_IN_NODE (TEXT_FILL_SOLID, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL),
511 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_UFILLTX, XL_NS_DRAW, "uFillTx", GSF_XML_NO_CONTENT, NULL, NULL),
512 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_ULNTX, XL_NS_DRAW, "uLnTx", GSF_XML_NO_CONTENT, NULL, NULL),
513 GSF_XML_IN_NODE (TX_RICH_FLD, PR_P_PR, XL_NS_DRAW, "pPr", GSF_XML_NO_CONTENT, NULL, NULL),
514 GSF_XML_IN_NODE (PR_P_PR, PR_P_PR_DEF, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
515 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_CS, XL_NS_DRAW, "cs", GSF_XML_NO_CONTENT, NULL, NULL),
516 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_EA, XL_NS_DRAW, "ea", GSF_XML_NO_CONTENT, NULL, NULL),
517 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_LATIN, XL_NS_DRAW, "latin", GSF_XML_NO_CONTENT, NULL, NULL),
518 GSF_XML_IN_NODE (PR_P_PR_DEF, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL),
519 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_UFILLTX, XL_NS_DRAW, "uFillTx", GSF_XML_NO_CONTENT, NULL, NULL),
520 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_ULNTX, XL_NS_DRAW, "uLnTx", GSF_XML_NO_CONTENT, NULL, NULL),
521 GSF_XML_IN_NODE (TX_RICH_FLD, TX_RICH_R_T, XL_NS_DRAW, "t", GSF_XML_CONTENT, NULL, &xlsx_chart_text_content),
522 GSF_XML_IN_NODE (TEXT_PR_P, TX_RICH_R, XL_NS_DRAW, "r", GSF_XML_NO_CONTENT, NULL, NULL),
523 GSF_XML_IN_NODE (TX_RICH_R, TX_RICH_R_PR, XL_NS_DRAW, "rPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
524 GSF_XML_IN_NODE (TX_RICH_R, TX_RICH_R_T, XL_NS_DRAW, "t", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
525 GSF_XML_IN_NODE (TEXT_PR_P, PR_P_PR, XL_NS_DRAW, "pPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
526 GSF_XML_IN_NODE (TEXT_PR_P, PR_P_PR_END,XL_NS_DRAW, "endParaRPr", GSF_XML_NO_CONTENT, NULL, NULL),
527 GSF_XML_IN_NODE (TEXT_PR_P, TX_RICH_R_T, XL_NS_DRAW, "t", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
528 GSF_XML_IN_NODE_END
531 static void
532 xlsx_chart_user_shapes (GsfXMLIn *xin, xmlChar const **attrs)
534 xmlChar const *part_id = NULL;
536 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
537 if (gsf_xml_in_namecmp (xin, attrs[0], XL_NS_DOC_REL, "id"))
538 part_id = attrs[1];
539 if (NULL != part_id) {
540 xlsx_parse_rel_by_id (xin, part_id, xlsx_chart_drawing_dtd, xlsx_ns);
544 /*****************************************************************************/
546 static void
547 xlsx_chart_add_plot (GsfXMLIn *xin, char const *type)
549 XLSXReadState *state = (XLSXReadState *)xin->user_state;
550 if (NULL != (state->plot = (GogPlot*) gog_plot_new_by_name (type)))
551 /* Add _before_ setting styles so theme does not override */
552 gog_object_add_by_name (GOG_OBJECT (state->chart),
553 "Plot", GOG_OBJECT (state->plot));
556 /* shared with pie of pie, and bar of pie */
557 static void
558 xlsx_vary_colors (GsfXMLIn *xin, xmlChar const **attrs)
560 XLSXReadState *state = (XLSXReadState *)xin->user_state;
561 int vary = TRUE; /* A somewhat crazy default */
562 (void)simple_bool (xin, attrs, &vary);
563 g_object_set (G_OBJECT (state->plot), "vary-style-by-element", vary, NULL);
566 static void
567 xlsx_chart_pie_sep (GsfXMLIn *xin, xmlChar const **attrs)
569 XLSXReadState *state = (XLSXReadState *)xin->user_state;
570 unsigned sep = 0;
571 (void)simple_uint (xin, attrs, &sep);
572 g_object_set (G_OBJECT (state->plot),
573 "default-separation", (double)(CLAMP (sep, 0u, 500u)) / 100.0, NULL);
576 /* shared with pie of pie, and bar of pie */
577 static void xlsx_chart_pie (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs) { xlsx_chart_add_plot (xin, "GogPiePlot"); }
578 static void xlsx_chart_ring (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs) { xlsx_chart_add_plot (xin, "GogRingPlot"); }
580 /***********************************************************************/
582 static void
583 xlsx_chart_bar_dir (GsfXMLIn *xin, xmlChar const **attrs)
585 static const EnumVal const dirs[] = {
586 { "bar", TRUE },
587 { "col", FALSE },
588 { NULL, 0 }
590 XLSXReadState *state = (XLSXReadState *)xin->user_state;
591 int dir = FALSE;
593 g_return_if_fail (state->plot != NULL);
595 (void)simple_enum (xin, attrs, dirs, &dir);
596 g_object_set (G_OBJECT (state->plot), "horizontal", dir, NULL);
599 static void
600 xlsx_chart_bar_overlap (GsfXMLIn *xin, xmlChar const **attrs)
602 XLSXReadState *state = (XLSXReadState *)xin->user_state;
603 const char *soverlap = simple_string (xin, attrs);
604 if (soverlap) {
605 /* Spec says add "%" at end; XL cannot handle that. */
606 int overlap = strtol (soverlap, NULL, 10);
607 g_object_set (G_OBJECT (state->plot),
608 "overlap-percentage", CLAMP (overlap, -100, 100),
609 NULL);
613 static void
614 xlsx_chart_bar_group (GsfXMLIn *xin, xmlChar const **attrs)
616 XLSXReadState *state = (XLSXReadState *)xin->user_state;
617 static const EnumVal const grps[] = {
618 { "percentStacked", 0 },
619 { "clustered", 1 },
620 { "standard", 2 },
621 { "stacked", 3 },
622 { NULL, 0 }
624 static const char *types[] = { "as_percentage", "normal", "normal", "stacked" };
625 int grp = 1;
627 g_return_if_fail (state->plot != NULL);
629 (void)simple_enum (xin, attrs, grps, &grp);
630 g_object_set (G_OBJECT (state->plot), "type", types[grp], NULL);
633 static void
634 xlsx_chart_bar_gap (GsfXMLIn *xin, xmlChar const **attrs)
636 XLSXReadState *state = (XLSXReadState *)xin->user_state;
637 const char *sgap = simple_string (xin, attrs);
638 if (sgap) {
639 /* Spec says add "%" at end; XL cannot handle that. */
640 int gap = strtol (sgap, NULL, 10);
641 g_object_set (G_OBJECT (state->plot),
642 "gap-percentage", CLAMP (gap, 0, 500), NULL);
646 static void
647 xlsx_chart_bar (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
649 xlsx_chart_add_plot (xin, "GogBarColPlot");
652 /***********************************************************************/
654 static void
655 xlsx_axis_info_free (XLSXAxisInfo *info)
657 g_free (info->id);
658 g_free (info->cross_id);
659 if (NULL != info->axis)
660 g_object_unref (info->axis);
661 g_slist_free (info->plots);
662 g_free (info);
665 static void
666 xlsx_plot_axis_id (GsfXMLIn *xin, xmlChar const **attrs)
668 XLSXReadState *state = (XLSXReadState *)xin->user_state;
669 const char *axid = simple_string (xin, attrs);
670 XLSXAxisInfo *res;
672 if (!state->plot || !axid)
673 return;
675 res = g_hash_table_lookup (state->axis.by_id, axid);
676 if (NULL == res) {
677 res = g_new0 (XLSXAxisInfo, 1);
678 res->id = g_strdup (axid);
679 res->axis = NULL;
680 res->plots = NULL;
681 res->type = XLSX_AXIS_UNKNOWN;
682 res->compass = GOG_POSITION_AUTO;
683 res->cross = GOG_AXIS_CROSS;
684 res->cross_value = go_nan;
685 res->invert_axis = FALSE;
686 res->logbase = 0;
687 g_hash_table_replace (state->axis.by_id, res->id, res);
688 #ifdef DEBUG_AXIS
689 g_printerr ("create info for %s = %p\n", res->id, res);
690 #endif
693 #ifdef DEBUG_AXIS
694 g_printerr ("add plot %p to info %p\n", state->plot, res);
695 #endif
696 res->plots = g_slist_prepend (res->plots, state->plot);
699 static void
700 xlsx_axis_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
702 XLSXReadState *state = (XLSXReadState *)xin->user_state;
703 state->axis.obj = NULL;
704 state->axis.type = xin->node->user_data.v_int;
705 state->axis.info = NULL;
707 /* Push dummy object for now until we can deduce the role. */
708 xlsx_chart_push_obj (state, NULL);
709 #ifdef DEBUG_AXIS
710 g_printerr ("Create NULL object for axis\n");
711 #endif
714 static void
715 xlsx_axis_crosses_at (GsfXMLIn *xin, xmlChar const **attrs)
717 /* This element specifies where on the axis the perpendicular axis crosses.
718 The units are dependent on the type of axis.
719 When specified as a child element of valAx, the value is a decimal number on the value axis. When specified as a
720 child element of dateAx, the date is defined as a integer number of days relative to the base date of the current
721 date base. When specified as a child element of catAx, the value is an integer category number, starting with 1
722 as the first category.
724 XLSXReadState *state = (XLSXReadState *)xin->user_state;
726 g_return_if_fail (state->axis.info != NULL);
728 simple_float (xin, attrs, &state->axis.info->cross_value);
731 static void
732 xlsx_axis_id (GsfXMLIn *xin, xmlChar const **attrs)
734 XLSXReadState *state = (XLSXReadState *)xin->user_state;
735 const char *axid = simple_string (xin, attrs);
736 if (axid) {
737 state->axis.info = g_hash_table_lookup (state->axis.by_id, axid);
738 #ifdef DEBUG_AXIS
739 g_printerr ("define %s = %p\n", axid, state->axis.info);
740 #endif
744 static void
745 xlsx_axis_delete (GsfXMLIn *xin, xmlChar const **attrs)
747 XLSXReadState *state = (XLSXReadState *)xin->user_state;
748 int del = TRUE; /* A crazy default */
749 (void)simple_bool (xin, attrs, &del);
750 if (state->axis.info)
751 state->axis.info->deleted = del;
754 static void
755 xlsx_axis_orientation (GsfXMLIn *xin, xmlChar const **attrs)
757 static const EnumVal const orients[] = {
758 { "minMax", FALSE },
759 { "maxMin", TRUE },
760 { NULL, 0 }
762 XLSXReadState *state = (XLSXReadState *)xin->user_state;
763 int orient = FALSE;
765 (void)simple_enum (xin, attrs, orients, &orient);
766 if (state->axis.info)
767 state->axis.info->invert_axis = orient;
770 static void
771 xlsx_axis_format (GsfXMLIn *xin, xmlChar const **attrs)
773 XLSXReadState *state = (XLSXReadState *)xin->user_state;
774 gboolean shared = TRUE;
775 char const *fmt = NULL;
776 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
777 if (0 == strcmp (attrs[0], "sourceLinked"))
778 attr_bool (xin, attrs, "sourceLinked", &shared);
779 else if (0 == strcmp (attrs[0], "formatCode"))
780 fmt = attrs[1];
781 if (fmt && !shared)
782 g_object_set (G_OBJECT (state->axis.obj),
783 "assigned-format-string-XL", fmt, NULL);
785 static void
786 xlsx_chart_logbase (GsfXMLIn *xin, xmlChar const **attrs)
788 XLSXReadState *state = (XLSXReadState *)xin->user_state;
789 gnm_float base;
792 * The documented limits are 2-1000. The example uses 1.0. *Sigh*
793 * We choose to ignore a base outside the limits rather than clamping
794 * and pretending it makes sense. (That's not to say that we currently
795 * do anything useful with it even if it is in range.)
798 if (state->axis.info &&
799 simple_float (xin, attrs, &base) &&
800 base >= 2 && base <= 1000)
801 state->axis.info->logbase = base;
804 /* See bug 743347 for discussion. */
805 static void
806 xlsx_create_axis_object (XLSXReadState *state)
808 GogPlot *plot;
809 char const *type;
810 char const *role = NULL;
811 gboolean inverted = FALSE;
812 gboolean cat_or_date = (state->axis.type == XLSX_AXIS_CAT ||
813 state->axis.type == XLSX_AXIS_DATE);
814 GogObject *axis;
815 gboolean dummy;
817 if (state->cur_obj)
818 return;
820 if (state->axis.info && state->axis.info->axis) {
821 axis = GOG_OBJECT (state->axis.obj = state->axis.info->axis);
822 /* Replace dummy object. */
823 xlsx_chart_pop_obj (state);
824 xlsx_chart_push_obj (state, axis);
825 #ifdef DEBUG_AXIS
826 g_printerr ("Re-using axis object %s with role %s\n",
827 gog_object_get_name (axis), role);
828 #endif
829 return;
832 dummy = (!state->axis.info || !state->axis.info->plots);
833 if (dummy) {
834 plot = NULL;
835 type = "GogLinePlot";
836 } else {
837 plot = state->axis.info->plots->data; /* just use the first */
838 type = G_OBJECT_TYPE_NAME (plot);
841 switch (xlsx_plottype_from_type_name (type)) {
842 case XLSX_PT_GOGRADARPLOT:
843 case XLSX_PT_GOGRADARAREAPLOT:
844 role = cat_or_date ? "Circular-Axis" : "Radial-Axis";
845 break;
846 case XLSX_PT_GOGBUBBLEPLOT:
847 case XLSX_PT_GOGXYPLOT:
848 if (state->axis.info->compass == GOG_POSITION_N ||
849 state->axis.info->compass == GOG_POSITION_S)
850 role = "X-Axis";
851 else
852 role = "Y-Axis";
853 break;
854 case XLSX_PT_GOGBARCOLPLOT:
855 /* swap for bar plots */
856 g_object_get (G_OBJECT (plot), "horizontal", &inverted, NULL);
857 break;
859 default:
860 break;
863 if (NULL == role)
864 role = (inverted ^ cat_or_date) ? "X-Axis" : "Y-Axis";
866 axis = gog_object_add_by_name (GOG_OBJECT (state->chart), role, NULL);
867 state->axis.obj = GOG_AXIS (axis);
868 #ifdef DEBUG_AXIS
869 g_printerr ("Created axis object %s with role %s\n",
870 gog_object_get_name (axis), role);
871 #endif
873 /* Replace dummy object. */
874 xlsx_chart_pop_obj (state);
875 xlsx_chart_push_obj (state, axis);
877 if (dummy)
878 g_object_set (axis, "invisible", TRUE, NULL);
880 if (state->axis.info) {
881 if (dummy)
882 state->axis.info->deleted = TRUE;
883 state->axis.info->axis = g_object_ref (state->axis.obj);
884 g_hash_table_replace (state->axis.by_obj, axis, state->axis.info);
886 g_object_set (G_OBJECT (state->axis.obj),
887 "invisible", state->axis.info->deleted,
888 "invert-axis", state->axis.info->invert_axis, NULL);
890 if (state->axis.info->logbase > 0) {
891 g_object_set (G_OBJECT (state->axis.obj),
892 "map-name", "Log",
893 NULL);
894 /* Base? */
900 static void
901 xlsx_axis_pos (GsfXMLIn *xin, xmlChar const **attrs)
903 static const EnumVal const positions[] = {
904 { "t", GOG_POSITION_N },
905 { "b", GOG_POSITION_S },
906 { "l", GOG_POSITION_W },
907 { "r", GOG_POSITION_E },
908 { NULL, 0 }
910 XLSXReadState *state = (XLSXReadState *)xin->user_state;
911 int position = GOG_POSITION_AUTO;
913 #ifdef DEBUG_AXIS
914 g_printerr ("SET POS %s for %p\n", simple_string (xin, attrs), state->axis.info);
915 #endif
916 /* Apparently no default value. */
917 (void)simple_enum (xin, attrs, positions, &position);
918 if (state->axis.info)
919 state->axis.info->compass = position;
921 if (state->axis.obj == NULL)
922 xlsx_create_axis_object (state);
925 static void
926 xlsx_axis_bound (GsfXMLIn *xin, xmlChar const **attrs)
928 XLSXReadState *state = (XLSXReadState *)xin->user_state;
929 gnm_float val;
930 GogAxisElemType et = xin->node->user_data.v_int;
932 if (state->axis.info && simple_float (xin, attrs, &val)) {
933 state->axis.info->axis_elements[et] = val;
934 state->axis.info->axis_element_set[et] = TRUE;
938 static void
939 xlsx_axis_crosses (GsfXMLIn *xin, xmlChar const **attrs)
941 static const EnumVal const crosses[] = {
942 { "autoZero", GOG_AXIS_CROSS },
943 { "max", GOG_AXIS_AT_HIGH },
944 { "min", GOG_AXIS_AT_LOW },
945 { NULL, 0 }
947 XLSXReadState *state = (XLSXReadState *)xin->user_state;
948 int cross = GOG_AXIS_CROSS;
950 /* No explicit default in docs -- assuming autoZero. */
951 (void)simple_enum (xin, attrs, crosses, &cross);
953 if (state->axis.info) {
954 state->axis.info->cross = cross;
955 if (cross == GOG_AXIS_CROSS)
956 state->axis.info->cross_value = 0.;
960 static void
961 xlsx_axis_crossax (GsfXMLIn *xin, xmlChar const **attrs)
963 XLSXReadState *state = (XLSXReadState *)xin->user_state;
964 const char *axid = simple_string (xin, attrs);
965 if (state->axis.info && axid)
966 state->axis.info->cross_id = g_strdup (axid);
969 static void
970 xlsx_chart_gridlines (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
972 XLSXReadState *state = (XLSXReadState *)xin->user_state;
973 gboolean ismajor = xin->node->user_data.v_int;
974 GogObject *grid = gog_object_add_by_name
975 (GOG_OBJECT (state->axis.obj),
976 ismajor ? "MajorGrid" : "MinorGrid",
977 NULL);
978 xlsx_chart_push_obj (state, grid);
981 static void
982 xlsx_axis_mark (GsfXMLIn *xin, xmlChar const **attrs)
984 XLSXReadState *state = (XLSXReadState *)xin->user_state;
985 gboolean ismajor = xin->node->user_data.v_int;
986 static const EnumVal marks[] = {
987 {"none", 0},
988 {"in", 1},
989 {"out", 2},
990 {"cross", 3},
992 int res = 3;
994 (void)simple_enum (xin, attrs, marks, &res);
995 g_object_set (G_OBJECT (state->axis.obj),
996 (ismajor ? "major-tick-in" : "minor-tick-in"), (res & 1) != 0,
997 (ismajor ? "major-tick-out" : "minor-tick-out"), (res & 2) != 0,
998 NULL);
1001 static void
1002 xslx_chart_tick_label_pos (GsfXMLIn *xin, xmlChar const **attrs)
1004 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1005 static const EnumVal positions[] = {
1006 {"high", 0},
1007 {"low", 1},
1008 {"nextTo", 2},
1009 {"none", 3},
1011 int res = 2;
1013 (void)simple_enum (xin, attrs, positions, &res);
1014 g_object_set (G_OBJECT (state->axis.obj), "major-tick-labeled", res != 3, NULL);
1017 static void
1018 xlsx_axis_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1020 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1021 GogAxis *axis = state->axis.obj;
1023 if (state->axis.info) {
1024 GSList *ptr;
1025 GogAxisElemType et;
1026 XLSXAxisInfo *info = state->axis.info;
1028 /* Apply pending attributes. */
1030 for (et = GOG_AXIS_ELEM_MIN; et < GOG_AXIS_ELEM_MAX_ENTRY; et++) {
1031 if (info->axis_element_set[et]) {
1032 double d = info->axis_elements[et];
1033 GnmExprTop const *te = gnm_expr_top_new_constant (value_new_float (d));
1034 gog_dataset_set_dim (GOG_DATASET (axis),
1036 gnm_go_data_scalar_new_expr (state->sheet, te),
1037 NULL);
1041 for (ptr = info->plots; ptr != NULL ; ptr = ptr->next) {
1042 GogPlot *plot = ptr->data;
1043 #ifdef DEBUG_AXIS
1044 g_printerr ("connect plot %p to %p\n", plot, axis);
1045 #endif
1046 gog_plot_set_axis (plot, axis);
1050 xlsx_chart_pop_obj (state);
1052 if (state->axis.info)
1053 state->axis.info = NULL;
1054 else if (axis) {
1055 if (gog_object_is_deletable (GOG_OBJECT (axis))) {
1056 #ifdef DEBUG_AXIS
1057 g_printerr ("Deleting axis %p\n", axis);
1058 #endif
1059 gog_object_clear_parent (GOG_OBJECT (axis));
1060 g_object_unref (axis);
1061 } else {
1062 #ifdef DEBUG_AXIS
1063 g_printerr ("Axis %p is not deletable\n", axis);
1064 #endif
1068 state->axis.obj = NULL;
1071 static void xlsx_chart_area (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs) { xlsx_chart_add_plot (xin, "GogAreaPlot"); }
1073 static void
1074 xlsx_chart_line (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1076 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1077 xlsx_chart_add_plot (xin, "GogLinePlot");
1078 g_object_set (G_OBJECT (state->plot), "default-style-has-markers", FALSE, NULL);
1081 static void
1082 xlsx_chart_line_marker (GsfXMLIn *xin, xmlChar const **attrs)
1084 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1085 gboolean has_marker = TRUE;
1087 (void)simple_bool (xin, attrs, &has_marker);
1088 g_object_set (G_OBJECT (state->plot),
1089 "default-style-has-markers", has_marker, NULL);
1092 static void
1093 xlsx_chart_xy (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1095 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1096 xlsx_chart_add_plot (xin, "GogXYPlot");
1097 g_object_set (G_OBJECT (state->plot), "default-style-has-fill", FALSE, NULL);
1100 static void
1101 xlsx_scatter_style (GsfXMLIn *xin, xmlChar const **attrs)
1103 enum { SCATTER_LINES = 1, SCATTER_MARKERS = 2, SCATTER_SPLINES = 4 };
1104 static const EnumVal styles[] = {
1105 {"line", SCATTER_LINES },
1106 {"lineMarker", SCATTER_LINES | SCATTER_MARKERS },
1107 {"marker", SCATTER_MARKERS },
1108 {"markers", SCATTER_MARKERS }, /* We used to write this erroneously */
1109 {"none", 0 },
1110 {"smooth", SCATTER_SPLINES },
1111 {"smoothMarker", SCATTER_SPLINES | SCATTER_MARKERS }
1113 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1114 int style = SCATTER_MARKERS;
1116 (void)simple_enum (xin, attrs, styles, &style);
1117 g_object_set (G_OBJECT (state->plot),
1118 "default-style-has-markers", (style & SCATTER_MARKERS) != 0,
1119 "default-style-has-lines", (style & SCATTER_LINES) != 0,
1120 "use-splines", (style & SCATTER_SPLINES) != 0,
1121 NULL);
1124 static void
1125 xlsx_chart_bubble (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1127 xlsx_chart_add_plot (xin, "GogBubblePlot");
1130 static void
1131 xlsx_chart_radar (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1133 xlsx_chart_add_plot (xin, "GogRadarPlot");
1137 static void
1138 xlsx_plot_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1140 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1141 state->plot = NULL;
1144 static void
1145 xlsx_chart_ser_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1147 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1148 state->series = gog_plot_new_series (state->plot);
1149 xlsx_chart_push_obj (state, GOG_OBJECT (state->series));
1152 static void
1153 xlsx_chart_ser_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1155 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1156 xlsx_chart_pop_obj (state);
1157 state->series = NULL;
1160 static void
1161 xlsx_ser_trendline_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1163 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1164 xlsx_chart_push_obj (state, NULL); /* Dummy object for now. */
1167 static void
1168 xlsx_ser_trendline_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1170 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1171 xlsx_chart_pop_obj (state);
1174 static void
1175 xlsx_ser_trendline_name (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1177 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1178 const char *name = xin->content->str;
1179 g_free (state->chart_tx);
1180 state->chart_tx = g_strdup (name);
1183 static void
1184 xlsx_ser_trendline_type (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1186 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1187 static const EnumVal styles[] = {
1188 {"exp", 0 },
1189 {"linear", 1 },
1190 {"log", 2 },
1191 {"movingAvg", 3 },
1192 {"poly", 4 },
1193 {"power", 5 }
1195 static const char *types[] = {
1196 "GogExpRegCurve", "GogLinRegCurve", "GogLogRegCurve",
1197 "GogMovingAvg", "GogPolynomRegCurve", "GogPowerRegCurve"
1199 int typ = 1;
1201 (void)simple_enum (xin, attrs, styles, &typ);
1202 state->cur_obj = GOG_OBJECT (gog_trend_line_new_by_name (types[typ]));
1203 if (state->cur_obj) {
1204 GogObject *trend =
1205 gog_object_add_by_name (GOG_OBJECT (state->series),
1206 "Trend line",
1207 state->cur_obj);
1208 if (state->chart_tx) {
1209 GOData *dat =
1210 gnm_go_data_scalar_new_expr (state->sheet,
1211 gnm_expr_top_new_constant (value_new_string (state->chart_tx)));
1212 gog_dataset_set_dim (GOG_DATASET (trend), -1, dat, NULL);
1216 g_free (state->chart_tx);
1217 state->chart_tx = NULL;
1220 static GogObject *
1221 xlsx_get_trend_eq (XLSXReadState *state)
1223 const char *role = "Equation";
1224 GogObject *eq = gog_object_get_child_by_name (state->cur_obj, role);
1226 if (!eq) {
1227 eq = gog_object_add_by_name (state->cur_obj, role, NULL);
1228 g_object_set (eq, "show-r2", FALSE, "show-eq", FALSE, NULL);
1231 return eq;
1235 static void
1236 xlsx_ser_trendline_disprsqr (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1238 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1239 gboolean disp = TRUE;
1241 (void)simple_bool (xin, attrs, &disp);
1242 g_object_set (xlsx_get_trend_eq (state), "show-r2", disp, NULL);
1245 static void
1246 xlsx_ser_trendline_dispeq (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1248 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1249 gboolean disp = TRUE;
1251 (void)simple_bool (xin, attrs, &disp);
1252 g_object_set (xlsx_get_trend_eq (state), "show-eq", disp, NULL);
1255 static void
1256 xlsx_ser_smooth (GsfXMLIn *xin, xmlChar const **attrs)
1258 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1259 gboolean smooth = TRUE;
1260 GOLineInterpolation inter;
1262 (void)simple_bool (xin, attrs, &smooth);
1263 inter = smooth ? GO_LINE_INTERPOLATION_CUBIC_SPLINE : GO_LINE_INTERPOLATION_LINEAR;
1264 g_object_set (state->cur_obj,
1265 "interpolation", go_line_interpolation_as_str (inter),
1266 NULL);
1270 static void
1271 xlsx_ser_labels_show_val (GsfXMLIn *xin, xmlChar const **attrs)
1273 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1274 gboolean has_val = TRUE;
1276 (void)simple_bool (xin, attrs, &has_val);
1277 if (GOG_IS_SERIES_LABELS (state->cur_obj) && has_val) {
1278 GogPlotDesc const *desc = gog_plot_description (state->plot);
1279 unsigned i;
1280 char *f, *new_f;
1281 g_object_get (state->cur_obj, "format", &f, NULL);
1282 /* seems that xl does not show anything else if a custom label is given */
1283 if (strstr (f, "%c") != NULL) {
1284 g_free (f);
1285 return;
1287 for (i = 0; i < desc->series.num_dim; i++)
1288 if (desc->series.dim[i].ms_type == GOG_MS_DIM_VALUES)
1289 break;
1290 if (i != desc->series.num_dim) {
1291 new_f = (f && *f)? g_strdup_printf ("%s%%s%%%d", f, i): g_strdup_printf ("%%%d", i);
1292 g_object_set (state->cur_obj, "format", new_f, NULL);
1293 g_free (new_f);
1295 g_free (f);
1299 static void
1300 xlsx_ser_labels_show_cat (GsfXMLIn *xin, xmlChar const **attrs)
1302 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1303 gboolean has_cat = TRUE;
1305 (void)simple_bool (xin, attrs, &has_cat);
1306 if (GOG_IS_SERIES_LABELS (state->cur_obj) && has_cat) {
1307 GogPlotDesc const *desc = gog_plot_description (state->plot);
1308 unsigned i;
1309 char *f, *new_f;
1310 g_object_get (state->cur_obj, "format", &f, NULL);
1311 /* seems that xl does not show anything else if a custom label is given */
1312 if (strstr (f, "%c") != NULL) {
1313 g_free (f);
1314 return;
1316 for (i = 0; i < desc->series.num_dim; i++)
1317 if (desc->series.dim[i].ms_type == GOG_MS_DIM_CATEGORIES)
1318 break;
1319 if (i != desc->series.num_dim) {
1320 new_f = (f && *f)? g_strdup_printf ("%s%%s%%%d", f, i): g_strdup_printf ("%%%d", i);
1321 g_object_set (state->cur_obj, "format", new_f, NULL);
1322 g_free (new_f);
1324 g_free (f);
1328 static void
1329 xlsx_ser_labels_pos (GsfXMLIn *xin, xmlChar const **attrs)
1331 static const EnumVal pos[] = {
1332 {"b", GOG_SERIES_LABELS_BOTTOM},
1333 {"bestFit", GOG_SERIES_LABELS_DEFAULT_POS},
1334 {"ctr", GOG_SERIES_LABELS_CENTERED},
1335 {"inBase", GOG_SERIES_LABELS_NEAR_ORIGIN},
1336 {"inEnd", GOG_SERIES_LABELS_INSIDE},
1337 {"l", GOG_SERIES_LABELS_LEFT},
1338 {"outEnd", GOG_SERIES_LABELS_OUTSIDE},
1339 {"r", GOG_SERIES_LABELS_RIGHT},
1340 {"t", GOG_SERIES_LABELS_TOP}
1342 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1343 int position = GOG_SERIES_LABELS_DEFAULT_POS;
1345 /* No documented default. */
1346 (void)simple_enum (xin, attrs, pos, &position);
1347 gog_series_labels_set_position (GOG_SERIES_LABELS (state->cur_obj), position);
1350 static void
1351 xlsx_ser_labels_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1353 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1354 GogObject *data = gog_object_add_by_name (GOG_OBJECT (state->series), "Data labels", NULL);
1355 GOData *sep = go_data_scalar_str_new (",", FALSE); /* FIXME, should be "\n" for pies */
1356 gog_dataset_set_dim (GOG_DATASET (data), 1, sep, NULL);
1357 g_object_set (data, "format", "", "offset", 3, NULL);
1358 xlsx_chart_push_obj (state, data);
1361 static void
1362 xlsx_ser_labels_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1364 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1365 if (!go_style_is_auto (state->cur_style)) {
1366 /* NOTE: this is a hack, but seems xl uses something like that */
1367 GSList *children, *ptr;
1368 children = gog_object_get_children (state->cur_obj, NULL);
1369 for (ptr = children; ptr; ptr = ptr->next)
1370 if (go_style_is_auto (go_styled_object_get_style (GO_STYLED_OBJECT (ptr->data))))
1371 g_object_set (ptr->data, "style", state->cur_style, NULL);
1372 g_slist_free (children);
1374 xlsx_chart_pop_obj (state);
1377 static void
1378 xlsx_data_label_pos (GsfXMLIn *xin, xmlChar const **attrs)
1380 static const EnumVal pos[] = {
1381 {"b", GOG_SERIES_LABELS_BOTTOM},
1382 {"bestFit", GOG_SERIES_LABELS_DEFAULT_POS},
1383 {"ctr", GOG_SERIES_LABELS_CENTERED},
1384 {"inBase", GOG_SERIES_LABELS_NEAR_ORIGIN},
1385 {"inEnd", GOG_SERIES_LABELS_INSIDE},
1386 {"l", GOG_SERIES_LABELS_LEFT},
1387 {"outEnd", GOG_SERIES_LABELS_OUTSIDE},
1388 {"r", GOG_SERIES_LABELS_RIGHT},
1389 {"t", GOG_SERIES_LABELS_TOP}
1391 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1392 int position = GOG_SERIES_LABELS_DEFAULT_POS;
1394 /* No documented default. */
1395 (void)simple_enum (xin, attrs, pos, &position);
1396 gog_data_label_set_position (GOG_DATA_LABEL (state->cur_obj), position);
1399 static void
1400 xlsx_data_label_index (GsfXMLIn *xin, xmlChar const **attrs)
1402 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1403 unsigned index;
1404 if (simple_uint (xin, attrs, &index))
1405 g_object_set (state->cur_obj, "index", index, NULL);
1408 static void
1409 xlsx_data_label_show_val (GsfXMLIn *xin, xmlChar const **attrs)
1411 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1412 gboolean has_val = TRUE;
1414 (void)simple_bool (xin, attrs, &has_val);
1415 if (GOG_IS_DATA_LABEL (state->cur_obj) && has_val) {
1416 GogPlotDesc const *desc = gog_plot_description (state->plot);
1417 unsigned i;
1418 char *f, *new_f;
1419 g_object_get (state->cur_obj, "format", &f, NULL);
1420 /* seems that xl does not show anything else if a custom label is given */
1421 if (strstr (f, "%c") != NULL) {
1422 g_free (f);
1423 return;
1425 for (i = 0; i < desc->series.num_dim; i++)
1426 if (desc->series.dim[i].ms_type == GOG_MS_DIM_VALUES)
1427 break;
1428 if (i != desc->series.num_dim) {
1429 new_f = (f && *f)? g_strdup_printf ("%s%%s%%%d", f, i): g_strdup_printf ("%%%d", i);
1430 g_object_set (state->cur_obj, "format", new_f, NULL);
1431 g_free (new_f);
1433 g_free (f);
1437 static void
1438 xlsx_data_label_show_cat (GsfXMLIn *xin, xmlChar const **attrs)
1440 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1441 gboolean has_cat = TRUE;
1443 (void)simple_bool (xin, attrs, &has_cat);
1444 if (GOG_IS_DATA_LABEL (state->cur_obj) && has_cat) {
1445 GogPlotDesc const *desc = gog_plot_description (state->plot);
1446 unsigned i;
1447 char *f, *new_f;
1448 g_object_get (state->cur_obj, "format", &f, NULL);
1449 /* seems that xl does not show anything else if a custom label is given */
1450 if (strstr (f, "%c") != NULL) {
1451 g_free (f);
1452 return;
1454 for (i = 0; i < desc->series.num_dim; i++)
1455 if (desc->series.dim[i].ms_type == GOG_MS_DIM_CATEGORIES)
1456 break;
1457 if (i != desc->series.num_dim) {
1458 new_f = (f && *f)? g_strdup_printf ("%s%%s%%%d", f, i): g_strdup_printf ("%%%d", i);
1459 g_object_set (state->cur_obj, "format", new_f, NULL);
1460 g_free (new_f);
1462 g_free (f);
1466 static void
1467 xlsx_data_label_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1469 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1470 GogObject *data = gog_object_add_by_name (state->cur_obj, "Point", NULL);
1471 GOData *sep = go_data_scalar_str_new (",", FALSE); /* FIXME, should be "\n" for pies */
1472 gog_dataset_set_dim (GOG_DATASET (data), 1, sep, NULL);
1473 g_object_set (data, "format", "", "offset", 3, NULL);
1474 xlsx_chart_push_obj (state, data);
1477 static void
1478 xlsx_chart_ser_f (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1480 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1481 if (NULL != state->series && state->cur_obj == (GogObject *) state->series) {
1482 GnmParsePos pp;
1483 GnmExprTop const *texpr = xlsx_parse_expr (xin, xin->content->str,
1484 parse_pos_init_sheet (&pp, state->sheet));
1486 gog_series_set_XL_dim (state->series, state->dim_type,
1487 ((state->dim_type != GOG_MS_DIM_LABELS)
1488 ? gnm_go_data_vector_new_expr (state->sheet, texpr)
1489 : gnm_go_data_scalar_new_expr (state->sheet, texpr)), NULL);
1490 } else if (GOG_IS_LABEL (state->cur_obj)) {
1491 GnmParsePos pp;
1492 GnmExprTop const *texpr = xlsx_parse_expr (xin, xin->content->str,
1493 parse_pos_init_sheet (&pp, state->sheet));
1495 gog_dataset_set_dim (GOG_DATASET (state->cur_obj), 0,
1496 gnm_go_data_scalar_new_expr (state->sheet, texpr), NULL);
1497 } else if (GOG_IS_SERIES_LABELS (state->cur_obj)) {
1498 GnmParsePos pp;
1499 GnmExprTop const *texpr = xlsx_parse_expr (xin, xin->content->str,
1500 parse_pos_init_sheet (&pp, state->sheet));
1501 char *new_f;
1503 gog_dataset_set_dim (GOG_DATASET (state->cur_obj), 0,
1504 gnm_go_data_vector_new_expr (state->sheet, texpr), NULL);
1505 /* seems that xl does not show anything else in that case, even if showVal is there */
1506 new_f = g_strdup ("%c");
1507 g_object_set (state->cur_obj, "format", new_f, NULL);
1508 g_free (new_f);
1509 } else if (GOG_IS_DATA_LABEL (state->cur_obj)) {
1510 GnmParsePos pp;
1511 GnmExprTop const *texpr = xlsx_parse_expr (xin, xin->content->str,
1512 parse_pos_init_sheet (&pp, state->sheet));
1513 char *new_f;
1515 gog_dataset_set_dim (GOG_DATASET (state->cur_obj), 0,
1516 gnm_go_data_scalar_new_expr (state->sheet, texpr), NULL);
1517 /* seems that xl does not show anything else in that case, even if showVal is there */
1518 new_f = g_strdup ("%c");
1519 g_object_set (state->cur_obj, "format", new_f, NULL);
1520 g_free (new_f);
1524 static void
1525 xlsx_ser_type_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1527 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1528 state->dim_type = xin->node->user_data.v_int;
1531 static void
1532 xlsx_ser_type_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1534 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1535 state->dim_type = GOG_MS_DIM_LABELS;
1538 static void
1539 xlsx_chart_legend (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1541 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1542 xlsx_chart_push_obj (state, gog_object_add_by_name (GOG_OBJECT (state->chart), "Legend", NULL));
1545 static void
1546 xlsx_chart_legend_pos (GsfXMLIn *xin, xmlChar const **attrs)
1548 static const EnumVal const positions[] = {
1549 { "t", GOG_POSITION_N },
1550 { "b", GOG_POSITION_S },
1551 { "l", GOG_POSITION_W },
1552 { "r", GOG_POSITION_E },
1553 { "tr", GOG_POSITION_N | GOG_POSITION_E },
1554 /* adding extra values not in spec, but actually possible */
1555 { "rt", GOG_POSITION_N | GOG_POSITION_E },
1556 { "lt", GOG_POSITION_N | GOG_POSITION_W },
1557 { "tl", GOG_POSITION_N | GOG_POSITION_W },
1558 { "rb", GOG_POSITION_S | GOG_POSITION_E },
1559 { "br", GOG_POSITION_S | GOG_POSITION_E },
1560 { "lb", GOG_POSITION_S | GOG_POSITION_W },
1561 { "bl", GOG_POSITION_S| GOG_POSITION_W },
1562 { NULL, 0 }
1564 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1565 int position = GOG_POSITION_E;
1567 (void)simple_enum (xin, attrs, positions, &position);
1568 if (GOG_IS_LEGEND (state->cur_obj))
1569 gog_object_set_position_flags (state->cur_obj, position, GOG_POSITION_COMPASS);
1572 static void
1573 xlsx_chart_pt_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1575 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1576 state->series_pt_has_index = FALSE;
1577 state->series_pt = gog_object_add_by_name (
1578 GOG_OBJECT (state->series), "Point", NULL);
1579 xlsx_chart_push_obj (state, state->series_pt);
1582 static void
1583 xlsx_chart_pt_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1585 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1586 xlsx_chart_pop_obj (state);
1587 if (!state->series_pt_has_index) {
1588 gog_object_clear_parent (state->series_pt);
1589 g_object_unref (state->series_pt);
1591 state->series_pt = NULL;
1594 static void
1595 xlsx_chart_pt_index (GsfXMLIn *xin, xmlChar const **attrs)
1597 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1598 unsigned idx;
1600 if (simple_uint (xin, attrs, &idx)) {
1601 state->series_pt_has_index = TRUE;
1602 g_object_set (state->series_pt, "index", idx, NULL);
1606 static void
1607 xlsx_chart_pt_sep (GsfXMLIn *xin, xmlChar const **attrs)
1609 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1610 unsigned sep;
1611 if (simple_uint (xin, attrs, &sep) &&
1612 g_object_class_find_property (G_OBJECT_GET_CLASS (state->series_pt), "separation"))
1613 g_object_set (state->series_pt, "separation", (double)sep / 100.0, NULL);
1616 static void
1617 xlsx_style_line_start (GsfXMLIn *xin, xmlChar const **attrs)
1619 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1620 int w = -1;
1622 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
1623 if (attr_int (xin, attrs, "w", &w))
1624 ; /* Nothing */
1627 state->sp_type |= GO_STYLE_LINE;
1628 if (!state->cur_style)
1629 state->cur_style = (GOStyle *) gog_style_new ();
1631 if (w == 0) {
1632 /* Special meaning of zero width */
1633 state->cur_style->line.auto_dash = FALSE;
1634 state->cur_style->line.dash_type = GO_LINE_NONE;
1635 } else if (w > 0) {
1636 state->cur_style->line.auto_width = FALSE;
1637 state->cur_style->line.width = w / 12700.;
1640 xlsx_chart_push_color_state (state, XLSX_CS_LINE);
1643 static void
1644 xlsx_style_line_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1646 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1647 state->sp_type &= ~GO_STYLE_LINE;
1648 xlsx_chart_pop_color_state (state, XLSX_CS_LINE);
1651 static void
1652 xlsx_draw_no_fill (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1654 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1655 if (NULL != state->marker)
1657 else if (NULL != state->cur_style) {
1658 if (state->sp_type & GO_STYLE_LINE) {
1659 state->cur_style->line.dash_type = GO_LINE_NONE;
1660 state->cur_style->line.auto_dash = FALSE;
1661 } else {
1662 state->cur_style->fill.type = GO_STYLE_FILL_NONE;
1663 state->cur_style->fill.auto_type = FALSE;
1668 static void
1669 xlsx_draw_grad_fill (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1671 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1672 if (NULL != state->marker) /* do xlsx support gradients in markers */
1674 else if (NULL != state->cur_style) {
1675 if (!(state->sp_type & GO_STYLE_LINE)) {
1676 state->cur_style->fill.type = GO_STYLE_FILL_GRADIENT;
1677 state->cur_style->fill.auto_type = FALSE;
1678 state->gradient_count = 0;
1683 static void
1684 xlsx_draw_grad_linear (GsfXMLIn *xin, xmlChar const **attrs)
1686 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1687 int ang = 0, ang_deg;
1688 GOGradientDirection dir;
1690 if (!state->cur_style)
1691 return;
1693 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
1694 if (attr_int (xin, attrs, "ang", &ang))
1695 ; /* Nothing */
1698 ang_deg = ((ang + 30000) / 60000);
1699 for (dir = 0; dir < GO_GRADIENT_MAX; dir++) {
1700 int this_ang = xlsx_gradient_info[dir].angle;
1701 gboolean this_mirrored = xlsx_gradient_info[dir].mirrored;
1702 int a;
1704 if (state->gradient_count != (this_mirrored ? 3 : 2))
1705 continue;
1706 /* We cannot distinguish the reversed case */
1708 /* Different angle convention. */
1709 this_ang = (360 - this_ang) % (this_mirrored ? 180 : 360);
1710 a = ang_deg % (this_mirrored ? 180 : 360);
1711 if (this_ang != a)
1712 continue;
1714 state->cur_style->fill.gradient.dir = dir;
1715 break;
1718 /* FIXME: we do not support the "scaled" attribute */
1721 static void
1722 xlsx_draw_grad_stop (GsfXMLIn *xin, xmlChar const **attrs)
1724 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1725 int pos = 0;
1726 XLSXColorState s = XLSX_CS_NONE;
1728 if (!state->cur_style)
1729 return;
1731 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
1732 if (attr_percent (xin, attrs, "pos", &pos))
1733 ; /* Nothing */
1736 state->gradient_count++;
1738 if (state->gradient_count == 1 && pos == 0)
1739 s = XLSX_CS_FILL_BACK;
1740 else if (state->gradient_count == 2 && (pos == 50000 || pos == 100000))
1741 s = XLSX_CS_FILL_FORE;
1742 else
1743 s = XLSX_CS_NONE; /* I.e., ignore. */
1745 xlsx_chart_push_color_state (state, s);
1748 static void
1749 xlsx_draw_grad_stop_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1751 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1753 if (!state->cur_style)
1754 return;
1756 xlsx_chart_pop_color_state (state, XLSX_CS_ANY);
1759 static void
1760 xlsx_draw_solid_fill (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1762 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1763 if (NULL != state->marker) {
1764 if (!(state->sp_type & GO_STYLE_LINE))
1765 xlsx_chart_push_color_state (state, XLSX_CS_MARKER);
1766 else
1767 xlsx_chart_push_color_state (state, XLSX_CS_MARKER_OUTLINE);
1768 } else if (state->cur_style) {
1769 if (state->sp_type & GO_STYLE_FONT)
1770 xlsx_chart_push_color_state (state, XLSX_CS_FONT);
1771 else if (state->sp_type & GO_STYLE_LINE) {
1772 state->cur_style->line.dash_type = GO_LINE_SOLID;
1773 xlsx_chart_push_color_state (state, XLSX_CS_LINE);
1774 } else {
1775 state->cur_style->fill.type = GO_STYLE_FILL_PATTERN;
1776 state->cur_style->fill.auto_type = FALSE;
1777 state->cur_style->fill.pattern.pattern = GO_PATTERN_FOREGROUND_SOLID;
1778 xlsx_chart_push_color_state (state, XLSX_CS_FILL_FORE);
1780 } else
1781 xlsx_chart_push_color_state (state, XLSX_CS_NONE);
1784 static void
1785 xlsx_draw_solid_fill_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1787 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1788 xlsx_chart_pop_color_state (state, XLSX_CS_ANY);
1791 static void
1792 xlsx_draw_patt_fill (GsfXMLIn *xin, xmlChar const **attrs)
1794 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1795 static EnumVal const patterns[] = {
1796 { "pct5", GO_PATTERN_GREY625 },
1797 { "pct10", GO_PATTERN_GREY125 },
1798 { "pct20", GO_PATTERN_GREY25 },
1799 { "pct25", GO_PATTERN_GREY25 },
1800 { "pct30", GO_PATTERN_GREY25 },
1801 { "pct40", GO_PATTERN_GREY50 },
1802 { "pct50", GO_PATTERN_GREY50 },
1803 { "pct60", GO_PATTERN_GREY50 },
1804 { "pct70", GO_PATTERN_GREY75 },
1805 { "pct75", GO_PATTERN_GREY75 },
1806 { "pct80", GO_PATTERN_GREY75 },
1807 { "pct90", GO_PATTERN_GREY75 },
1808 { "horz", GO_PATTERN_HORIZ },
1809 { "vert", GO_PATTERN_VERT },
1810 { "ltHorz", GO_PATTERN_THIN_HORIZ },
1811 { "ltVert", GO_PATTERN_THIN_VERT },
1812 { "dkHorz", GO_PATTERN_HORIZ },
1813 { "dkVert", GO_PATTERN_VERT },
1814 { "narHorz", GO_PATTERN_HORIZ },
1815 { "narVert", GO_PATTERN_VERT },
1816 { "dashHorz", GO_PATTERN_THIN_HORIZ },
1817 { "dashVert", GO_PATTERN_THIN_VERT },
1818 { "cross", -1 },
1819 { "dnDiag", GO_PATTERN_REV_DIAG },
1820 { "upDiag", GO_PATTERN_DIAG },
1821 { "ltDnDiag", GO_PATTERN_THIN_REV_DIAG },
1822 { "ltUpDiag", GO_PATTERN_THIN_DIAG },
1823 { "dkDnDiag", GO_PATTERN_REV_DIAG },
1824 { "dkUpDiag", GO_PATTERN_DIAG },
1825 { "wdDnDiag", GO_PATTERN_REV_DIAG },
1826 { "wdUpDiag", GO_PATTERN_DIAG },
1827 { "dashDnDiag", GO_PATTERN_THIN_REV_DIAG },
1828 { "dashUpDiag", GO_PATTERN_THIN_DIAG },
1829 { "diagCross", GO_PATTERN_DIAG_CROSS },
1830 { "smCheck", -1 },
1831 { "lgCheck", -1 },
1832 { "smGrid", GO_PATTERN_THIN_HORIZ_CROSS },
1833 { "lgGrid", GO_PATTERN_THIN_HORIZ_CROSS },
1834 { "dotGrid", -1 },
1835 { "smConfetti", GO_PATTERN_SMALL_CIRCLES },
1836 { "lgConfetti", GO_PATTERN_SMALL_CIRCLES },
1837 { "horzBrick", GO_PATTERN_BRICKS },
1838 { "diagBrick", GO_PATTERN_BRICKS },
1839 { "solidDmnd", -1 },
1840 { "openDmnd", GO_PATTERN_THIN_DIAG_CROSS },
1841 { "dotDmnd", -1 },
1842 { "plaid", -1 },
1843 { "sphere", GO_PATTERN_LARGE_CIRCLES },
1844 { "weave", GO_PATTERN_THATCH },
1845 { "divot", -1 },
1846 { "shingle", GO_PATTERN_SEMI_CIRCLES },
1847 { "wave", -1 },
1848 { "trellis", GO_PATTERN_THICK_DIAG_CROSS },
1849 { "zigZag", -1 },
1850 { NULL, 0 }
1852 int pat = -1;
1854 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
1855 if (attr_enum (xin, attrs, "prst", patterns, &pat)) {
1856 /* Nothing */
1860 state->cur_style->fill.type = GO_STYLE_FILL_PATTERN;
1861 state->cur_style->fill.auto_type = (pat < 0);
1862 state->cur_style->fill.pattern.pattern = (pat < 0 ? GO_PATTERN_SOLID : pat);
1865 static void
1866 xlsx_draw_patt_fill_clr (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
1868 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1869 gboolean is_fg = xin->node->user_data.v_int;
1871 xlsx_chart_push_color_state (state, is_fg ? XLSX_CS_FILL_FORE : XLSX_CS_FILL_BACK);
1874 static void
1875 xlsx_draw_patt_fill_clr_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
1877 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1878 xlsx_chart_pop_color_state (state, XLSX_CS_ANY);
1881 static void
1882 xlsx_draw_line_headtail (GsfXMLIn *xin, xmlChar const **attrs)
1884 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1885 gboolean is_tail = xin->node->user_data.v_int;
1887 static EnumVal const types[] = {
1888 { "arrow", GO_ARROW_KITE },
1889 { "diamond", GO_ARROW_KITE },
1890 { "none", GO_ARROW_NONE },
1891 { "oval", GO_ARROW_OVAL },
1892 { "stealth", GO_ARROW_KITE },
1893 { "triangle", GO_ARROW_KITE },
1894 { NULL, 0 }
1896 static EnumVal const sizes[] = {
1897 { "sm", 0 },
1898 { "med", 1 },
1899 { "lg", 2 },
1900 { NULL, 0 }
1902 int typ = XL_ARROW_NONE;
1903 int w = 1, l = 1;
1905 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
1906 if (attr_enum (xin, attrs, "type", types, &typ) ||
1907 attr_enum (xin, attrs, "w", sizes, &w) ||
1908 attr_enum (xin, attrs, "len", sizes, &l)) {
1909 /* Nothing */
1913 if (GNM_IS_SO_LINE (state->so)) {
1914 GOArrow arrow;
1915 GOStyle const *style = state->cur_style;
1916 double width = style->line.auto_width ? 0 : style->line.width;
1917 xls_arrow_from_xl (&arrow, width, typ, l, w);
1918 g_object_set (state->so,
1919 (is_tail ? "end-arrow" : "start-arrow"), &arrow,
1920 NULL);
1925 static void
1926 color_set_helper (XLSXReadState *state)
1928 #ifdef DEBUG_COLOR
1929 g_printerr ("color: #%08x in state %d\n",
1930 state->color, state->chart_color_state & 7);
1931 #endif
1933 switch (state->chart_color_state & 7) {
1934 default:
1935 case XLSX_CS_NONE:
1936 break;
1937 case XLSX_CS_FONT:
1938 state->cur_style->font.color = state->color;
1939 state->cur_style->font.auto_color = FALSE;
1940 break;
1941 case XLSX_CS_LINE:
1942 state->cur_style->line.color = state->color;
1943 state->cur_style->line.auto_color = FALSE;
1944 break;
1945 case XLSX_CS_FILL_BACK:
1946 state->cur_style->fill.pattern.back = state->color;
1947 state->cur_style->fill.auto_back = FALSE;
1948 break;
1949 case XLSX_CS_FILL_FORE:
1950 state->cur_style->fill.pattern.fore = state->color;
1951 state->cur_style->fill.auto_fore = FALSE;
1952 break;
1953 case XLSX_CS_MARKER:
1954 go_marker_set_fill_color (state->marker, state->color);
1955 state->cur_style->marker.auto_fill_color = FALSE;
1956 break;
1957 case XLSX_CS_MARKER_OUTLINE:
1958 go_marker_set_outline_color (state->marker, state->color);
1959 state->cur_style->marker.auto_outline_color = FALSE;
1960 break;
1964 static void
1965 xlsx_draw_color_themed (GsfXMLIn *xin, xmlChar const **attrs)
1967 #if 0
1968 static EnumVal const colors[] = {
1969 { "bg1", 0 }, /* Background Color 1 */
1970 { "tx1", 1 }, /* Text Color 1 */
1971 { "bg2", 2 }, /* Background Color 2 */
1972 { "tx2", 3 }, /* Text Color 2 */
1973 { "accent1", 4 }, /* Accent Color 1 */
1974 { "accent2", 5 }, /* Accent Color 2 */
1975 { "accent3", 6 }, /* Accent Color 3 */
1976 { "accent4", 7 }, /* Accent Color 4 */
1977 { "accent5", 8 }, /* Accent Color 5 */
1978 { "accent6", 9 }, /* Accent Color 6 */
1979 { "hlink", 10 }, /* Hyperlink Color */
1980 { "folHlink", 11 }, /* Followed Hyperlink Color */
1981 { "phClr", 12 }, /* Style Color */
1982 { "dk1", 13 }, /* Dark Color 1 */
1983 { "lt1", 14 }, /* Light Color 1 */
1984 { "dk2", 15 }, /* Dark Color 2 */
1985 { "lt2", 16 }, /* Light Color 2 */
1986 { NULL, 0 }
1988 #endif
1990 XLSXReadState *state = (XLSXReadState *)xin->user_state;
1991 const char *colname = simple_string (xin, attrs);
1993 if (colname) {
1994 gpointer val;
1995 if (g_hash_table_lookup_extended (state->theme_colors_by_name, colname, NULL, &val)) {
1996 state->color = GPOINTER_TO_UINT (val);
1997 color_set_helper (state);
1998 } else
1999 xlsx_warning (xin, _("Unknown color '%s'"), colname);
2003 static void
2004 xlsx_draw_color_rgb (GsfXMLIn *xin, xmlChar const **attrs)
2006 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2007 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
2008 if (attr_gocolor (xin, attrs, "val", &state->color))
2009 color_set_helper (state);
2013 static void
2014 xlsx_draw_color_alpha (GsfXMLIn *xin, xmlChar const **attrs)
2016 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2017 guint action = xin->node->user_data.v_int;
2018 unsigned val;
2019 if (simple_uint (xin, attrs, &val)) {
2020 const unsigned scale = 100000u;
2021 int a = GO_COLOR_UINT_A (state->color);
2022 switch (action) {
2023 case 0:
2024 a = 255u * CLAMP (val, 0u, scale) / scale;
2025 break;
2026 case 1:
2027 a += 255u * CLAMP (val, 0u, scale) / scale;
2028 break;
2029 case 2:
2030 a = a * CLAMP (val, 0u, scale) / scale;
2031 break;
2032 default:
2033 g_assert_not_reached ();
2036 a = CLAMP (a, 0, 255);
2037 state->color = GO_COLOR_CHANGE_A (state->color, a);
2038 color_set_helper (state);
2042 static void
2043 xlsx_draw_color_shade (GsfXMLIn *xin, xmlChar const **attrs)
2045 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2046 unsigned val;
2047 if (simple_uint (xin, attrs, &val)) {
2048 const unsigned scale = 100000u;
2049 double f = CLAMP (val, 0u, scale) / (double)scale;
2051 * FIXME: Wrong RGB colour space, see
2052 * https://social.msdn.microsoft.com/forums/office/en-US/f6d26f2c-114f-4a0d-8bca-a27442aec4d0/tint-and-shade-elements
2054 state->color = GO_COLOR_CHANGE_R(state->color, (guint8)(f*GO_COLOR_UINT_R(state->color)));
2055 state->color = GO_COLOR_CHANGE_G(state->color, (guint8)(f*GO_COLOR_UINT_G(state->color)));
2056 state->color = GO_COLOR_CHANGE_B(state->color, (guint8)(f*GO_COLOR_UINT_B(state->color)));
2057 color_set_helper (state);
2061 static void
2062 xlsx_draw_color_tint (GsfXMLIn *xin, xmlChar const **attrs)
2064 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2065 unsigned val;
2066 if (simple_uint (xin, attrs, &val)) {
2067 const unsigned scale = 100000u;
2068 double f = CLAMP (val, 0u, scale) / (double)scale;
2070 * FIXME: Wrong RGB colour space, see
2071 * https://social.msdn.microsoft.com/forums/office/en-US/f6d26f2c-114f-4a0d-8bca-a27442aec4d0/tint-and-shade-elements
2073 state->color = GO_COLOR_CHANGE_R(state->color, (guint8)(f * 255 + (1 - f) * GO_COLOR_UINT_R(state->color)));
2074 state->color = GO_COLOR_CHANGE_G(state->color, (guint8)(f * 255 + (1 - f) * GO_COLOR_UINT_G(state->color)));
2075 state->color = GO_COLOR_CHANGE_B(state->color, (guint8)(f * 255 + (1 - f) * GO_COLOR_UINT_B(state->color)));
2076 color_set_helper (state);
2080 static void
2081 xlsx_draw_line_dash (GsfXMLIn *xin, xmlChar const **attrs)
2083 static const EnumVal const dashes[] = {
2084 { "solid", GO_LINE_SOLID },
2085 { "dot", GO_LINE_DOT },
2086 { "dash", GO_LINE_DASH },
2087 { "lgDash", GO_LINE_LONG_DASH },
2088 { "dashDot", GO_LINE_DASH_DOT },
2089 { "lgDashDot", GO_LINE_DASH_DOT_DOT },
2090 { "lgDashDotDot", GO_LINE_DASH_DOT_DOT_DOT },
2091 { "sysDash", GO_LINE_S_DASH },
2092 { "sysDot", GO_LINE_S_DOT },
2093 { "sysDashDot", GO_LINE_S_DASH_DOT },
2094 { "sysDashDotDot", GO_LINE_S_DASH_DOT_DOT },
2095 { NULL, 0 }
2097 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2098 int dash = GO_LINE_SOLID;
2100 /* No documented default -- solid seems reasonable. */
2101 (void)simple_enum (xin, attrs, dashes, &dash);
2103 if (NULL != state->marker)
2104 ; /* what goes here ?*/
2105 else if (NULL != state->cur_style) {
2106 if (state->sp_type & GO_STYLE_LINE) {
2107 state->cur_style->line.auto_dash = FALSE;
2108 state->cur_style->line.dash_type = dash;
2109 } else {
2110 ; /* what goes here ?*/
2115 static void
2116 xlsx_chart_marker_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
2118 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2119 state->marker = go_marker_new ();
2122 static void
2123 xlsx_chart_marker_symbol (GsfXMLIn *xin, xmlChar const **attrs)
2125 static const EnumVal const symbols[] = {
2126 { "circle", GO_MARKER_CIRCLE },
2127 { "dash", GO_MARKER_BAR }, /* FIXME */
2128 { "diamond", GO_MARKER_DIAMOND },
2129 { "dot", GO_MARKER_HALF_BAR }, /* FIXME */
2130 { "none", GO_MARKER_NONE },
2131 { "plus", GO_MARKER_CROSS }, /* CHECK ME */
2132 { "square", GO_MARKER_SQUARE },
2133 { "star", GO_MARKER_ASTERISK }, /* CHECK ME */
2134 { "triangle", GO_MARKER_TRIANGLE_UP },
2135 { "x", GO_MARKER_X },
2136 { "auto", GO_MARKER_MAX }, /* Not in all versions of spec. */
2137 { NULL, 0 }
2139 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2140 int symbol = GO_MARKER_MAX;
2142 simple_enum (xin, attrs, symbols, &symbol);
2143 if (NULL != state->marker) {
2144 if (symbol < GO_MARKER_MAX) {
2145 go_marker_set_shape (state->marker, symbol);
2146 state->cur_style->marker.auto_shape = FALSE;
2147 } else
2148 state->cur_style->marker.auto_shape = TRUE;
2152 static void
2153 xlsx_chart_marker_size (GsfXMLIn *xin, xmlChar const **attrs)
2155 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2156 unsigned sz = 5; /* Documented default. */
2158 (void)simple_uint (xin, attrs, &sz);
2159 go_marker_set_size (state->marker, CLAMP (sz, 2, 72));
2162 static void
2163 xlsx_chart_marker_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
2165 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2166 if (NULL != state->cur_obj && GOG_IS_STYLED_OBJECT (state->cur_obj)) {
2167 go_style_set_marker (state->cur_style, state->marker);
2169 state->marker = NULL;
2172 static void
2173 xlsx_plot_area (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
2175 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2176 GogObject *backplane = gog_object_add_by_name (
2177 GOG_OBJECT (state->chart), "Backplane", NULL);
2178 xlsx_chart_push_obj (state, backplane);
2181 static void
2182 xlsx_chart_pop (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
2184 xlsx_chart_pop_obj ((XLSXReadState *)xin->user_state);
2187 static void
2188 xlsx_chart_layout_manual (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
2190 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2191 GogViewAllocation alloc;
2193 /* FIXME: we don't take xMode and yMode into account for now */
2195 alloc.x = state->chart_pos[0];
2196 alloc.w = state->chart_pos[1];
2197 alloc.y = state->chart_pos[2];
2198 alloc.h = state->chart_pos[3];
2200 if (GOG_IS_GRID (state->cur_obj)) {
2202 if (0 && state->chart_pos_mode[0]) {
2203 alloc.x = 0;
2204 alloc.w = 1;
2206 if (0 && state->chart_pos_mode[2]) {
2207 alloc.y = 0;
2208 alloc.h = 1;
2211 if (state->chart_pos_target) {/* inner mode */
2212 gog_chart_set_plot_area (state->chart, &alloc);
2214 /* else FIXME: how can we deal cleanly with an outer target? */
2215 } else {
2216 /* FIXME: this is correct only for chart children */
2217 gog_object_set_position_flags (state->cur_obj, GOG_POSITION_MANUAL, GOG_POSITION_ANY_MANUAL);
2218 gog_object_set_manual_position (state->cur_obj, &alloc);
2221 xlsx_reset_chart_pos (state);
2224 static void
2225 xlsx_chart_layout_target (GsfXMLIn *xin, xmlChar const **attrs)
2227 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2228 state->chart_pos_target = !(attrs[1] && strcmp (attrs[1], "inner"));
2231 static void
2232 xlsx_chart_layout_dim (GsfXMLIn *xin, xmlChar const **attrs)
2234 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2235 simple_float (xin, attrs, state->chart_pos + xin->node->user_data.v_int);
2238 static void
2239 xlsx_chart_layout_mode (GsfXMLIn *xin, xmlChar const **attrs)
2241 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2242 static const EnumVal const choices[] = {
2243 { "factor", FALSE },
2244 { "edge", TRUE },
2245 { NULL, 0 }
2247 int choice = FALSE;
2249 (void)simple_enum (xin, attrs, choices, &choice);
2250 state->chart_pos_mode[xin->node->user_data.v_int] = choice;
2253 static void
2254 xlsx_ext_gostyle (GsfXMLIn *xin, xmlChar const **attrs)
2256 XLSXReadState *state = (XLSXReadState *)xin->user_state;
2257 GOStyle *style = state->cur_style;
2258 GOArrow *start_arrow = NULL;
2259 GOArrow *end_arrow = NULL;
2260 gboolean has_arrow = GNM_IS_SO_LINE (state->so);
2261 int rev_gradient = 0;
2263 if (!style)
2264 return;
2266 if (has_arrow)
2267 g_object_get (state->so, "start_arrow", &start_arrow, "end_arrow", &end_arrow, NULL);
2269 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
2270 gnm_float f;
2272 if (strcmp (attrs[0], "pattern") == 0) {
2273 GOPatternType p = go_pattern_from_str (attrs[1]);
2274 if (style->fill.pattern.pattern == GO_PATTERN_FOREGROUND_SOLID &&
2275 p == GO_PATTERN_SOLID) {
2276 /* We read the wrong color */
2277 style->fill.pattern.back = style->fill.pattern.fore;
2278 style->fill.auto_back = style->fill.auto_fore;
2279 style->fill.auto_fore = TRUE;
2280 style->fill.pattern.fore = GO_COLOR_BLACK;
2282 style->fill.pattern.pattern = p;
2283 } else if (start_arrow && strcmp (attrs[0], "StartArrowType") == 0) {
2284 start_arrow->typ = go_arrow_type_from_str (attrs[1]);
2285 } else if (start_arrow && attr_float (xin, attrs, "StartArrowShapeA", &f)) {
2286 start_arrow->a = f;
2287 } else if (start_arrow && attr_float (xin, attrs, "StartArrowShapeB", &f)) {
2288 start_arrow->b = f;
2289 } else if (start_arrow && attr_float (xin, attrs, "StartArrowShapeC", &f)) {
2290 start_arrow->c = f;
2291 } else if (start_arrow && strcmp (attrs[0], "EndArrowType") == 0) {
2292 end_arrow->typ = go_arrow_type_from_str (attrs[1]);
2293 } else if (end_arrow && attr_float (xin, attrs, "EndArrowShapeA", &f)) {
2294 end_arrow->a = f;
2295 } else if (end_arrow && attr_float (xin, attrs, "EndArrowShapeB", &f)) {
2296 end_arrow->b = f;
2297 } else if (end_arrow && attr_float (xin, attrs, "EndArrowShapeC", &f)) {
2298 end_arrow->c = f;
2299 } else if (attr_bool (xin, attrs, "reverse-gradient", &rev_gradient)) {
2300 /* Nothing */
2301 } else if (strcmp (attrs[0], "markerSymbol") == 0) {
2302 const char *s = attrs[1];
2303 if (strcmp (s, "auto") == 0) {
2304 style->marker.auto_shape = TRUE;
2305 } else {
2306 style->marker.auto_shape = FALSE;
2307 go_marker_set_shape (state->marker, go_marker_shape_from_str (s));
2309 } else if (strcmp (attrs[0], "dashType") == 0) {
2310 const char *s = attrs[1];
2311 if (strcmp (s, "auto") == 0) {
2312 style->line.auto_dash = TRUE;
2313 } else {
2314 style->line.auto_dash = FALSE;
2315 style->line.dash_type = go_line_dash_from_str (s);
2320 if (has_arrow) {
2321 g_object_set (state->so, "start_arrow", start_arrow, "end_arrow", end_arrow, NULL);
2322 g_free (start_arrow);
2323 g_free (end_arrow);
2326 if (rev_gradient) {
2327 GOGradientDirection dir0 = style->fill.gradient.dir;
2328 GOGradientDirection dir;
2329 for (dir = 0; dir < GO_GRADIENT_MAX; dir++) {
2330 if (xlsx_gradient_info[dir0].angle == xlsx_gradient_info[dir].angle &&
2331 xlsx_gradient_info[dir0].mirrored == xlsx_gradient_info[dir].mirrored &&
2332 xlsx_gradient_info[dir0].reversed == !xlsx_gradient_info[dir].reversed) {
2333 GOColor c = style->fill.pattern.back;
2334 gboolean a = style->fill.auto_back;
2335 style->fill.gradient.dir = dir;
2336 style->fill.pattern.back = style->fill.pattern.fore;
2337 style->fill.pattern.fore = c;
2338 style->fill.auto_back = style->fill.auto_fore;
2339 style->fill.auto_fore = a;
2340 break;
2346 #define COLOR_MODIFIER_NODE(parent,node,name,first,handler,user) \
2347 GSF_XML_IN_NODE_FULL (parent, node, XL_NS_DRAW, name, (first ? GSF_XML_NO_CONTENT : GSF_XML_2ND), FALSE, FALSE, handler, NULL, user)
2349 #define COLOR_MODIFIER_NODES(parent,first) \
2350 COLOR_MODIFIER_NODE(parent, COLOR_SHADE, "shade", first, &xlsx_draw_color_shade, 0), \
2351 COLOR_MODIFIER_NODE(parent, COLOR_TINT, "tint", first, &xlsx_draw_color_tint, 0), \
2352 COLOR_MODIFIER_NODE(parent, COLOR_COMP, "comp", first, NULL, 0), \
2353 COLOR_MODIFIER_NODE(parent, COLOR_INV, "inv", first, NULL, 0), \
2354 COLOR_MODIFIER_NODE(parent, COLOR_GRAY, "gray", first, NULL, 0), \
2355 COLOR_MODIFIER_NODE(parent, COLOR_ALPHA, "alpha", first, &xlsx_draw_color_alpha, 0), \
2356 COLOR_MODIFIER_NODE(parent, COLOR_ALPHA_OFF, "alphaOff", first, &xlsx_draw_color_alpha, 1), \
2357 COLOR_MODIFIER_NODE(parent, COLOR_ALPHA_MOD, "alphaMod", first, &xlsx_draw_color_alpha, 2), \
2358 COLOR_MODIFIER_NODE(parent, COLOR_HUE, "hue", first, NULL, 0), \
2359 COLOR_MODIFIER_NODE(parent, COLOR_HUE_OFF, "hueOff", first, NULL, 1), \
2360 COLOR_MODIFIER_NODE(parent, COLOR_HUE_MOD, "hueMod", first, NULL, 2), \
2361 COLOR_MODIFIER_NODE(parent, COLOR_SAT, "sat", first, NULL, 0), \
2362 COLOR_MODIFIER_NODE(parent, COLOR_SAT_OFF, "satOff", first, NULL, 1), \
2363 COLOR_MODIFIER_NODE(parent, COLOR_SAT_MOD, "satMod", first, NULL, 2), \
2364 COLOR_MODIFIER_NODE(parent, COLOR_LUM, "lum", first, NULL, 0), \
2365 COLOR_MODIFIER_NODE(parent, COLOR_LUM_OFF, "lumOff", first, NULL, 1), \
2366 COLOR_MODIFIER_NODE(parent, COLOR_LUM_MOD, "lumMod", first, NULL, 2), \
2367 COLOR_MODIFIER_NODE(parent, COLOR_RED, "red", first, NULL, 0), \
2368 COLOR_MODIFIER_NODE(parent, COLOR_RED_OFF, "redOff", first, NULL, 1), \
2369 COLOR_MODIFIER_NODE(parent, COLOR_RED_MOD, "redMod", first, NULL, 2), \
2370 COLOR_MODIFIER_NODE(parent, COLOR_GREEN, "green", first, NULL, 0), \
2371 COLOR_MODIFIER_NODE(parent, COLOR_GREEN_OFF, "greenOff", first, NULL, 1), \
2372 COLOR_MODIFIER_NODE(parent, COLOR_GREEN_MOD, "greenMod", first, NULL, 2), \
2373 COLOR_MODIFIER_NODE(parent, COLOR_BLUE, "blue", first, NULL, 0), \
2374 COLOR_MODIFIER_NODE(parent, COLOR_BLUE_OFF, "blueOff", first, NULL, 1), \
2375 COLOR_MODIFIER_NODE(parent, COLOR_BLUE_MOD, "blueMod", first, NULL, 2), \
2376 COLOR_MODIFIER_NODE(parent, COLOR_GAMMA, "gamma", first, NULL, 0), \
2377 COLOR_MODIFIER_NODE(parent, COLOR_INV_GAMMA, "invGamma", first, NULL, 0)
2380 static GsfXMLInNode const xlsx_chart_dtd[] =
2382 GSF_XML_IN_NODE_FULL (START, START, -1, NULL, GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
2383 GSF_XML_IN_NODE_FULL (START, CHART_SPACE, XL_NS_CHART, "chartSpace", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
2384 GSF_XML_IN_NODE (CHART_SPACE, DATE1904, XL_NS_CHART, "date1904", GSF_XML_NO_CONTENT, NULL, NULL),
2385 GSF_XML_IN_NODE (CHART_SPACE, ROUNDEDCORNERS, XL_NS_CHART, "roundedCorners", GSF_XML_NO_CONTENT, NULL, NULL),
2386 GSF_XML_IN_NODE (CHART_SPACE, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL),
2387 GSF_XML_IN_NODE (SHAPE_PR, SP_XFRM, XL_NS_DRAW, "xfrm", GSF_XML_NO_CONTENT, &xlsx_sppr_xfrm, NULL),
2388 GSF_XML_IN_NODE (SP_XFRM, SP_XFRM_OFF, XL_NS_DRAW, "off", GSF_XML_NO_CONTENT, NULL, NULL),
2389 GSF_XML_IN_NODE (SP_XFRM, SP_XFRM_EXT, XL_NS_DRAW, "ext", GSF_XML_NO_CONTENT, NULL, NULL),
2390 GSF_XML_IN_NODE (SHAPE_PR, SP_PR_PRST_GEOM, XL_NS_DRAW, "prstGeom", GSF_XML_NO_CONTENT, NULL, NULL),
2391 GSF_XML_IN_NODE (SHAPE_PR, FILL_NONE, XL_NS_DRAW, "noFill", GSF_XML_NO_CONTENT, &xlsx_draw_no_fill, NULL),
2392 GSF_XML_IN_NODE (SHAPE_PR, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, &xlsx_draw_solid_fill, &xlsx_draw_solid_fill_end),
2393 GSF_XML_IN_NODE (FILL_SOLID, COLOR_THEMED, XL_NS_DRAW, "schemeClr", GSF_XML_NO_CONTENT, &xlsx_draw_color_themed, NULL),
2394 COLOR_MODIFIER_NODES(COLOR_THEMED,1),
2395 GSF_XML_IN_NODE (FILL_SOLID, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, &xlsx_draw_color_rgb, NULL),
2396 COLOR_MODIFIER_NODES(COLOR_RGB,0),
2397 GSF_XML_IN_NODE (FILL_SOLID, LN_DASH, XL_NS_DRAW, "prstDash", GSF_XML_NO_CONTENT, &xlsx_draw_line_dash, NULL),
2399 GSF_XML_IN_NODE (SHAPE_PR, FILL_BLIP, XL_NS_DRAW, "blipFill", GSF_XML_NO_CONTENT, NULL, NULL),
2400 GSF_XML_IN_NODE (FILL_BLIP, FILL_BLIP_BLIP, XL_NS_DRAW, "blip", GSF_XML_NO_CONTENT, NULL, NULL),
2401 GSF_XML_IN_NODE (FILL_BLIP, FILL_BLIP_SRC, XL_NS_DRAW, "srcRect", GSF_XML_NO_CONTENT, NULL, NULL),
2402 GSF_XML_IN_NODE (FILL_BLIP, FILL_BLIP_TILE, XL_NS_DRAW, "tile", GSF_XML_NO_CONTENT, NULL, NULL),
2404 GSF_XML_IN_NODE (SHAPE_PR, FILL_GRAD, XL_NS_DRAW, "gradFill", GSF_XML_NO_CONTENT, &xlsx_draw_grad_fill, NULL),
2405 GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIST, XL_NS_DRAW, "gsLst", GSF_XML_NO_CONTENT, NULL, NULL),
2406 GSF_XML_IN_NODE (GRAD_LIST, GRAD_LIST_ITEM, XL_NS_DRAW, "gs", GSF_XML_NO_CONTENT, xlsx_draw_grad_stop, xlsx_draw_grad_stop_end),
2407 GSF_XML_IN_NODE (GRAD_LIST_ITEM, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2408 GSF_XML_IN_NODE (GRAD_LIST_ITEM, COLOR_SYS, XL_NS_DRAW, "sysClr", GSF_XML_NO_CONTENT, NULL, NULL),
2409 GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIN, XL_NS_DRAW, "lin", GSF_XML_NO_CONTENT, &xlsx_draw_grad_linear, NULL),
2410 GSF_XML_IN_NODE (FILL_GRAD, GRAD_TILE, XL_NS_DRAW, "tileRect", GSF_XML_NO_CONTENT, NULL, NULL),
2412 GSF_XML_IN_NODE (SHAPE_PR, FILL_PATT, XL_NS_DRAW, "pattFill", GSF_XML_NO_CONTENT, &xlsx_draw_patt_fill, NULL),
2413 GSF_XML_IN_NODE_FULL (FILL_PATT, FILL_PATT_BG, XL_NS_DRAW, "bgClr", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_draw_patt_fill_clr, &xlsx_draw_patt_fill_clr_end, FALSE),
2414 GSF_XML_IN_NODE (FILL_PATT_BG, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2415 GSF_XML_IN_NODE_FULL (FILL_PATT, FILL_PATT_FG, XL_NS_DRAW, "fgClr", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_draw_patt_fill_clr, &xlsx_draw_patt_fill_clr_end, TRUE),
2416 GSF_XML_IN_NODE (FILL_PATT_FG, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2418 GSF_XML_IN_NODE (SHAPE_PR, SHAPE_PR_LN, XL_NS_DRAW, "ln", GSF_XML_NO_CONTENT, &xlsx_style_line_start, &xlsx_style_line_end),
2419 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_NOFILL, XL_NS_DRAW, "noFill", GSF_XML_NO_CONTENT, &xlsx_draw_no_fill, NULL),
2420 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_DASH, XL_NS_DRAW, "prstDash", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2421 GSF_XML_IN_NODE (SHAPE_PR_LN, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2422 GSF_XML_IN_NODE (SHAPE_PR_LN, FILL_PATT, XL_NS_DRAW, "pattFill", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2423 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_MITER, XL_NS_DRAW, "miter", GSF_XML_NO_CONTENT, NULL, NULL),
2424 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_ROUND, XL_NS_DRAW, "round", GSF_XML_NO_CONTENT, NULL, NULL),
2425 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_HEAD, XL_NS_DRAW, "headEnd", GSF_XML_NO_CONTENT, NULL, NULL),
2426 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_TAIL, XL_NS_DRAW, "tailEnd", GSF_XML_NO_CONTENT, NULL, NULL),
2427 GSF_XML_IN_NODE (SHAPE_PR, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, &xlsx_tx_pr, &xlsx_tx_pr_end),
2428 GSF_XML_IN_NODE (TEXT_PR, TEXT_PR_BODY, XL_NS_DRAW, "bodyPr", GSF_XML_NO_CONTENT, &xlsx_body_pr, NULL),
2429 GSF_XML_IN_NODE (TEXT_PR, TEXT_PR_STYLE, XL_NS_DRAW, "lstStyle", GSF_XML_NO_CONTENT, NULL, NULL),
2430 GSF_XML_IN_NODE (TEXT_PR, TEXT_PR_P, XL_NS_DRAW, "p", GSF_XML_NO_CONTENT, NULL, NULL),
2431 GSF_XML_IN_NODE (TEXT_PR_P, PR_P_PR, XL_NS_DRAW, "pPr", GSF_XML_NO_CONTENT, NULL, NULL),
2432 GSF_XML_IN_NODE (PR_P_PR, PR_P_PR_DEF, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, &xlsx_draw_text_run_props, NULL),
2433 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_CS, XL_NS_DRAW, "cs", GSF_XML_NO_CONTENT, NULL, NULL),
2434 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_EA, XL_NS_DRAW, "ea", GSF_XML_NO_CONTENT, NULL, NULL),
2435 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_LATIN, XL_NS_DRAW, "latin", GSF_XML_NO_CONTENT, &xlsx_rpr_latin, NULL),
2436 GSF_XML_IN_NODE (PR_P_PR_DEF, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2437 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_UFILLTX, XL_NS_DRAW, "uFillTx", GSF_XML_NO_CONTENT, NULL, NULL),
2438 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_ULNTX, XL_NS_DRAW, "uLnTx", GSF_XML_NO_CONTENT, NULL, NULL),
2439 GSF_XML_IN_NODE (TEXT_PR_P, PR_P_PR_END,XL_NS_DRAW, "endParaRPr", GSF_XML_NO_CONTENT, NULL, NULL),
2440 GSF_XML_IN_NODE (SHAPE_PR, EXTLST, XL_NS_DRAW, "extLst", GSF_XML_NO_CONTENT, NULL, NULL),
2441 GSF_XML_IN_NODE (EXTLST, EXTITEM, XL_NS_DRAW, "ext", GSF_XML_NO_CONTENT, &xlsx_ext_begin, &xlsx_ext_end),
2442 GSF_XML_IN_NODE (EXTITEM, EXT_GOSTYLE, XL_NS_GNM_EXT, "gostyle", GSF_XML_NO_CONTENT, &xlsx_ext_gostyle, NULL),
2444 GSF_XML_IN_NODE (CHART_SPACE, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2446 GSF_XML_IN_NODE (CHART_SPACE, CHART, XL_NS_CHART, "chart", GSF_XML_NO_CONTENT, NULL, NULL),
2447 GSF_XML_IN_NODE (CHART, SHOW_DBLS_OVER_MAX, XL_NS_CHART, "showDLblsOverMax", GSF_XML_NO_CONTENT, NULL, NULL),
2448 GSF_XML_IN_NODE (CHART, PLOTAREA, XL_NS_CHART, "plotArea", GSF_XML_NO_CONTENT, &xlsx_plot_area, &xlsx_chart_pop),
2449 GSF_XML_IN_NODE (PLOTAREA, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2450 GSF_XML_IN_NODE_FULL (PLOTAREA, CAT_AXIS, XL_NS_CHART, "catAx", GSF_XML_NO_CONTENT, FALSE, TRUE,
2451 &xlsx_axis_start, &xlsx_axis_end, XLSX_AXIS_CAT),
2452 GSF_XML_IN_NODE (CAT_AXIS, AXIS_AXID, XL_NS_CHART, "axId", GSF_XML_NO_CONTENT, &xlsx_axis_id, NULL),
2453 GSF_XML_IN_NODE (CAT_AXIS, AXIS_DELETE, XL_NS_CHART, "delete", GSF_XML_NO_CONTENT, &xlsx_axis_delete, NULL),
2454 GSF_XML_IN_NODE (CAT_AXIS, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2455 GSF_XML_IN_NODE (CAT_AXIS, AXIS_NUMFMT, XL_NS_CHART, "numFmt", GSF_XML_NO_CONTENT, &xlsx_axis_format, NULL),
2456 GSF_XML_IN_NODE (CAT_AXIS, AXIS_DELETE, XL_NS_CHART, "delete", GSF_XML_NO_CONTENT, NULL, NULL),
2457 GSF_XML_IN_NODE_FULL (CAT_AXIS, AXIS_MAJORTICKMARK, XL_NS_CHART, "majorTickMark", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_axis_mark, NULL, 1),
2458 GSF_XML_IN_NODE_FULL (CAT_AXIS, AXIS_MINORTICKMARK, XL_NS_CHART, "minorTickMark", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_axis_mark, NULL, 0),
2459 GSF_XML_IN_NODE_FULL (CAT_AXIS, AXIS_MAJORTICK_UNIT, XL_NS_CHART, "majorUnit", GSF_XML_NO_CONTENT, FALSE, TRUE,
2460 &xlsx_axis_bound, NULL, GOG_AXIS_ELEM_MAJOR_TICK),
2461 GSF_XML_IN_NODE_FULL (CAT_AXIS, AXIS_MINORTICK_UNIT, XL_NS_CHART, "minorUnit", GSF_XML_NO_CONTENT, FALSE, TRUE,
2462 &xlsx_axis_bound, NULL, GOG_AXIS_ELEM_MINOR_TICK),
2463 GSF_XML_IN_NODE (CAT_AXIS, AXIS_TICK_LBL_SKIP, XL_NS_CHART, "tickLblSkip", GSF_XML_NO_CONTENT, NULL, NULL),
2464 GSF_XML_IN_NODE (CAT_AXIS, AXIS_TICK_MARK_SKIP, XL_NS_CHART, "tickMarkSkip", GSF_XML_NO_CONTENT, NULL, NULL),
2465 GSF_XML_IN_NODE (CAT_AXIS, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2466 GSF_XML_IN_NODE (CAT_AXIS, AXIS_SCALING, XL_NS_CHART, "scaling", GSF_XML_NO_CONTENT, NULL, NULL),
2467 GSF_XML_IN_NODE_FULL (AXIS_SCALING, AX_MIN, XL_NS_CHART, "min", GSF_XML_NO_CONTENT, FALSE, TRUE,
2468 &xlsx_axis_bound, NULL, GOG_AXIS_ELEM_MIN),
2469 GSF_XML_IN_NODE_FULL (AXIS_SCALING, AX_MAX, XL_NS_CHART, "max", GSF_XML_NO_CONTENT, FALSE, TRUE,
2470 &xlsx_axis_bound, NULL, GOG_AXIS_ELEM_MAX),
2471 GSF_XML_IN_NODE (AXIS_SCALING, AX_LOG, XL_NS_CHART, "logBase", GSF_XML_NO_CONTENT, &xlsx_chart_logbase, NULL),
2472 GSF_XML_IN_NODE (AXIS_SCALING, AX_ORIENTATION, XL_NS_CHART, "orientation", GSF_XML_NO_CONTENT, &xlsx_axis_orientation, NULL),
2473 GSF_XML_IN_NODE_FULL (CAT_AXIS, MAJOR_GRID, XL_NS_CHART, "majorGridlines", GSF_XML_NO_CONTENT,
2474 FALSE, FALSE, &xlsx_chart_gridlines, &xlsx_chart_pop, 1),
2475 GSF_XML_IN_NODE (MAJOR_GRID, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2476 GSF_XML_IN_NODE_FULL (CAT_AXIS, MINOR_GRID, XL_NS_CHART, "minorGridlines", GSF_XML_NO_CONTENT,
2477 FALSE, FALSE, &xlsx_chart_gridlines, &xlsx_chart_pop, 0),
2478 GSF_XML_IN_NODE (MINOR_GRID, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2479 GSF_XML_IN_NODE (CAT_AXIS, AXIS_POS, XL_NS_CHART, "axPos", GSF_XML_NO_CONTENT, &xlsx_axis_pos, NULL),
2480 GSF_XML_IN_NODE (CAT_AXIS, CAT_AXIS_TICKLBLPOS, XL_NS_CHART, "tickLblPos", GSF_XML_NO_CONTENT, &xslx_chart_tick_label_pos, NULL),
2481 GSF_XML_IN_NODE (CAT_AXIS, CAT_AXIS_AUTO, XL_NS_CHART, "auto", GSF_XML_NO_CONTENT, NULL, NULL),
2482 GSF_XML_IN_NODE (CAT_AXIS, AXIS_CROSSAX, XL_NS_CHART, "crossAx", GSF_XML_NO_CONTENT, &xlsx_axis_crossax, NULL),
2483 GSF_XML_IN_NODE (CAT_AXIS, AXIS_CROSSES, XL_NS_CHART, "crosses", GSF_XML_NO_CONTENT, &xlsx_axis_crosses, NULL),
2484 GSF_XML_IN_NODE (CAT_AXIS, AXIS_CROSSES_AT, XL_NS_CHART, "crossesAt", GSF_XML_NO_CONTENT, &xlsx_axis_crosses_at, NULL),
2486 GSF_XML_IN_NODE (CAT_AXIS, CAT_AXIS_LBLALGN, XL_NS_CHART, "lblAlgn", GSF_XML_NO_CONTENT, NULL, NULL),
2487 GSF_XML_IN_NODE (CAT_AXIS, CAT_AXIS_LBLOFFSET, XL_NS_CHART, "lblOffset", GSF_XML_NO_CONTENT, NULL, NULL),
2488 GSF_XML_IN_NODE (CAT_AXIS, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2489 GSF_XML_IN_NODE (CAT_AXIS, TITLE, XL_NS_CHART, "title", GSF_XML_NO_CONTENT, &xlsx_chart_title_start, xlsx_chart_title_end), /* ID is used */
2490 GSF_XML_IN_NODE (TITLE, OVERLAY, XL_NS_CHART, "overlay", GSF_XML_NO_CONTENT, NULL, NULL),
2491 GSF_XML_IN_NODE (TITLE, LAYOUT, XL_NS_CHART, "layout", GSF_XML_NO_CONTENT, NULL, NULL),
2492 GSF_XML_IN_NODE (LAYOUT, LAST_LAYOUT, XL_NS_CHART, "lastLayout", GSF_XML_NO_CONTENT, NULL, NULL),
2493 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_X, XL_NS_CHART, "x", GSF_XML_NO_CONTENT, NULL, NULL),
2494 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_Y, XL_NS_CHART, "y", GSF_XML_NO_CONTENT, NULL, NULL),
2495 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_W, XL_NS_CHART, "w", GSF_XML_NO_CONTENT, NULL, NULL),
2496 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_H, XL_NS_CHART, "h", GSF_XML_NO_CONTENT, NULL, NULL),
2497 GSF_XML_IN_NODE (LAYOUT, LAST_LAYOUT_OUTER, XL_NS_CHART, "lastLayoutOuter", GSF_XML_NO_CONTENT, NULL, NULL),
2498 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_X, XL_NS_CHART, "x", GSF_XML_NO_CONTENT, NULL, NULL),
2499 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_Y, XL_NS_CHART, "y", GSF_XML_NO_CONTENT, NULL, NULL),
2500 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_W, XL_NS_CHART, "w", GSF_XML_NO_CONTENT, NULL, NULL),
2501 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_H, XL_NS_CHART, "h", GSF_XML_NO_CONTENT, NULL, NULL),
2502 GSF_XML_IN_NODE (LAYOUT, MAN_LAYOUT, XL_NS_CHART, "manualLayout", GSF_XML_NO_CONTENT, NULL, &xlsx_chart_layout_manual),
2503 GSF_XML_IN_NODE (MAN_LAYOUT, MAN_LAYOUT_TARGET, XL_NS_CHART, "layoutTarget", GSF_XML_NO_CONTENT, &xlsx_chart_layout_target, NULL),
2504 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_H, XL_NS_CHART, "h", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_dim, NULL, 3),
2505 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_HMODE, XL_NS_CHART, "hMode", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_mode, NULL, 3),
2506 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_W, XL_NS_CHART, "w", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_dim, NULL, 1),
2507 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_WMODE, XL_NS_CHART, "wMode", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_mode, NULL, 1),
2508 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_X, XL_NS_CHART, "x", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_dim, NULL, 0),
2509 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_XMODE, XL_NS_CHART, "xMode", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_mode, NULL, 0),
2510 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_Y, XL_NS_CHART, "y", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_dim, NULL, 2),
2511 GSF_XML_IN_NODE_FULL (MAN_LAYOUT, MAN_LAYOUT_YMODE, XL_NS_CHART, "yMode", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_chart_layout_mode, NULL, 2),
2512 GSF_XML_IN_NODE (TITLE, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2513 GSF_XML_IN_NODE (TITLE, TEXT, XL_NS_CHART, "tx", GSF_XML_NO_CONTENT, &xlsx_chart_text_start, &xlsx_chart_text),
2514 GSF_XML_IN_NODE (TEXT, TX_RICH, XL_NS_CHART, "rich", GSF_XML_NO_CONTENT, NULL, NULL),
2515 GSF_XML_IN_NODE (TX_RICH, TX_RICH_BODY, XL_NS_CHART, "bodyP", GSF_XML_NO_CONTENT, NULL, NULL),
2516 GSF_XML_IN_NODE (TX_RICH, TEXT_PR_BODY, XL_NS_DRAW, "bodyPr", GSF_XML_NO_CONTENT, NULL, NULL),
2517 GSF_XML_IN_NODE (TX_RICH, TX_RICH_STYLES, XL_NS_DRAW, "lstStyle", GSF_XML_NO_CONTENT, NULL, NULL),
2518 GSF_XML_IN_NODE (TX_RICH, TX_RICH_P, XL_NS_DRAW, "p", GSF_XML_NO_CONTENT, &xlsx_chart_p_start, NULL),
2519 GSF_XML_IN_NODE (TX_RICH_P, PR_P_PR, XL_NS_DRAW, "pPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2520 GSF_XML_IN_NODE (TX_RICH_P, TX_RICH_R, XL_NS_DRAW, "r", GSF_XML_NO_CONTENT, NULL, NULL),
2521 GSF_XML_IN_NODE (TX_RICH_R, TX_RICH_R_PR, XL_NS_DRAW, "rPr", GSF_XML_NO_CONTENT, &xlsx_draw_text_run_props, NULL),
2522 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_CS, XL_NS_DRAW, "cs", GSF_XML_NO_CONTENT, NULL, NULL),
2523 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_EA, XL_NS_DRAW, "ea", GSF_XML_NO_CONTENT, NULL, NULL),
2524 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_LATIN, XL_NS_DRAW, "latin", GSF_XML_NO_CONTENT, NULL, NULL),
2525 GSF_XML_IN_NODE (TX_RICH_R_PR, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2526 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_UFILLTX, XL_NS_DRAW, "uFillTx", GSF_XML_NO_CONTENT, NULL, NULL),
2527 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_ULNTX, XL_NS_DRAW, "uLnTx", GSF_XML_NO_CONTENT, NULL, NULL),
2528 GSF_XML_IN_NODE (TX_RICH_R, TX_RICH_R_T, XL_NS_DRAW, "t", GSF_XML_CONTENT, NULL, &xlsx_chart_text_content),
2529 GSF_XML_IN_NODE (TEXT, STR_REF, XL_NS_CHART, "strRef", GSF_XML_NO_CONTENT, NULL, NULL),
2530 GSF_XML_IN_NODE (STR_REF, FUNC, XL_NS_CHART, "f", GSF_XML_CONTENT, NULL, &xlsx_chart_ser_f),
2531 GSF_XML_IN_NODE (STR_REF, STR_CACHE, XL_NS_CHART, "strCache", GSF_XML_NO_CONTENT, NULL, NULL),
2532 GSF_XML_IN_NODE (STR_CACHE, STR_CACHE_COUNT, XL_NS_CHART,"ptCount", GSF_XML_NO_CONTENT, NULL, NULL),
2533 GSF_XML_IN_NODE (STR_CACHE, STR_PT, XL_NS_CHART,"pt", GSF_XML_NO_CONTENT, NULL, NULL),
2534 GSF_XML_IN_NODE (STR_PT, STR_VAL, XL_NS_CHART,"v", GSF_XML_NO_CONTENT, NULL, NULL),
2535 GSF_XML_IN_NODE (TITLE, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2537 GSF_XML_IN_NODE_FULL (PLOTAREA, VAL_AXIS, XL_NS_CHART, "valAx", GSF_XML_NO_CONTENT, FALSE, TRUE,
2538 &xlsx_axis_start, &xlsx_axis_end, XLSX_AXIS_VAL),
2539 GSF_XML_IN_NODE (VAL_AXIS, AXIS_AXID, XL_NS_CHART, "axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2540 GSF_XML_IN_NODE (VAL_AXIS, AXIS_DELETE, XL_NS_CHART, "delete", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2541 GSF_XML_IN_NODE (VAL_AXIS, TITLE, XL_NS_CHART, "title", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2542 GSF_XML_IN_NODE (VAL_AXIS, AXIS_SCALING, XL_NS_CHART, "scaling", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2543 GSF_XML_IN_NODE (VAL_AXIS, AXIS_POS, XL_NS_CHART, "axPos", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2544 GSF_XML_IN_NODE (VAL_AXIS, MAJOR_GRID, XL_NS_CHART, "majorGridlines", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2545 GSF_XML_IN_NODE (VAL_AXIS, MINOR_GRID, XL_NS_CHART, "minorGridlines", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2546 GSF_XML_IN_NODE (VAL_AXIS, AXIS_NUMFMT, XL_NS_CHART, "numFmt", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2547 GSF_XML_IN_NODE (VAL_AXIS, AXIS_MAJORTICKMARK, XL_NS_CHART, "majorTickMark", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2548 GSF_XML_IN_NODE (VAL_AXIS, AXIS_MINORTICKMARK, XL_NS_CHART, "minorTickMark", GSF_XML_NO_CONTENT, NULL, NULL),
2549 GSF_XML_IN_NODE (VAL_AXIS, AXIS_MAJORTICK_UNIT, XL_NS_CHART, "majorUnit", GSF_XML_NO_CONTENT, NULL, NULL),
2550 GSF_XML_IN_NODE (VAL_AXIS, AXIS_MINORTICK_UNIT, XL_NS_CHART, "minorUnit", GSF_XML_NO_CONTENT, NULL, NULL),
2551 GSF_XML_IN_NODE (VAL_AXIS, VAL_AXIS_TICKLBLPOS, XL_NS_CHART, "tickLblPos", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2552 GSF_XML_IN_NODE (VAL_AXIS, AXIS_CROSSAX, XL_NS_CHART, "crossAx", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2553 GSF_XML_IN_NODE (VAL_AXIS, AXIS_CROSSES, XL_NS_CHART, "crosses", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2554 GSF_XML_IN_NODE (VAL_AXIS, AXIS_CROSSES_AT, XL_NS_CHART, "crossesAt", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2555 GSF_XML_IN_NODE (VAL_AXIS, VAL_AXIS_CROSSBETWEEN, XL_NS_CHART, "crossBetween", GSF_XML_NO_CONTENT, NULL, NULL),
2556 GSF_XML_IN_NODE (VAL_AXIS, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2557 GSF_XML_IN_NODE (VAL_AXIS, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2559 GSF_XML_IN_NODE_FULL (PLOTAREA, DATE_AXIS, XL_NS_CHART, "dateAx", GSF_XML_NO_CONTENT, FALSE, TRUE,
2560 &xlsx_axis_start, &xlsx_axis_end, XLSX_AXIS_DATE),
2561 GSF_XML_IN_NODE (DATE_AXIS, AXIS_AUTO, XL_NS_CHART, "auto", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2562 GSF_XML_IN_NODE (DATE_AXIS, AXIS_AXID, XL_NS_CHART, "axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2563 GSF_XML_IN_NODE (DATE_AXIS, AXIS_POS, XL_NS_CHART, "axPos", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2564 GSF_XML_IN_NODE (DATE_AXIS, AXIS_CROSSAX, XL_NS_CHART, "crossAx", GSF_XML_NO_CONTENT, NULL, NULL),
2565 GSF_XML_IN_NODE (DATE_AXIS, AXIS_CROSSES, XL_NS_CHART, "crosses", GSF_XML_NO_CONTENT, NULL, NULL),
2566 GSF_XML_IN_NODE (DATE_AXIS, AXIS_CROSSES_AT, XL_NS_CHART, "crossesAt", GSF_XML_NO_CONTENT, NULL, NULL),
2567 GSF_XML_IN_NODE (DATE_AXIS, AXIS_DELETE, XL_NS_CHART, "delete", GSF_XML_NO_CONTENT, NULL, NULL),
2568 GSF_XML_IN_NODE (DATE_AXIS, AXIS_SCALING, XL_NS_CHART, "scaling", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2569 GSF_XML_IN_NODE (DATE_AXIS, MAJOR_GRID, XL_NS_CHART, "majorGridlines", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2570 GSF_XML_IN_NODE (DATE_AXIS, MINOR_GRID, XL_NS_CHART, "minorGridlines", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2571 GSF_XML_IN_NODE (DATE_AXIS, AXIS_NUMFMT, XL_NS_CHART, "numFmt", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2572 GSF_XML_IN_NODE (DATE_AXIS, AXIS_MAJORTICKMARK, XL_NS_CHART, "majorTickMark", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2573 GSF_XML_IN_NODE (DATE_AXIS, VAL_AXIS_TICKLBLPOS, XL_NS_CHART, "tickLblPos", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2574 GSF_XML_IN_NODE (DATE_AXIS, CAT_AXIS_LBLOFFSET, XL_NS_CHART, "lblOffset", GSF_XML_NO_CONTENT, NULL, NULL),
2575 GSF_XML_IN_NODE (DATE_AXIS, VAL_AXIS_TICKLBLPOS, XL_NS_CHART, "tickLblPos", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2576 GSF_XML_IN_NODE (DATE_AXIS, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2577 GSF_XML_IN_NODE (DATE_AXIS, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2579 GSF_XML_IN_NODE (PLOTAREA, LAYOUT, XL_NS_CHART, "layout", GSF_XML_NO_CONTENT, NULL, NULL),
2580 GSF_XML_IN_NODE (LAYOUT, LAST_LAYOUT, XL_NS_CHART, "lastLayout", GSF_XML_NO_CONTENT, NULL, NULL),
2581 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_X, XL_NS_CHART, "x", GSF_XML_NO_CONTENT, NULL, NULL),
2582 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_Y, XL_NS_CHART, "y", GSF_XML_NO_CONTENT, NULL, NULL),
2583 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_W, XL_NS_CHART, "w", GSF_XML_NO_CONTENT, NULL, NULL),
2584 GSF_XML_IN_NODE (LAST_LAYOUT, LAYOUT_H, XL_NS_CHART, "h", GSF_XML_NO_CONTENT, NULL, NULL),
2585 GSF_XML_IN_NODE (LAYOUT, LAST_LAYOUT_OUTER, XL_NS_CHART, "lastLayoutOuter", GSF_XML_NO_CONTENT, NULL, NULL),
2586 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_X, XL_NS_CHART, "x", GSF_XML_NO_CONTENT, NULL, NULL),
2587 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_Y, XL_NS_CHART, "y", GSF_XML_NO_CONTENT, NULL, NULL),
2588 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_W, XL_NS_CHART, "w", GSF_XML_NO_CONTENT, NULL, NULL),
2589 GSF_XML_IN_NODE (LAST_LAYOUT_OUTER, LAYOUT_H, XL_NS_CHART, "h", GSF_XML_NO_CONTENT, NULL, NULL),
2590 GSF_XML_IN_NODE (LAYOUT, MAN_LAYOUT, XL_NS_CHART, "manualLayout", GSF_XML_NO_CONTENT, NULL, NULL),
2592 GSF_XML_IN_NODE (PLOTAREA, SCATTER, XL_NS_CHART, "scatterChart", GSF_XML_NO_CONTENT, xlsx_chart_xy, &xlsx_plot_end),
2593 GSF_XML_IN_NODE (SCATTER, VARYCOLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, NULL, NULL),
2594 GSF_XML_IN_NODE (SCATTER, SCATTER_DLBLS, XL_NS_CHART, "dLbls", GSF_XML_NO_CONTENT, NULL, NULL),
2595 GSF_XML_IN_NODE (SCATTER_DLBLS, SCATTER_DLBLS_LEGEND, XL_NS_CHART, "showLegendKey", GSF_XML_NO_CONTENT, NULL, NULL),
2596 GSF_XML_IN_NODE (SCATTER_DLBLS, SCATTER_DLBLS_VAL, XL_NS_CHART, "showVal", GSF_XML_NO_CONTENT, NULL, NULL),
2597 GSF_XML_IN_NODE (SCATTER_DLBLS, SCATTER_DLBLS_CAT_NAME, XL_NS_CHART, "showCatName", GSF_XML_NO_CONTENT, NULL, NULL),
2598 GSF_XML_IN_NODE (SCATTER_DLBLS, SCATTER_DLBLS_SERIES_NAME, XL_NS_CHART, "showSerName", GSF_XML_NO_CONTENT, NULL, NULL),
2599 GSF_XML_IN_NODE (SCATTER_DLBLS, SCATTER_DLBLS_PERCENT, XL_NS_CHART, "showPercent", GSF_XML_NO_CONTENT, NULL, NULL),
2600 GSF_XML_IN_NODE (SCATTER_DLBLS, SCATTER_DLBLS_BUBBLE, XL_NS_CHART, "showBubbleSize", GSF_XML_NO_CONTENT, NULL, NULL),
2601 GSF_XML_IN_NODE (SCATTER, SCATTER_STYLE, XL_NS_CHART, "scatterStyle", GSF_XML_NO_CONTENT, &xlsx_scatter_style, NULL),
2602 GSF_XML_IN_NODE (SCATTER, PLOT_AXIS_ID, XL_NS_CHART, "axId", GSF_XML_NO_CONTENT, &xlsx_plot_axis_id, NULL),
2604 GSF_XML_IN_NODE (SCATTER, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, &xlsx_chart_ser_start, &xlsx_chart_ser_end),
2605 GSF_XML_IN_NODE (SERIES, SERIES_INVERTIFNEG, XL_NS_CHART, "invertIfNegative", GSF_XML_NO_CONTENT, NULL, NULL),
2606 GSF_XML_IN_NODE (SERIES, SERIES_TRENDLINE, XL_NS_CHART, "trendline", GSF_XML_NO_CONTENT, &xlsx_ser_trendline_start, &xlsx_ser_trendline_end),
2607 GSF_XML_IN_NODE (SERIES_TRENDLINE, SERIES_TRENDLINE_NAME, XL_NS_CHART, "name", GSF_XML_CONTENT, NULL, &xlsx_ser_trendline_name),
2608 GSF_XML_IN_NODE (SERIES_TRENDLINE, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2609 GSF_XML_IN_NODE (SERIES_TRENDLINE, SERIES_TRENDLINE_TYPE, XL_NS_CHART, "trendlineType", GSF_XML_NO_CONTENT, &xlsx_ser_trendline_type, NULL),
2610 GSF_XML_IN_NODE (SERIES_TRENDLINE, SERIES_TRENDLINE_RSQR, XL_NS_CHART, "dispRSqr", GSF_XML_NO_CONTENT, &xlsx_ser_trendline_disprsqr, NULL),
2611 GSF_XML_IN_NODE (SERIES_TRENDLINE, SERIES_TRENDLINE_EQ, XL_NS_CHART, "dispEq", GSF_XML_NO_CONTENT, &xlsx_ser_trendline_dispeq, NULL),
2612 GSF_XML_IN_NODE (SERIES_TRENDLINE, SERIES_TRENDLINE_LABEL, XL_NS_CHART, "trendlineLbl", GSF_XML_NO_CONTENT, NULL, NULL),
2613 GSF_XML_IN_NODE (SERIES_TRENDLINE_LABEL, SERIES_TRENDLINE_LABEL_LAYOUT, XL_NS_CHART, "layout", GSF_XML_NO_CONTENT, NULL, NULL),
2614 GSF_XML_IN_NODE (SERIES_TRENDLINE_LABEL_LAYOUT, SERIES_TRENDLINE_LABEL_LAYOUT_MANUAL, XL_NS_CHART, "manualLayout", GSF_XML_NO_CONTENT, NULL, NULL),
2615 GSF_XML_IN_NODE (SERIES_TRENDLINE_LABEL_LAYOUT_MANUAL, SERIES_TRENDLINE_LABEL_LAYOUT_MANUAL_X, XL_NS_CHART, "x", GSF_XML_NO_CONTENT, NULL, NULL),
2616 GSF_XML_IN_NODE (SERIES_TRENDLINE_LABEL_LAYOUT_MANUAL, SERIES_TRENDLINE_LABEL_LAYOUT_MANUAL_Y, XL_NS_CHART, "y", GSF_XML_NO_CONTENT, NULL, NULL),
2617 GSF_XML_IN_NODE (SERIES_TRENDLINE_LABEL, SERIES_TRENDLINE_LABEL_FORMAT, XL_NS_CHART, "numFmt", GSF_XML_NO_CONTENT, NULL, NULL),
2618 GSF_XML_IN_NODE (SERIES, SERIES_IDX, XL_NS_CHART, "idx", GSF_XML_NO_CONTENT, NULL, NULL),
2619 GSF_XML_IN_NODE (SERIES, SERIES_ORDER, XL_NS_CHART, "order", GSF_XML_NO_CONTENT, NULL, NULL),
2621 GSF_XML_IN_NODE_FULL (SERIES, SERIES_CAT, XL_NS_CHART,"cat", GSF_XML_NO_CONTENT, FALSE, TRUE,
2622 &xlsx_ser_type_start, &xlsx_ser_type_end, GOG_MS_DIM_CATEGORIES),
2623 GSF_XML_IN_NODE (SERIES_CAT, STR_REF, XL_NS_CHART, "strRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2624 GSF_XML_IN_NODE (SERIES_CAT, NUM_LIT, XL_NS_CHART, "numLit", GSF_XML_NO_CONTENT, NULL, NULL),
2625 GSF_XML_IN_NODE (NUM_LIT, NUM_LIT_FMT, XL_NS_CHART, "formatCode", GSF_XML_NO_CONTENT, NULL, NULL),
2626 GSF_XML_IN_NODE (NUM_LIT, NUM_LIT_COUNT, XL_NS_CHART, "ptCount", GSF_XML_NO_CONTENT, NULL, NULL),
2627 GSF_XML_IN_NODE (NUM_LIT, NUM_LIT_PT, XL_NS_CHART, "pt", GSF_XML_NO_CONTENT, NULL, NULL),
2628 GSF_XML_IN_NODE (NUM_LIT_PT, NUM_LIT_PT_VAL, XL_NS_CHART, "v", GSF_XML_NO_CONTENT, NULL, NULL),
2629 GSF_XML_IN_NODE (SERIES_CAT, NUM_REF, XL_NS_CHART, "numRef", GSF_XML_NO_CONTENT, NULL, NULL),
2630 GSF_XML_IN_NODE (NUM_REF, FUNC, XL_NS_CHART, "f", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2631 GSF_XML_IN_NODE (NUM_REF, NUM_CACHE, XL_NS_CHART, "numCache", GSF_XML_NO_CONTENT, NULL, NULL),
2632 GSF_XML_IN_NODE (NUM_CACHE, NUM_CACHE_FMT, XL_NS_CHART, "formatCode", GSF_XML_NO_CONTENT, NULL, NULL),
2633 GSF_XML_IN_NODE (NUM_CACHE, NUM_CACHE_COUNT, XL_NS_CHART,"ptCount", GSF_XML_NO_CONTENT, NULL, NULL),
2634 GSF_XML_IN_NODE (NUM_CACHE, NUM_PT, XL_NS_CHART,"pt", GSF_XML_NO_CONTENT, NULL, NULL),
2635 GSF_XML_IN_NODE (NUM_PT, NUM_VAL, XL_NS_CHART,"v", GSF_XML_NO_CONTENT, NULL, NULL),
2637 GSF_XML_IN_NODE_FULL (SERIES, SERIES_VAL, XL_NS_CHART, "val", GSF_XML_NO_CONTENT, FALSE, TRUE,
2638 &xlsx_ser_type_start, &xlsx_ser_type_end, GOG_MS_DIM_VALUES),
2639 GSF_XML_IN_NODE (SERIES_VAL, NUM_REF, XL_NS_CHART, "numRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2641 GSF_XML_IN_NODE_FULL (SERIES, SERIES_X_VAL, XL_NS_CHART, "xVal", GSF_XML_NO_CONTENT, FALSE, TRUE,
2642 &xlsx_ser_type_start, &xlsx_ser_type_end, GOG_MS_DIM_CATEGORIES),
2643 GSF_XML_IN_NODE (SERIES_X_VAL, NUM_REF, XL_NS_CHART, "numRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2644 GSF_XML_IN_NODE (SERIES_X_VAL, STR_REF, XL_NS_CHART, "strRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2645 GSF_XML_IN_NODE (SERIES_X_VAL, NUM_LIT, XL_NS_CHART, "numLit", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2647 GSF_XML_IN_NODE_FULL (SERIES, SERIES_Y_VAL, XL_NS_CHART, "yVal", GSF_XML_NO_CONTENT, FALSE, TRUE,
2648 &xlsx_ser_type_start, &xlsx_ser_type_end, GOG_MS_DIM_VALUES),
2649 GSF_XML_IN_NODE (SERIES_Y_VAL, NUM_REF, XL_NS_CHART, "numRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2650 GSF_XML_IN_NODE (SERIES_X_VAL, STR_REF, XL_NS_CHART, "strRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2651 GSF_XML_IN_NODE (SERIES_Y_VAL, NUM_LIT, XL_NS_CHART, "numLit", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2653 GSF_XML_IN_NODE_FULL (SERIES, SERIES_BUBBLES, XL_NS_CHART, "bubbleSize", GSF_XML_NO_CONTENT, FALSE, TRUE,
2654 &xlsx_ser_type_start, &xlsx_ser_type_end, GOG_MS_DIM_BUBBLES),
2655 GSF_XML_IN_NODE (SERIES_BUBBLES, NUM_REF, XL_NS_CHART, "numRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2656 GSF_XML_IN_NODE (SERIES_BUBBLES, NUM_LIT, XL_NS_CHART, "numLit", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2658 GSF_XML_IN_NODE (SERIES, TEXT, XL_NS_CHART, "tx", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2660 GSF_XML_IN_NODE (SERIES, SERIES_BUBBLES_3D, XL_NS_CHART, "bubble3D", GSF_XML_NO_CONTENT, NULL, NULL),
2661 GSF_XML_IN_NODE (SERIES, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2662 GSF_XML_IN_NODE (SERIES, SERIES_SMOOTH, XL_NS_CHART, "smooth", GSF_XML_NO_CONTENT, xlsx_ser_smooth, NULL),
2663 GSF_XML_IN_NODE (SERIES, SERIES_IDX, XL_NS_CHART, "idx", GSF_XML_NO_CONTENT, NULL, NULL),
2664 GSF_XML_IN_NODE (SERIES, SERIES_D_LBLS, XL_NS_CHART, "dLbls", GSF_XML_NO_CONTENT, &xlsx_ser_labels_start, &xlsx_ser_labels_end),
2665 GSF_XML_IN_NODE (SERIES_D_LBLS, SERIES_D_LBLS_POS, XL_NS_CHART, "dLblPos", GSF_XML_NO_CONTENT, &xlsx_ser_labels_pos, NULL),
2666 GSF_XML_IN_NODE (SERIES_D_LBLS, SERIES_D_LBL, XL_NS_CHART, "dLbl", GSF_XML_NO_CONTENT, &xlsx_data_label_start, &xlsx_chart_pop),
2667 GSF_XML_IN_NODE (SERIES_D_LBL, SERIES_D_LBL_POS, XL_NS_CHART, "dLblPos", GSF_XML_NO_CONTENT, &xlsx_data_label_pos, NULL),
2668 GSF_XML_IN_NODE (SERIES_D_LBL, SERIES_D_LBL_IDX, XL_NS_CHART, "idx", GSF_XML_NO_CONTENT, &xlsx_data_label_index, NULL),
2669 GSF_XML_IN_NODE (SERIES_D_LBL, SERIES_D_LBL_LAYOUT, XL_NS_CHART, "layout", GSF_XML_NO_CONTENT, NULL, NULL),
2670 GSF_XML_IN_NODE (SERIES_D_LBL, SERIES_D_LBL_SHOW_VAL, XL_NS_CHART, "showVal", GSF_XML_NO_CONTENT, &xlsx_data_label_show_val, NULL),
2671 GSF_XML_IN_NODE (SERIES_D_LBL, SERIES_D_LBL_SHOW_CAT, XL_NS_CHART, "showCatName", GSF_XML_NO_CONTENT, &xlsx_data_label_show_cat, NULL),
2672 GSF_XML_IN_NODE (SERIES_D_LBL, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2673 GSF_XML_IN_NODE (SERIES_D_LBL, TEXT, XL_NS_CHART, "tx", GSF_XML_NO_CONTENT, NULL, NULL),
2674 GSF_XML_IN_NODE (SERIES_D_LBL, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2675 GSF_XML_IN_NODE (SERIES_D_LBLS, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2676 GSF_XML_IN_NODE (SERIES_D_LBLS, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2677 GSF_XML_IN_NODE (SERIES_D_LBLS, SHOW_VAL, XL_NS_CHART, "showVal", GSF_XML_NO_CONTENT, &xlsx_ser_labels_show_val, NULL),
2678 GSF_XML_IN_NODE (SERIES_D_LBLS, NUM_FMT, XL_NS_CHART, "numFmt", GSF_XML_NO_CONTENT, NULL, NULL),
2679 GSF_XML_IN_NODE (SERIES_D_LBLS, SHOW_BUBBLE, XL_NS_CHART, "showBubbleSize", GSF_XML_NO_CONTENT, NULL, NULL),
2680 GSF_XML_IN_NODE (SERIES_D_LBLS, SHOW_CAT_NAME, XL_NS_CHART, "showCatName", GSF_XML_NO_CONTENT, &xlsx_ser_labels_show_cat, NULL),
2681 GSF_XML_IN_NODE (SERIES_D_LBLS, SHOW_LEADERS, XL_NS_CHART, "showLeaderLines", GSF_XML_NO_CONTENT, NULL, NULL),
2682 GSF_XML_IN_NODE (SERIES_D_LBLS, SHOW_PERCENT, XL_NS_CHART, "showPercent", GSF_XML_NO_CONTENT, NULL, NULL),
2684 GSF_XML_IN_NODE (SERIES, SERIES_PT, XL_NS_CHART, "dPt", GSF_XML_NO_CONTENT, &xlsx_chart_pt_start, &xlsx_chart_pt_end),
2685 GSF_XML_IN_NODE (SERIES_PT, BUBBLE3D, XL_NS_CHART, "bubble3D", GSF_XML_NO_CONTENT, NULL, NULL),
2686 GSF_XML_IN_NODE (SERIES_PT, PT_IDX, XL_NS_CHART, "idx", GSF_XML_NO_CONTENT, &xlsx_chart_pt_index, NULL),
2687 GSF_XML_IN_NODE (SERIES_PT, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL),
2688 GSF_XML_IN_NODE (SERIES_PT, PT_SEP, XL_NS_CHART, "explosion", GSF_XML_NO_CONTENT, &xlsx_chart_pt_sep, NULL),
2689 GSF_XML_IN_NODE (SERIES_PT, MARKER, XL_NS_CHART, "marker", GSF_XML_NO_CONTENT, &xlsx_chart_marker_start, &xlsx_chart_marker_end),
2690 GSF_XML_IN_NODE (MARKER, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2691 GSF_XML_IN_NODE (MARKER, MARKER_SYMBOL, XL_NS_CHART, "symbol", GSF_XML_NO_CONTENT, &xlsx_chart_marker_symbol, NULL),
2692 GSF_XML_IN_NODE (MARKER, MARKER_SIZE, XL_NS_CHART, "size", GSF_XML_NO_CONTENT, &xlsx_chart_marker_size, NULL),
2693 GSF_XML_IN_NODE (MARKER, EXTLST_C, XL_NS_CHART, "extLst", GSF_XML_NO_CONTENT, NULL, NULL),
2694 GSF_XML_IN_NODE (EXTLST_C, EXTITEM_C, XL_NS_CHART, "ext", GSF_XML_NO_CONTENT, &xlsx_ext_begin, &xlsx_ext_end),
2695 GSF_XML_IN_NODE (EXTITEM_C, EXT_GOSTYLE, XL_NS_GNM_EXT, "gostyle", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2697 GSF_XML_IN_NODE (SERIES, SERIES_ERR_BARS, XL_NS_CHART,"errBars", GSF_XML_NO_CONTENT, NULL, NULL),
2698 GSF_XML_IN_NODE (SERIES_ERR_BARS, SERIES_ERR_BARS_ERRBARTYPE, XL_NS_CHART, "errBarType", GSF_XML_NO_CONTENT, NULL, NULL),
2699 GSF_XML_IN_NODE (SERIES_ERR_BARS, SERIES_ERR_BARS_ERRDIR, XL_NS_CHART, "errDir", GSF_XML_NO_CONTENT, NULL, NULL),
2700 GSF_XML_IN_NODE (SERIES_ERR_BARS, SERIES_ERR_BARS_ERRVALTYPE, XL_NS_CHART, "errValType", GSF_XML_NO_CONTENT, NULL, NULL),
2701 GSF_XML_IN_NODE (SERIES_ERR_BARS, SERIES_ERR_BARS_MINUS, XL_NS_CHART, "minus", GSF_XML_NO_CONTENT, NULL, NULL),
2702 GSF_XML_IN_NODE (SERIES_ERR_BARS_MINUS, NUM_REF, XL_NS_CHART, "numRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2703 GSF_XML_IN_NODE (SERIES_ERR_BARS_MINUS, NUM_LIT, XL_NS_CHART, "numLit", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2704 GSF_XML_IN_NODE (SERIES_ERR_BARS, SERIES_ERR_BARS_PLUS, XL_NS_CHART, "plus", GSF_XML_NO_CONTENT, NULL, NULL),
2705 GSF_XML_IN_NODE (SERIES_ERR_BARS_PLUS, NUM_REF, XL_NS_CHART, "numRef", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2706 GSF_XML_IN_NODE (SERIES_ERR_BARS_PLUS, NUM_LIT, XL_NS_CHART, "numLit", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2707 GSF_XML_IN_NODE (SERIES_ERR_BARS, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2709 GSF_XML_IN_NODE (PLOTAREA, BUBBLE, XL_NS_CHART, "bubbleChart", GSF_XML_NO_CONTENT, &xlsx_chart_bubble, &xlsx_plot_end),
2710 GSF_XML_IN_NODE (BUBBLE, PLOT_AXIS_ID, XL_NS_CHART, "axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2711 GSF_XML_IN_NODE (BUBBLE, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL),
2712 GSF_XML_IN_NODE (BUBBLE, BUBBLE_SCALE, XL_NS_CHART, "bubbleScale", GSF_XML_NO_CONTENT, NULL, NULL),
2713 GSF_XML_IN_NODE (BUBBLE, BUBBLE_NEGATIVES, XL_NS_CHART, "showNegBubbles", GSF_XML_NO_CONTENT, NULL, NULL),
2714 GSF_XML_IN_NODE (BUBBLE, BUBBLE_SIZE_REP, XL_NS_CHART, "sizeRepresents", GSF_XML_NO_CONTENT, NULL, NULL),
2715 GSF_XML_IN_NODE (BUBBLE, VARY_COLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, &xlsx_vary_colors, NULL),
2717 GSF_XML_IN_NODE (PLOTAREA, BARCOL, XL_NS_CHART, "barChart", GSF_XML_NO_CONTENT, &xlsx_chart_bar, &xlsx_plot_end),
2718 GSF_XML_IN_NODE (BARCOL, VARYCOLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, NULL, NULL),
2719 GSF_XML_IN_NODE (BARCOL, PLOT_AXIS_ID, XL_NS_CHART, "axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2720 GSF_XML_IN_NODE (BARCOL, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2721 GSF_XML_IN_NODE (BARCOL, BARCOL_DIR, XL_NS_CHART, "barDir", GSF_XML_NO_CONTENT, &xlsx_chart_bar_dir, NULL),
2722 GSF_XML_IN_NODE (BARCOL, BARCOL_OVERLAP, XL_NS_CHART,"overlap", GSF_XML_NO_CONTENT, &xlsx_chart_bar_overlap, NULL),
2723 GSF_XML_IN_NODE (BARCOL, GROUPING, XL_NS_CHART, "grouping", GSF_XML_NO_CONTENT, &xlsx_chart_bar_group, NULL),
2724 GSF_XML_IN_NODE (BARCOL, GAP_WIDTH, XL_NS_CHART, "gapWidth", GSF_XML_NO_CONTENT, &xlsx_chart_bar_gap, NULL),
2726 GSF_XML_IN_NODE (PLOTAREA, LINE, XL_NS_CHART, "lineChart", GSF_XML_NO_CONTENT, &xlsx_chart_line, &xlsx_plot_end),
2727 GSF_XML_IN_NODE (LINE, VARYCOLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, NULL, NULL),
2728 GSF_XML_IN_NODE (LINE, PLOT_AXIS_ID, XL_NS_CHART,"axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2729 GSF_XML_IN_NODE (LINE, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2730 GSF_XML_IN_NODE (SERIES, MARKER, XL_NS_CHART, "marker", GSF_XML_NO_CONTENT, NULL, NULL),
2731 GSF_XML_IN_NODE (LINE, PLOT_AXIS_ID, XL_NS_CHART,"axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2732 GSF_XML_IN_NODE (LINE, GROUPING, XL_NS_CHART, "grouping", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2733 GSF_XML_IN_NODE (LINE, LINE_MARKER, XL_NS_CHART, "marker", GSF_XML_NO_CONTENT, &xlsx_chart_line_marker, NULL),
2735 GSF_XML_IN_NODE (PLOTAREA, AREA, XL_NS_CHART, "areaChart", GSF_XML_NO_CONTENT, &xlsx_chart_area, &xlsx_plot_end),
2736 GSF_XML_IN_NODE (AREA, PLOT_AXIS_ID, XL_NS_CHART,"axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2737 GSF_XML_IN_NODE (AREA, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2738 GSF_XML_IN_NODE (AREA, GROUPING, XL_NS_CHART, "grouping", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2740 GSF_XML_IN_NODE (PLOTAREA, RADAR, XL_NS_CHART, "radarChart", GSF_XML_NO_CONTENT, &xlsx_chart_radar, &xlsx_plot_end),
2741 GSF_XML_IN_NODE (RADAR, PLOT_AXIS_ID, XL_NS_CHART, "axId", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2742 GSF_XML_IN_NODE (RADAR, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2743 GSF_XML_IN_NODE (RADAR, RADAR_STYLE, XL_NS_CHART, "radarStyle", GSF_XML_NO_CONTENT, NULL, NULL),
2744 GSF_XML_IN_NODE (RADAR, VARY_COLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2746 GSF_XML_IN_NODE (PLOTAREA, PIE, XL_NS_CHART, "pieChart", GSF_XML_NO_CONTENT, &xlsx_chart_pie, &xlsx_plot_end),
2747 GSF_XML_IN_NODE (PIE, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2748 GSF_XML_IN_NODE (SERIES, PIE_SER_SEP, XL_NS_CHART, "explosion", GSF_XML_NO_CONTENT, &xlsx_chart_pie_sep, NULL),
2749 GSF_XML_IN_NODE (PIE, VARY_COLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2750 GSF_XML_IN_NODE (PIE, PIE_FIRST_SLICE, XL_NS_CHART, "firstSliceAng", GSF_XML_NO_CONTENT, NULL, NULL),
2752 GSF_XML_IN_NODE (PLOTAREA, OF_PIE, XL_NS_CHART, "ofPieChart", GSF_XML_NO_CONTENT, &xlsx_chart_pie, &xlsx_plot_end),
2753 GSF_XML_IN_NODE (OF_PIE, OF_PIE_TYPE, XL_NS_CHART, "ofPieType", GSF_XML_NO_CONTENT, NULL, NULL),
2754 GSF_XML_IN_NODE (OF_PIE, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2755 GSF_XML_IN_NODE (OF_PIE, SERIES_LINES, XL_NS_CHART, "serLines", GSF_XML_NO_CONTENT, NULL, NULL),
2756 GSF_XML_IN_NODE (SERIES_LINES, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2757 GSF_XML_IN_NODE (OF_PIE, PIE_GAP_WIDTH, XL_NS_CHART, "gapWidth", GSF_XML_NO_CONTENT, NULL, NULL),
2758 GSF_XML_IN_NODE (OF_PIE, VARY_COLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2759 GSF_XML_IN_NODE (OF_PIE, OF_2ND_PIE, XL_NS_CHART, "secondPieSize", GSF_XML_NO_CONTENT, NULL, NULL),
2761 GSF_XML_IN_NODE (PLOTAREA, DOUGHNUT, XL_NS_CHART, "doughnutChart", GSF_XML_NO_CONTENT, &xlsx_chart_ring, &xlsx_plot_end),
2762 GSF_XML_IN_NODE (DOUGHNUT, SERIES, XL_NS_CHART, "ser", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2763 GSF_XML_IN_NODE (DOUGHNUT, VARY_COLORS, XL_NS_CHART, "varyColors", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2764 GSF_XML_IN_NODE (DOUGHNUT, PIE_FIRST_SLICE, XL_NS_CHART, "firstSliceAng", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2765 GSF_XML_IN_NODE (DOUGHNUT, HOLE_SIZE, XL_NS_CHART, "holeSize", GSF_XML_NO_CONTENT, NULL, NULL),
2767 GSF_XML_IN_NODE (PLOTAREA, DATA_TABLE, XL_NS_CHART, "dTable", GSF_XML_NO_CONTENT, NULL, NULL),
2768 GSF_XML_IN_NODE (DATA_TABLE, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2769 GSF_XML_IN_NODE (DATA_TABLE, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2770 GSF_XML_IN_NODE (DATA_TABLE, DT_SHOW_H_BORDER, XL_NS_CHART, "showHorzBorder", GSF_XML_NO_CONTENT, NULL, NULL),
2771 GSF_XML_IN_NODE (DATA_TABLE, DT_SHOW_V_BORDER, XL_NS_CHART, "showVertBorder", GSF_XML_NO_CONTENT, NULL, NULL),
2772 GSF_XML_IN_NODE (DATA_TABLE, DT_SHOW_KEYS, XL_NS_CHART, "showKeys", GSF_XML_NO_CONTENT, NULL, NULL),
2773 GSF_XML_IN_NODE (DATA_TABLE, DT_SHOW_OUTLINE, XL_NS_CHART, "showOutline", GSF_XML_NO_CONTENT, NULL, NULL),
2775 GSF_XML_IN_NODE (CHART, TITLE, XL_NS_CHART, "title", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2777 GSF_XML_IN_NODE (CHART, LEGEND, XL_NS_CHART, "legend", GSF_XML_NO_CONTENT, &xlsx_chart_legend, &xlsx_chart_pop),
2778 GSF_XML_IN_NODE (LEGEND, OVERLAY, XL_NS_CHART, "overlay", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2779 GSF_XML_IN_NODE (LEGEND, SHAPE_PR, XL_NS_CHART, "spPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2780 GSF_XML_IN_NODE (LEGEND, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2781 GSF_XML_IN_NODE (LEGEND, LAYOUT, XL_NS_CHART, "layout", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
2782 GSF_XML_IN_NODE (LEGEND, LEGEND_POS, XL_NS_CHART, "legendPos", GSF_XML_NO_CONTENT, &xlsx_chart_legend_pos, NULL),
2783 GSF_XML_IN_NODE (CHART, CHART_HIDDEN, XL_NS_CHART, "plotVisOnly", GSF_XML_NO_CONTENT, NULL, NULL),
2784 GSF_XML_IN_NODE (CHART, CHART_BLANKS, XL_NS_CHART, "dispBlanksAs", GSF_XML_NO_CONTENT, NULL, NULL),
2785 GSF_XML_IN_NODE (CHART, AUTO_TITLE_DEL, XL_NS_CHART, "autoTitleDeleted", GSF_XML_NO_CONTENT, NULL, NULL),
2787 GSF_XML_IN_NODE (CHART_SPACE, STYLE, XL_NS_CHART, "style", GSF_XML_NO_CONTENT, NULL, NULL),
2788 GSF_XML_IN_NODE (CHART_SPACE, PRINT_SETTINGS, XL_NS_CHART, "printSettings", GSF_XML_NO_CONTENT, NULL, NULL),
2789 GSF_XML_IN_NODE (PRINT_SETTINGS, PAGE_SETUP, XL_NS_CHART, "pageSetup", GSF_XML_NO_CONTENT, NULL, NULL),
2790 GSF_XML_IN_NODE (PRINT_SETTINGS, PAGE_MARGINS, XL_NS_CHART, "pageMargins", GSF_XML_NO_CONTENT, NULL, NULL),
2791 GSF_XML_IN_NODE (PRINT_SETTINGS, HEADER_FOOTER, XL_NS_CHART, "headerFooter", GSF_XML_NO_CONTENT, NULL, NULL),
2792 GSF_XML_IN_NODE (HEADER_FOOTER, ODD_HEADER, XL_NS_CHART, "oddHeader", GSF_XML_NO_CONTENT, NULL, NULL),
2793 GSF_XML_IN_NODE (HEADER_FOOTER, ODD_FOOTER, XL_NS_CHART, "oddFooter", GSF_XML_NO_CONTENT, NULL, NULL),
2794 GSF_XML_IN_NODE (CHART_SPACE, LANG, XL_NS_CHART, "lang", GSF_XML_NO_CONTENT, NULL, NULL),
2795 GSF_XML_IN_NODE (CHART_SPACE, USER_SHAPE, XL_NS_CHART, "userShapes", GSF_XML_NO_CONTENT, &xlsx_chart_user_shapes, NULL),
2796 GSF_XML_IN_NODE_END
2799 /***********************************************************************/
2801 static int
2802 cb_by_id (gconstpointer a, gconstpointer b)
2804 return gog_object_get_id (a) - gog_object_get_id (b);
2807 static GSList *
2808 xlsx_get_axes (GogObject *chart)
2810 GSList *children, *waste = NULL, *axes = NULL;
2812 children = gog_object_get_children (chart, NULL);
2814 while (children) {
2815 GSList *next = children->next;
2816 GogObject *obj = children->data;
2818 if (GOG_IS_AXIS (obj)) {
2819 children->next = axes;
2820 axes = children;
2821 } else {
2822 children->next = waste;
2823 waste = children;
2826 children = next;
2829 g_slist_free (waste);
2830 return g_slist_sort (axes, cb_by_id);
2833 static void
2834 cb_axis_set_position (GObject *axis, XLSXAxisInfo *info, XLSXReadState *state)
2836 XLSXAxisInfo *cross_info = info->cross_id
2837 ? g_hash_table_lookup (state->axis.by_id, info->cross_id)
2838 : NULL;
2839 GogAxisPosition pos = info->cross;
2841 if (cross_info && cross_info->invert_axis) {
2842 switch (pos) {
2843 case GOG_AXIS_AT_LOW: pos = GOG_AXIS_AT_HIGH; break;
2844 case GOG_AXIS_AT_HIGH: pos = GOG_AXIS_AT_LOW; break;
2845 default: break;
2849 g_object_set (axis, "pos", pos, NULL);
2853 * Rename axes so we get numbers 1, 2, 3, etc. This is partly cosmetic
2854 * and partly for roundtrips. Note, that different axis types have their
2855 * own numbering.
2857 static void
2858 xlsx_axes_rename (XLSXReadState *state)
2860 GogObject *chart = GOG_OBJECT (state->chart);
2861 GSList *axes, *l, *l2;
2862 GHashTable *role_to_id = g_hash_table_new (NULL, NULL);
2864 axes = xlsx_get_axes (chart);
2866 for (l = axes; l; l = l->next) {
2867 GogObject *axis = l->data;
2868 GogObjectRole const *role = axis->role;
2869 guint old_id = axis->id;
2870 guint new_id = 1 + GPOINTER_TO_UINT (g_hash_table_lookup (role_to_id, (gpointer)role));
2871 GogAxisType cross_atype;
2873 if (new_id == old_id)
2874 continue;
2875 #ifdef DEBUG_AXIS
2876 g_printerr ("Changing id of %s to %u\n",
2877 gog_object_get_name (axis), new_id);
2878 #endif
2879 g_object_set (axis, "id", new_id, NULL);
2880 g_hash_table_replace (role_to_id, (gpointer)role, GUINT_TO_POINTER (new_id));
2883 * We shouldn't have to fixup cross-axis-id of other axes, but
2884 * looking for the old id won't hurt either.
2886 cross_atype = gog_axis_base_get_crossed_axis_type (GOG_AXIS_BASE (axis));
2887 for (l2 = axes; l2; l2 = l2->next) {
2888 GogObject *axis2 = l2->data;
2889 guint cross_id;
2891 if (gog_axis_get_atype (GOG_AXIS (axis2)) != cross_atype)
2892 continue;
2894 g_object_get (axis2, "cross-axis-id", &cross_id, NULL);
2895 if (cross_id == old_id)
2896 g_object_set (axis2, "cross-axis-id", new_id, NULL);
2900 g_slist_free (axes);
2901 g_hash_table_destroy (role_to_id);
2904 static void
2905 xlsx_axes_redirect_deleted (XLSXReadState *state)
2907 GogObject *chart = GOG_OBJECT (state->chart);
2908 GSList *l, *axes = xlsx_get_axes (chart);
2910 for (l = axes; l; l = l->next) {
2911 GogAxis *axis = l->data;
2912 XLSXAxisInfo *info;
2913 GogAxisType atype;
2914 GSList *l2, *plots, *children;
2915 GogAxis *visible = NULL;
2917 info = g_hash_table_lookup (state->axis.by_obj, axis);
2918 if (!info || !info->deleted)
2919 continue;
2921 /* Find a visible alternative for the deleted axis. */
2922 atype = gog_axis_get_atype (GOG_AXIS (axis));
2923 for (l2 = axes; l2; l2 = l2->next) {
2924 GogAxis *axis2 = GOG_AXIS (l2->data);
2925 if (gog_axis_get_atype (GOG_AXIS (axis2)) == atype &&
2926 !gnm_object_get_bool (axis2, "invisible")) {
2927 visible = axis2;
2928 break;
2931 if (!visible)
2932 continue;
2934 /* Make all plots use the new, visible axis. */
2935 plots = g_slist_copy ((GSList *) gog_axis_contributors (GOG_AXIS (axis)));
2936 for (l2 = plots; l2; l2 = l2->next) {
2937 GogPlot *plot = l2->data;
2938 if (GOG_IS_PLOT (plot))
2939 gog_plot_set_axis (plot, visible);
2941 g_slist_free (plots);
2943 /* Reparent the children of the deleted axis */
2944 children = gog_object_get_children (GOG_OBJECT (axis), NULL);
2945 for (l2 = children; l2; l2 = l2->next) {
2946 GogObject *obj = l2->data;
2947 GogObjectRole const *role = obj->role;
2948 gog_object_clear_parent (obj);
2949 gog_object_set_parent (obj, GOG_OBJECT (visible), role, obj->id);
2951 g_slist_free (children);
2954 g_slist_free (axes);
2957 static void
2958 xlsx_axes_remove_deleted (XLSXReadState *state)
2960 GHashTableIter hiter;
2961 gpointer key, val;
2963 g_hash_table_iter_init (&hiter, state->axis.by_obj);
2964 while (g_hash_table_iter_next (&hiter, &key, &val)) {
2965 GogAxis *axis = key;
2966 XLSXAxisInfo *info = val;
2967 if (info->deleted) {
2968 gboolean may_delete =
2969 gog_object_is_deletable (GOG_OBJECT (axis));
2970 #ifdef DEBUG_AXIS
2971 g_printerr ("Would like to delete file axis %p (%s): %s\n",
2972 axis,
2973 gog_object_get_name (GOG_OBJECT (axis)),
2974 may_delete ? "allowed" : "not allowed");
2975 #endif
2976 if (may_delete) {
2977 gog_object_clear_parent (GOG_OBJECT (axis));
2978 g_object_unref (axis);
2984 static void
2985 xlsx_axis_cleanup (XLSXReadState *state)
2987 GSList *axes, *l;
2989 /* clean out axes that were auto created */
2990 axes = xlsx_get_axes (GOG_OBJECT (state->chart));
2991 for (l = axes; l; l = l->next) {
2992 GogAxis *axis = l->data;
2993 XLSXAxisInfo *info;
2994 gboolean may_delete;
2996 info = g_hash_table_lookup (state->axis.by_obj, axis);
2997 if (info)
2998 continue;
3000 may_delete = gog_object_is_deletable (GOG_OBJECT (axis));
3001 #ifdef DEBUG_AXIS
3002 g_printerr ("Would like to delete auto axis %p (%s): %s\n",
3003 axis, gog_object_get_name (GOG_OBJECT (axis)),
3004 may_delete ? "allowed" : "not allowed");
3005 #endif
3006 if (may_delete) {
3007 gog_object_clear_parent (GOG_OBJECT (axis));
3008 g_object_unref (axis);
3011 g_slist_free (axes);
3013 xlsx_axes_redirect_deleted (state);
3015 g_hash_table_foreach (state->axis.by_obj,
3016 (GHFunc)cb_axis_set_position, state);
3018 xlsx_axes_remove_deleted (state);
3020 g_hash_table_destroy (state->axis.by_obj);
3021 g_hash_table_destroy (state->axis.by_id);
3022 state->axis.by_obj = state->axis.by_id = NULL;
3024 xlsx_axes_rename (state);
3027 static void
3028 xlsx_read_chart (GsfXMLIn *xin, xmlChar const **attrs)
3030 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3031 xmlChar const *part_id = NULL;
3033 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
3034 if (gsf_xml_in_namecmp (xin, attrs[0], XL_NS_DOC_REL, "id"))
3035 part_id = attrs[1];
3036 if (NULL != part_id) {
3037 /* leave it in 'state' for the frame to insert */
3038 state->so = sheet_object_graph_new (NULL);
3040 state->graph = sheet_object_graph_get_gog (state->so);
3041 state->cur_obj = gog_object_add_by_name (GOG_OBJECT (state->graph), "Chart", NULL);
3042 state->chart = GOG_CHART (state->cur_obj);
3043 state->cur_style = go_style_dup (go_styled_object_get_style (GO_STYLED_OBJECT (state->chart)));
3044 state->obj_stack = NULL;
3045 state->style_stack = NULL;
3046 state->dim_type = GOG_MS_DIM_LABELS;
3047 state->axis.by_id = g_hash_table_new_full (g_str_hash, g_str_equal,
3048 NULL, (GDestroyNotify) xlsx_axis_info_free);
3049 state->axis.by_obj = g_hash_table_new (g_direct_hash, g_direct_equal);
3050 xlsx_reset_chart_pos (state);
3052 xlsx_parse_rel_by_id (xin, part_id, xlsx_chart_dtd, xlsx_ns);
3054 if (NULL != state->obj_stack) {
3055 g_warning ("left over content on chart object stack");
3056 g_slist_free (state->obj_stack);
3057 state->obj_stack = NULL;
3060 xlsx_axis_cleanup (state);
3061 g_object_set (state->chart, "style", state->cur_style, NULL);
3062 g_object_unref (state->cur_style);
3063 state->cur_style = NULL;
3064 if (NULL != state->style_stack) {
3065 g_warning ("left over style");
3066 g_slist_free (state->style_stack);
3067 state->style_stack = NULL;
3069 if (state->chart) {
3070 GogObject *title = gog_object_get_child_by_name (GOG_OBJECT (state->chart), "Title");
3071 if (title) {
3072 /* test if the title s empty */
3073 GOData *dat = gog_dataset_get_dim (GOG_DATASET (title), 0);
3074 GError *err = NULL;
3075 char *str = dat != NULL? go_data_get_scalar_string (dat): NULL;
3076 /* if no title, use the first series label */
3077 if (!str || !*str) {
3078 GSList *plots = gog_chart_get_plots (state->chart);
3079 if (plots != NULL && plots->data != NULL) {
3080 GogPlot *plot = GOG_PLOT (plots->data);
3081 GogDataset *ds = plot? GOG_DATASET (gog_plot_get_series (plot)->data): NULL;
3082 if (ds)
3083 dat = gog_dataset_get_dim (ds, -1);
3084 if (dat)
3085 gog_dataset_set_dim (GOG_DATASET (title), 0,
3086 GO_DATA (g_object_ref (dat)), &err);
3087 if (err)
3088 g_error_free (err);
3091 g_free (str);
3094 xlsx_reset_chart_pos (state);
3095 state->cur_obj = NULL;
3096 state->chart = NULL;
3097 state->graph = NULL;
3101 /**************************************************************************/
3102 #define CELL 0
3103 #define OFFSET 1
3104 #define FROM 0
3105 #define TO 4
3106 #define COL 0
3107 #define ROW 2
3109 static void
3110 xlsx_draw_anchor_start (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
3112 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3114 g_return_if_fail (state->so == NULL);
3116 memset ((gpointer)state->drawing_pos, 0, sizeof (state->drawing_pos));
3117 state->drawing_pos_flags = 0;
3118 state->so_direction = GOD_ANCHOR_DIR_DOWN_RIGHT;
3119 state->so_anchor_mode = GNM_SO_ANCHOR_TWO_CELLS;
3122 static void
3123 xlsx_drawing_twoCellAnchor_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3125 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3127 if (NULL == state->so) {
3128 xlsx_warning (xin,
3129 _("Dropping missing object"));
3130 } else if ((state->drawing_pos_flags & 0xFF) != 0xFF) {
3131 xlsx_warning (xin,
3132 _("Dropping object with incomplete anchor %2x"), state->drawing_pos_flags);
3133 g_object_unref (state->so);
3134 } else {
3135 SheetObjectAnchor anchor;
3136 GnmRange r;
3137 double coords[4];
3138 double size;
3139 int i, max;
3141 range_init (&r,
3142 state->drawing_pos[COL | FROM],
3143 state->drawing_pos[ROW | FROM],
3144 state->drawing_pos[COL | TO],
3145 state->drawing_pos[ROW | TO]);
3147 switch (state->so_anchor_mode) {
3148 default:
3149 case GNM_SO_ANCHOR_TWO_CELLS:
3150 max = 8;
3151 break;
3152 case GNM_SO_ANCHOR_ONE_CELL:
3153 max = 4;
3154 break;
3155 case GNM_SO_ANCHOR_ABSOLUTE:
3156 max = 0;
3157 break;
3159 for (i = 0; i < 8; i+=2) {
3160 ColRowInfo const *cri;
3161 if (i < max) {
3162 if (i & 2) {
3163 cri = sheet_row_get (state->sheet, state->drawing_pos[i]);
3164 size = cri? cri->size_pts: sheet_row_get_default_size_pts (state->sheet);
3165 } else {
3166 cri = sheet_col_get (state->sheet, state->drawing_pos[i]);
3167 /* FIXME: scaling horizontally just like in xlsx_CT_Col */
3168 size = (cri? cri->size_pts: sheet_col_get_default_size_pts (state->sheet)) * 1.16191275167785;
3170 coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700. / size;
3171 } else
3172 coords[i / 2] = (double) state->drawing_pos[i + 1] / 12700.;
3174 sheet_object_anchor_init (&anchor, &r, coords, state->so_direction, state->so_anchor_mode);
3175 sheet_object_set_anchor (state->so, &anchor);
3176 if (state->cur_style &&
3177 g_object_class_find_property (G_OBJECT_GET_CLASS (state->so), "style"))
3178 g_object_set (state->so, "style", state->cur_style, NULL);
3180 state->pending_objects = g_slist_prepend (state->pending_objects, state->so);
3183 if (state->cur_style) {
3184 g_object_unref (state->cur_style);
3185 state->cur_style = NULL;
3187 state->so = NULL;
3191 static void
3192 xlsx_drawing_oneCellAnchor_end (GsfXMLIn *xin, GsfXMLBlob *blob)
3194 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3196 state->drawing_pos[COL | TO] = state->drawing_pos[COL | FROM];
3197 state->drawing_pos[ROW | TO] = state->drawing_pos[ROW | FROM];
3198 state->drawing_pos_flags |= ((1 << (COL | TO)) | (1 << (ROW | TO)));
3199 state->so_anchor_mode = GNM_SO_ANCHOR_ONE_CELL;
3200 xlsx_drawing_twoCellAnchor_end (xin, blob);
3203 static void
3204 xlsx_drawing_absoluteAnchor_end (GsfXMLIn *xin, GsfXMLBlob *blob)
3206 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3208 state->drawing_pos_flags |= ((1 << (COL | TO)) | (1 << (ROW | TO)) |
3209 (1 << (COL | FROM)) | (1 << (ROW | FROM)));
3210 state->so_anchor_mode = GNM_SO_ANCHOR_ABSOLUTE;
3211 xlsx_drawing_twoCellAnchor_end (xin, blob);
3214 static void
3215 xlsx_drawing_anchor_pos (GsfXMLIn *xin, xmlChar const **attrs)
3217 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3218 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
3219 if (attr_int64 (xin, attrs, "x", state->drawing_pos + (COL | FROM | OFFSET)))
3220 state->drawing_pos_flags |= (1 << (COL | FROM | OFFSET));
3221 else if (attr_int64 (xin, attrs, "y", state->drawing_pos + (ROW | FROM | OFFSET)))
3222 state->drawing_pos_flags |= (1 << (ROW | FROM | OFFSET));
3225 static void
3226 xlsx_drawing_ext (GsfXMLIn *xin, xmlChar const **attrs)
3228 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3229 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
3230 if (attr_int64 (xin, attrs, "cx", state->drawing_pos + (COL | TO | OFFSET)))
3231 state->drawing_pos_flags |= (1 << (COL | TO | OFFSET));
3232 else if (attr_int64 (xin, attrs, "cy", state->drawing_pos + (ROW | TO | OFFSET)))
3233 state->drawing_pos_flags |= (1 << (ROW | TO | OFFSET));
3236 static void
3237 xlsx_drawing_pos (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3239 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3240 gint64 val;
3241 char *end;
3243 errno = 0;
3244 val = g_ascii_strtoll (xin->content->str, &end, 10);
3245 if (errno == ERANGE || end == xin->content->str || *end != '\0')
3246 return;
3248 state->drawing_pos[xin->node->user_data.v_int] = val;
3249 state->drawing_pos_flags |= 1 << xin->node->user_data.v_int;
3250 #if 0
3251 g_printerr ("%s %s %s = %" G_GINT64_FORMAT "\n",
3252 (xin->node->user_data.v_int & TO) ? "To" : "From",
3253 (xin->node->user_data.v_int & ROW) ? "Row" : "Col",
3254 (xin->node->user_data.v_int & OFFSET) ? "Offset" : "",
3255 val);
3256 #endif
3259 static void
3260 xlsx_drawing_preset_geom (GsfXMLIn *xin, xmlChar const **attrs)
3262 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3264 static EnumVal const types[] = {
3265 { "rect", 0 },
3266 { "ellipse", 1 },
3267 { "line", 2 },
3268 { NULL, 0 }
3270 int typ = -1;
3272 if (NULL != state->so) /* FIXME FIXME FIXME: how does this happen? */
3273 return;
3275 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
3276 if (attr_enum (xin, attrs, "prst", types, &typ))
3277 ; /* Nothing */
3280 switch (typ) {
3281 case 0:
3282 state->so = g_object_new (GNM_SO_FILLED_TYPE, "is_oval", FALSE, NULL);
3283 break;
3284 case 1:
3285 state->so = g_object_new (GNM_SO_FILLED_TYPE, "is_oval", TRUE, NULL);
3286 break;
3287 case 2:
3288 state->so = g_object_new (GNM_SO_LINE_TYPE, NULL);
3289 break;
3290 default:
3291 break;
3294 if (state->so) {
3295 GOStyle *style = NULL;
3296 if (g_object_class_find_property (G_OBJECT_GET_CLASS (state->so), "style"))
3297 g_object_get (state->so, "style", &style, NULL);
3298 if (style) {
3299 state->cur_style = go_style_dup (style);
3300 g_object_unref (style);
3305 static void
3306 xlsx_drawing_picture (GsfXMLIn *xin, G_GNUC_UNUSED xmlChar const **attrs)
3308 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3309 state->so = g_object_new (GNM_SO_IMAGE_TYPE, NULL);
3312 static void
3313 xlsx_blip_start (GsfXMLIn *xin, xmlChar const **attrs)
3315 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3316 g_return_if_fail (GNM_IS_SO_IMAGE (state->so));
3317 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
3318 if (gsf_xml_in_namecmp (xin, attrs[0], XL_NS_DOC_REL, "embed")) {
3319 GsfOpenPkgRel const *rel = gsf_open_pkg_lookup_rel_by_id (
3320 gsf_xml_in_get_input (xin), attrs[1]);
3321 GsfInput *input = gsf_open_pkg_open_rel (
3322 gsf_xml_in_get_input (xin), rel, NULL);
3323 size_t size;
3324 gconstpointer data;
3326 g_return_if_fail (input != NULL);
3327 size = gsf_input_size (input);
3328 data = gsf_input_read (input, size, NULL);
3329 sheet_object_image_set_image (GNM_SO_IMAGE (state->so),
3330 NULL, data, size);
3331 g_object_unref (input);
3336 static GsfXMLInNode const xlsx_drawing_dtd[] = {
3337 GSF_XML_IN_NODE_FULL (START, START, -1, NULL, GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
3338 GSF_XML_IN_NODE_FULL (START, DRAWING, XL_NS_SS_DRAW, "wsDr", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
3340 GSF_XML_IN_NODE (DRAWING, TWO_CELL, XL_NS_SS_DRAW, "twoCellAnchor", GSF_XML_NO_CONTENT,
3341 &xlsx_draw_anchor_start, &xlsx_drawing_twoCellAnchor_end),
3342 GSF_XML_IN_NODE (TWO_CELL, ANCHOR_FROM, XL_NS_SS_DRAW, "from", GSF_XML_NO_CONTENT, NULL, NULL),
3343 GSF_XML_IN_NODE_FULL (ANCHOR_FROM, ANCHOR_FROM_COL, XL_NS_SS_DRAW, "col", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, FROM | COL | CELL),
3344 GSF_XML_IN_NODE_FULL (ANCHOR_FROM, ANCHOR_FROM_COL_OFF, XL_NS_SS_DRAW, "colOff", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, FROM | COL | OFFSET),
3345 GSF_XML_IN_NODE_FULL (ANCHOR_FROM, ANCHOR_FROM_ROW, XL_NS_SS_DRAW, "row", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, FROM | ROW | CELL),
3346 GSF_XML_IN_NODE_FULL (ANCHOR_FROM, ANCHOR_FROM_ROW_OFF, XL_NS_SS_DRAW, "rowOff", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, FROM | ROW | OFFSET),
3347 GSF_XML_IN_NODE (TWO_CELL, TWO_CELL_TO, XL_NS_SS_DRAW, "to", GSF_XML_NO_CONTENT, NULL, NULL),
3348 GSF_XML_IN_NODE_FULL (TWO_CELL_TO, TWO_CELL_TO_COL, XL_NS_SS_DRAW, "col", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, TO | COL | CELL),
3349 GSF_XML_IN_NODE_FULL (TWO_CELL_TO, TWO_CELL_TO_COL_OFF, XL_NS_SS_DRAW, "colOff", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, TO | COL | OFFSET),
3350 GSF_XML_IN_NODE_FULL (TWO_CELL_TO, TWO_CELL_TO_ROW, XL_NS_SS_DRAW, "row", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, TO | ROW | CELL),
3351 GSF_XML_IN_NODE_FULL (TWO_CELL_TO, TWO_CELL_TO_ROW_OFF, XL_NS_SS_DRAW, "rowOff", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_drawing_pos, TO | ROW | OFFSET),
3352 #undef FROM
3353 #undef TO
3354 #undef COL
3355 #undef ROW
3356 #undef CELL
3357 #undef OFFSET
3358 GSF_XML_IN_NODE (TWO_CELL, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL),
3359 GSF_XML_IN_NODE (SHAPE, SP_XFRM_STYLE, XL_NS_SS_DRAW, "style", GSF_XML_NO_CONTENT, NULL, NULL),
3360 GSF_XML_IN_NODE (SP_XFRM_STYLE, LN_REF, XL_NS_DRAW, "lnRef", GSF_XML_NO_CONTENT, NULL, NULL),
3361 GSF_XML_IN_NODE (LN_REF, SCHEME_CLR, XL_NS_DRAW, "schemeClr", GSF_XML_NO_CONTENT, NULL, NULL),
3362 GSF_XML_IN_NODE (LN_REF, SCRGB_CLR, XL_NS_DRAW, "scrgbClr", GSF_XML_NO_CONTENT, xlsx_draw_color_rgb, NULL),
3363 GSF_XML_IN_NODE (SP_XFRM_STYLE, FILL_REF, XL_NS_DRAW, "fillRef", GSF_XML_NO_CONTENT, NULL, NULL),
3364 GSF_XML_IN_NODE (FILL_REF, SCHEME_CLR, XL_NS_DRAW, "schemeClr", GSF_XML_NO_CONTENT, NULL, NULL),
3365 GSF_XML_IN_NODE (FILL_REF, SCRGB_CLR, XL_NS_DRAW, "scrgbClr", GSF_XML_NO_CONTENT, NULL, NULL),
3366 GSF_XML_IN_NODE (SP_XFRM_STYLE, EFFECT_REF, XL_NS_DRAW, "effectRef", GSF_XML_NO_CONTENT, NULL, NULL),
3367 GSF_XML_IN_NODE (EFFECT_REF, SCHEME_CLR, XL_NS_DRAW, "schemeClr", GSF_XML_NO_CONTENT, NULL, NULL),
3368 GSF_XML_IN_NODE (EFFECT_REF, SCRGB_CLR, XL_NS_DRAW, "scrgbClr", GSF_XML_NO_CONTENT, NULL, NULL),
3369 GSF_XML_IN_NODE (SP_XFRM_STYLE, FONT_REF, XL_NS_DRAW, "fontRef", GSF_XML_NO_CONTENT, NULL, NULL),
3370 GSF_XML_IN_NODE (FONT_REF, SCHEME_CLR, XL_NS_DRAW, "schemeClr", GSF_XML_NO_CONTENT, NULL, NULL),
3371 GSF_XML_IN_NODE (SHAPE, SHAPE_PR, XL_NS_SS_DRAW, "spPr", GSF_XML_NO_CONTENT, NULL, NULL),
3372 GSF_XML_IN_NODE (SHAPE_PR, SP_PR_PRST_GEOM, XL_NS_DRAW, "prstGeom", GSF_XML_NO_CONTENT, &xlsx_drawing_preset_geom, NULL),
3373 GSF_XML_IN_NODE (SHAPE_PR, SP_PR_XFRM, XL_NS_DRAW, "xfrm", GSF_XML_NO_CONTENT, &xlsx_sppr_xfrm, NULL),
3374 GSF_XML_IN_NODE (SP_PR_XFRM, SP_XFRM_STYLE, XL_NS_SS_DRAW, "style", GSF_XML_NO_CONTENT, NULL, NULL),
3375 GSF_XML_IN_NODE (SP_PR_XFRM, SP_XFRM_OFF, XL_NS_DRAW, "off", GSF_XML_NO_CONTENT, NULL, NULL),
3376 GSF_XML_IN_NODE (SP_XFRM_OFF, SP_PR_PRST_GEOM, XL_NS_DRAW, "prstGeom", GSF_XML_NO_CONTENT, NULL, NULL),
3377 GSF_XML_IN_NODE (SP_XFRM_OFF, SHAPE_PR_LN, XL_NS_DRAW, "ln", GSF_XML_NO_CONTENT, xlsx_style_line_start, &xlsx_style_line_end),
3378 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_NOFILL, XL_NS_DRAW, "noFill", GSF_XML_NO_CONTENT, NULL, NULL),
3379 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_DASH, XL_NS_DRAW, "prstDash", GSF_XML_NO_CONTENT, &xlsx_draw_line_dash, NULL),
3380 GSF_XML_IN_NODE (SHAPE_PR_LN, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, &xlsx_draw_solid_fill, &xlsx_draw_solid_fill_end),
3381 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_FILL_PATT, XL_NS_DRAW, "pattFill", GSF_XML_NO_CONTENT, NULL, NULL),
3382 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_MITER, XL_NS_DRAW, "miter", GSF_XML_NO_CONTENT, NULL, NULL),
3383 GSF_XML_IN_NODE (SHAPE_PR_LN, LN_ROUND, XL_NS_DRAW, "round", GSF_XML_NO_CONTENT, NULL, NULL),
3384 GSF_XML_IN_NODE_FULL (SHAPE_PR_LN, LN_HEAD, XL_NS_DRAW, "headEnd", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_draw_line_headtail, NULL, FALSE),
3385 GSF_XML_IN_NODE_FULL (SHAPE_PR_LN, LN_TAIL, XL_NS_DRAW, "tailEnd", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_draw_line_headtail, NULL, TRUE),
3386 GSF_XML_IN_NODE (SP_PR_XFRM, CHILD_OFF, XL_NS_DRAW, "chOff", GSF_XML_NO_CONTENT, NULL, NULL),
3387 GSF_XML_IN_NODE (SP_PR_XFRM, CHILD_EXT, XL_NS_DRAW, "chExt", GSF_XML_NO_CONTENT, NULL, NULL),
3388 GSF_XML_IN_NODE (SHAPE_PR, SP_FILL_NONE, XL_NS_DRAW, "noFill", GSF_XML_NO_CONTENT, NULL, NULL),
3389 GSF_XML_IN_NODE (SHAPE_PR, SP_FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL),
3390 GSF_XML_IN_NODE (FILL_SOLID, COLOR_THEMED, XL_NS_DRAW, "schemeClr", GSF_XML_NO_CONTENT, &xlsx_draw_color_themed, NULL),
3391 COLOR_MODIFIER_NODES(COLOR_THEMED,1),
3392 GSF_XML_IN_NODE (FILL_SOLID, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, &xlsx_draw_color_rgb, NULL),
3393 COLOR_MODIFIER_NODES(COLOR_THEMED,0),
3395 GSF_XML_IN_NODE (SHAPE_PR, FILL_BLIP, XL_NS_DRAW, "blipFill", GSF_XML_NO_CONTENT, NULL, NULL),
3396 GSF_XML_IN_NODE (FILL_BLIP, FILL_BLIP_BLIP, XL_NS_DRAW, "blip", GSF_XML_NO_CONTENT, NULL, NULL),
3397 GSF_XML_IN_NODE (FILL_BLIP, FILL_BLIP_SRC, XL_NS_DRAW, "srcRect", GSF_XML_NO_CONTENT, NULL, NULL),
3398 GSF_XML_IN_NODE (FILL_BLIP, FILL_BLIP_TILE, XL_NS_DRAW, "tile", GSF_XML_NO_CONTENT, NULL, NULL),
3400 GSF_XML_IN_NODE (SHAPE_PR, FILL_GRAD, XL_NS_DRAW, "gradFill", GSF_XML_NO_CONTENT, xlsx_draw_grad_fill, NULL),
3401 GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIST, XL_NS_DRAW, "gsLst", GSF_XML_NO_CONTENT, NULL, NULL),
3402 GSF_XML_IN_NODE (GRAD_LIST, GRAD_LIST_ITEM, XL_NS_DRAW, "gs", GSF_XML_NO_CONTENT, xlsx_draw_grad_stop, xlsx_draw_grad_stop_end),
3403 GSF_XML_IN_NODE (GRAD_LIST_ITEM, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3404 GSF_XML_IN_NODE (FILL_GRAD, GRAD_LIN, XL_NS_DRAW, "lin", GSF_XML_NO_CONTENT, &xlsx_draw_grad_linear, NULL),
3405 GSF_XML_IN_NODE (FILL_GRAD, GRAD_TILE, XL_NS_DRAW, "tileRect", GSF_XML_NO_CONTENT, NULL, NULL),
3407 GSF_XML_IN_NODE (SHAPE_PR, FILL_PATT, XL_NS_DRAW, "pattFill", GSF_XML_NO_CONTENT, &xlsx_draw_patt_fill, NULL),
3408 GSF_XML_IN_NODE_FULL (FILL_PATT, FILL_PATT_BG, XL_NS_DRAW, "bgClr", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_draw_patt_fill_clr, &xlsx_draw_patt_fill_clr_end, FALSE),
3409 GSF_XML_IN_NODE (FILL_PATT_BG, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3410 GSF_XML_IN_NODE_FULL (FILL_PATT, FILL_PATT_FG, XL_NS_DRAW, "fgClr", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_draw_patt_fill_clr, &xlsx_draw_patt_fill_clr_end, TRUE),
3411 GSF_XML_IN_NODE (FILL_PATT_FG, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3413 GSF_XML_IN_NODE (SHAPE_PR, SHAPE_PR_LN, XL_NS_DRAW, "ln", GSF_XML_NO_CONTENT, NULL, NULL),
3415 GSF_XML_IN_NODE (SHAPE_PR, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL),
3416 GSF_XML_IN_NODE (TEXT_PR, TEXT_PR_BODY, XL_NS_DRAW, "bodyPr", GSF_XML_NO_CONTENT, NULL, NULL),
3417 GSF_XML_IN_NODE (TEXT_PR, TEXT_PR_STYLE, XL_NS_DRAW, "lstStyle", GSF_XML_NO_CONTENT, NULL, NULL),
3418 GSF_XML_IN_NODE (TEXT_PR, TEXT_PR_P, XL_NS_DRAW, "p", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3419 GSF_XML_IN_NODE (TEXT_PR_P, TX_RICH_R, XL_NS_DRAW, "r", GSF_XML_NO_CONTENT, NULL, NULL),
3420 GSF_XML_IN_NODE (TX_RICH_R, TX_RICH_R_PR, XL_NS_DRAW, "rPr", GSF_XML_NO_CONTENT, NULL, NULL),
3421 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_CS, XL_NS_DRAW, "cs", GSF_XML_NO_CONTENT, NULL, NULL),
3422 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_EA, XL_NS_DRAW, "ea", GSF_XML_NO_CONTENT, NULL, NULL),
3423 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_LATIN, XL_NS_DRAW, "latin", GSF_XML_NO_CONTENT, &xlsx_rpr_latin, NULL),
3424 GSF_XML_IN_NODE (TX_RICH_R_PR, TEXT_FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL),
3425 GSF_XML_IN_NODE (TEXT_FILL_SOLID, COLOR_RGB, XL_NS_DRAW, "srgbClr", GSF_XML_NO_CONTENT, NULL, NULL),
3426 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_UFILLTX, XL_NS_DRAW, "uFillTx", GSF_XML_NO_CONTENT, NULL, NULL),
3427 GSF_XML_IN_NODE (TX_RICH_R_PR, PR_P_PR_DEF_ULNTX, XL_NS_DRAW, "uLnTx", GSF_XML_NO_CONTENT, NULL, NULL),
3429 GSF_XML_IN_NODE (TX_RICH_R, TX_RICH_R_T, XL_NS_DRAW, "t", GSF_XML_CONTENT, NULL, &xlsx_chart_text_content),
3430 GSF_XML_IN_NODE (TEXT_PR_P, PR_P_PR, XL_NS_DRAW, "pPr", GSF_XML_NO_CONTENT, NULL, NULL),
3431 GSF_XML_IN_NODE (PR_P_PR, PR_P_PR_DEF, XL_NS_DRAW, "defRPr", GSF_XML_NO_CONTENT, NULL, NULL),
3432 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_CS, XL_NS_DRAW, "cs", GSF_XML_NO_CONTENT, NULL, NULL),
3433 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_EA, XL_NS_DRAW, "ea", GSF_XML_NO_CONTENT, NULL, NULL),
3434 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_LATIN, XL_NS_DRAW, "latin", GSF_XML_NO_CONTENT, NULL, NULL),
3435 GSF_XML_IN_NODE (PR_P_PR_DEF, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3436 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_UFILLTX, XL_NS_DRAW, "uFillTx", GSF_XML_NO_CONTENT, NULL, NULL),
3437 GSF_XML_IN_NODE (PR_P_PR_DEF, PR_P_PR_DEF_ULNTX, XL_NS_DRAW, "uLnTx", GSF_XML_NO_CONTENT, NULL, NULL),
3438 GSF_XML_IN_NODE (TEXT_PR_P, PR_P_PR_END,XL_NS_DRAW, "endParaRPr", GSF_XML_NO_CONTENT, NULL, NULL),
3440 GSF_XML_IN_NODE (SHAPE_PR, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL),
3441 GSF_XML_IN_NODE (CXN_SP, CXN_SP_PR, XL_NS_SS_DRAW, "nvCxnSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3442 GSF_XML_IN_NODE (CXN_SP_PR, C_NV_CXN_SP, XL_NS_SS_DRAW, "cNvCxnSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3443 GSF_XML_IN_NODE (CXN_SP_PR, C_NV_PR, XL_NS_SS_DRAW, "cNvPr", GSF_XML_NO_CONTENT, NULL, NULL),
3444 GSF_XML_IN_NODE (C_NV_PR, HLINK_CLICK, XL_NS_DRAW, "hlinkClick", GSF_XML_NO_CONTENT, NULL, NULL),
3445 GSF_XML_IN_NODE (CXN_SP, SHAPE_PR, XL_NS_SS_DRAW, "spPr", GSF_XML_NO_CONTENT, NULL, NULL),
3446 GSF_XML_IN_NODE (CXN_SP, SP_XFRM_STYLE, XL_NS_SS_DRAW, "style", GSF_XML_NO_CONTENT, NULL, NULL),
3447 GSF_XML_IN_NODE (SHAPE_PR, SP_PR_PRST_GEOM, XL_NS_DRAW, "prstGeom", GSF_XML_NO_CONTENT, NULL, NULL),
3448 GSF_XML_IN_NODE (SHAPE_PR, EXTLST, XL_NS_DRAW, "extLst", GSF_XML_NO_CONTENT, NULL, NULL),
3449 GSF_XML_IN_NODE (EXTLST, EXTITEM, XL_NS_DRAW, "ext", GSF_XML_NO_CONTENT, &xlsx_ext_begin, &xlsx_ext_end),
3450 GSF_XML_IN_NODE (EXTITEM, EXT_GOSTYLE, XL_NS_GNM_EXT, "gostyle", GSF_XML_NO_CONTENT, &xlsx_ext_gostyle, NULL),
3452 GSF_XML_IN_NODE (SHAPE, TX_BODY, XL_NS_SS_DRAW, "txBody", GSF_XML_NO_CONTENT, &xlsx_chart_text_start, &xlsx_chart_text),
3453 GSF_XML_IN_NODE (TX_BODY, LST_STYLE, XL_NS_DRAW, "lstStyle", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3454 GSF_XML_IN_NODE (TX_BODY, TX_BODY_PR, XL_NS_DRAW, "bodyPr", GSF_XML_NO_CONTENT, NULL, NULL),
3455 GSF_XML_IN_NODE (TX_BODY, TEXT_PR_P, XL_NS_DRAW, "p", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3457 GSF_XML_IN_NODE (SHAPE, NV_SP_PR, XL_NS_SS_DRAW, "nvSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3458 GSF_XML_IN_NODE (NV_SP_PR, C_NV_SP_PR, XL_NS_SS_DRAW, "cNvSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3459 GSF_XML_IN_NODE (C_NV_SP_PR, SP_LOCKS, XL_NS_DRAW, "spLocks", GSF_XML_NO_CONTENT, NULL, NULL),
3460 GSF_XML_IN_NODE (NV_SP_PR, C_NV_PR, XL_NS_SS_DRAW, "cNvPr", GSF_XML_NO_CONTENT, NULL, NULL),
3462 GSF_XML_IN_NODE (SP_PR_XFRM, SP_XFRM_EXT, XL_NS_DRAW, "ext", GSF_XML_NO_CONTENT, NULL, NULL),
3463 GSF_XML_IN_NODE (SP_XFRM_EXT, SP_PR_PRST_GEOM, XL_NS_DRAW, "prstGeom", GSF_XML_NO_CONTENT, NULL, NULL),
3464 GSF_XML_IN_NODE (SP_PR_PRST_GEOM, AV_LST, XL_NS_DRAW, "avLst", GSF_XML_NO_CONTENT, NULL, NULL),
3465 GSF_XML_IN_NODE (SHAPE_PR, FILL_NONE, XL_NS_DRAW, "noFill", GSF_XML_NO_CONTENT, NULL, NULL),
3466 GSF_XML_IN_NODE (SHAPE_PR, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL),
3467 GSF_XML_IN_NODE (SHAPE_PR, FILL_BLIP, XL_NS_DRAW, "blipFill", GSF_XML_NO_CONTENT, NULL, NULL),
3468 GSF_XML_IN_NODE (SHAPE_PR, FILL_GRAD, XL_NS_DRAW, "gradFill", GSF_XML_NO_CONTENT, NULL, NULL),
3469 GSF_XML_IN_NODE (SHAPE_PR, FILL_PATT, XL_NS_DRAW, "pattFill", GSF_XML_NO_CONTENT, NULL, NULL),
3470 GSF_XML_IN_NODE (SHAPE_PR, SHAPE_PR_LN, XL_NS_DRAW, "ln", GSF_XML_NO_CONTENT, NULL, NULL),
3471 GSF_XML_IN_NODE (SHAPE_PR, TEXT_PR, XL_NS_CHART, "txPr", GSF_XML_NO_CONTENT, NULL, NULL),
3472 GSF_XML_IN_NODE (SHAPE, TX_BODY, XL_NS_SS_DRAW, "txBody", GSF_XML_NO_CONTENT, NULL, NULL),
3473 GSF_XML_IN_NODE (TX_BODY, LST_STYLE, XL_NS_DRAW, "lstStyle", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3474 GSF_XML_IN_NODE (TX_BODY, TX_BODY_PR, XL_NS_DRAW, "bodyPr", GSF_XML_NO_CONTENT, NULL, NULL),
3475 GSF_XML_IN_NODE (TX_BODY, TEXT_PR_P, XL_NS_DRAW, "p", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3477 GSF_XML_IN_NODE (SHAPE, NV_SP_PR, XL_NS_SS_DRAW, "nvSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3478 GSF_XML_IN_NODE (NV_SP_PR, C_NV_SP_PR, XL_NS_SS_DRAW, "cNvSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3479 GSF_XML_IN_NODE (C_NV_SP_PR, SP_LOCKS, XL_NS_DRAW, "spLocks", GSF_XML_NO_CONTENT, NULL, NULL),
3480 GSF_XML_IN_NODE (C_NV_SP_PR, HLINK_CLICK, XL_NS_DRAW, "hlinkClick", GSF_XML_NO_CONTENT, NULL, NULL),
3481 GSF_XML_IN_NODE (NV_SP_PR, C_NV_PR, XL_NS_SS_DRAW, "cNvPr", GSF_XML_NO_CONTENT, NULL, NULL),
3483 GSF_XML_IN_NODE (TWO_CELL, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL, NULL),
3484 GSF_XML_IN_NODE (GRAPHIC_FRAME, GRAPHIC_PR, XL_NS_SS_DRAW, "nvGraphicFramePr", GSF_XML_NO_CONTENT, NULL, NULL),
3485 GSF_XML_IN_NODE (GRAPHIC_PR, CNVPR, XL_NS_SS_DRAW, "cNvPr", GSF_XML_NO_CONTENT, NULL, NULL),
3486 GSF_XML_IN_NODE (GRAPHIC_PR, GRAPHIC_PR_CHILD, XL_NS_SS_DRAW, "cNvGraphicFramePr", GSF_XML_NO_CONTENT, NULL, NULL),
3487 GSF_XML_IN_NODE (GRAPHIC_PR_CHILD, GRAPHIC_LOCKS, XL_NS_DRAW, "graphicFrameLocks", GSF_XML_NO_CONTENT, NULL, NULL),
3488 GSF_XML_IN_NODE (GRAPHIC_FRAME, GRAPHIC, XL_NS_DRAW, "graphic", GSF_XML_NO_CONTENT, NULL, NULL),
3489 GSF_XML_IN_NODE_FULL (GRAPHIC, GRAPHIC_DATA, XL_NS_DRAW, "graphicData",
3490 GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
3491 GSF_XML_IN_NODE (GRAPHIC_DATA, CHART, XL_NS_CHART, "chart", GSF_XML_NO_CONTENT, &xlsx_read_chart, NULL),
3492 GSF_XML_IN_NODE (GRAPHIC_DATA, GRAPHIC_PR_CHILD, XL_NS_SS_DRAW, "cNvGraphicFramePr", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3493 GSF_XML_IN_NODE (GRAPHIC_FRAME, TWO_CELL_XFRM, XL_NS_SS_DRAW, "xfrm", GSF_XML_NO_CONTENT, &xlsx_sppr_xfrm, NULL),
3494 GSF_XML_IN_NODE (TWO_CELL_XFRM, XFRM_OFF, XL_NS_DRAW, "off", GSF_XML_NO_CONTENT, NULL, NULL),
3495 GSF_XML_IN_NODE (TWO_CELL_XFRM, XFRM_EXT, XL_NS_DRAW, "ext", GSF_XML_NO_CONTENT, NULL, NULL),
3496 GSF_XML_IN_NODE (TWO_CELL, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL),
3497 GSF_XML_IN_NODE (TWO_CELL, CONTENT_PART, XL_NS_SS_DRAW, "contentPart", GSF_XML_NO_CONTENT, NULL, NULL),
3498 GSF_XML_IN_NODE (TWO_CELL, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL),
3499 GSF_XML_IN_NODE (TWO_CELL, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, &xlsx_drawing_picture, NULL),
3500 GSF_XML_IN_NODE_FULL (PICTURE, PIC_FILL_BLIP, XL_NS_SS_DRAW, "blipFill", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
3501 GSF_XML_IN_NODE (PIC_FILL_BLIP, BLIP, XL_NS_DRAW, "blip", GSF_XML_NO_CONTENT, &xlsx_blip_start, NULL),
3502 GSF_XML_IN_NODE (BLIP, EXTLST, XL_NS_DRAW, "extLst", GSF_XML_NO_CONTENT, NULL, NULL),
3503 GSF_XML_IN_NODE (PIC_FILL_BLIP, BLIP_STRETCH, XL_NS_DRAW, "stretch", GSF_XML_NO_CONTENT, NULL, NULL),
3504 GSF_XML_IN_NODE (BLIP_STRETCH, BLIP_FILL_RECT, XL_NS_DRAW, "fillRect", GSF_XML_NO_CONTENT, NULL, NULL),
3505 GSF_XML_IN_NODE (PIC_FILL_BLIP, BLIP_SRC_RECT, XL_NS_DRAW, "srcRect", GSF_XML_NO_CONTENT, NULL, NULL),
3506 GSF_XML_IN_NODE (BLIP_SRC_RECT, BLIP_FILL_RECT, XL_NS_DRAW, "fillRect", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd */
3507 GSF_XML_IN_NODE (PIC_FILL_BLIP, BLIP_TILE, XL_NS_DRAW, "tile", GSF_XML_NO_CONTENT, NULL, NULL),
3508 GSF_XML_IN_NODE (PICTURE, NV_PIC_PR, XL_NS_SS_DRAW, "nvPicPr", GSF_XML_NO_CONTENT, NULL, NULL),
3509 GSF_XML_IN_NODE (NV_PIC_PR, C_NV_PIC_PR, XL_NS_SS_DRAW, "cNvPicPr", GSF_XML_NO_CONTENT, NULL, NULL),
3510 GSF_XML_IN_NODE (C_NV_PIC_PR, PIC_LOCKS, XL_NS_DRAW, "picLocks", GSF_XML_NO_CONTENT, NULL, NULL),
3511 GSF_XML_IN_NODE (NV_PIC_PR, C_NV_PR, XL_NS_SS_DRAW, "cNvPr", GSF_XML_NO_CONTENT, NULL, NULL),
3512 GSF_XML_IN_NODE (PICTURE, SHAPE_PR, XL_NS_SS_DRAW, "spPr", GSF_XML_NO_CONTENT, NULL, NULL),
3513 GSF_XML_IN_NODE (PICTURE, SP_XFRM_STYLE, XL_NS_SS_DRAW, "style", GSF_XML_NO_CONTENT, NULL, NULL),
3514 GSF_XML_IN_NODE (TWO_CELL, GROUP_SP, XL_NS_SS_DRAW, "grpSp", GSF_XML_NO_CONTENT, NULL, NULL),
3515 GSF_XML_IN_NODE (GROUP_SP, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL),
3516 GSF_XML_IN_NODE (GROUP_SP, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL),
3517 GSF_XML_IN_NODE (GROUP_SP, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, NULL, NULL),
3518 GSF_XML_IN_NODE (GROUP_SP, GROUP_SP_PR, XL_NS_SS_DRAW, "grpSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3519 GSF_XML_IN_NODE (GROUP_SP_PR, PIC_FILL_BLIP, XL_NS_SS_DRAW, "blipFill", GSF_XML_NO_CONTENT, NULL, NULL),
3520 GSF_XML_IN_NODE (GROUP_SP_PR, EFFECT_DAG, XL_NS_SS_DRAW, "effectDag", GSF_XML_NO_CONTENT, NULL, NULL),
3521 GSF_XML_IN_NODE (GROUP_SP_PR, EFFECT_LST, XL_NS_SS_DRAW, "effectLst", GSF_XML_NO_CONTENT, NULL, NULL),
3522 GSF_XML_IN_NODE (GROUP_SP_PR, EXT_LST, XL_NS_SS_DRAW, "extLst", GSF_XML_NO_CONTENT, NULL, NULL),
3523 GSF_XML_IN_NODE (GROUP_SP_PR, FILL_GRAD, XL_NS_DRAW, "gradFill", GSF_XML_NO_CONTENT, NULL, NULL),
3524 GSF_XML_IN_NODE (GROUP_SP_PR, FILL_GRP, XL_NS_DRAW, "grpFill", GSF_XML_NO_CONTENT, NULL, NULL),
3525 GSF_XML_IN_NODE (GROUP_SP_PR, FILL_NONE, XL_NS_DRAW, "noFill", GSF_XML_NO_CONTENT, NULL, NULL),
3526 GSF_XML_IN_NODE (GROUP_SP_PR, FILL_PATT, XL_NS_DRAW, "pattFill", GSF_XML_NO_CONTENT, NULL, NULL),
3527 GSF_XML_IN_NODE (GROUP_SP_PR, SCENE3D, XL_NS_DRAW, "scene3d", GSF_XML_NO_CONTENT, NULL, NULL),
3528 GSF_XML_IN_NODE (GROUP_SP_PR, FILL_SOLID, XL_NS_DRAW, "solidFill", GSF_XML_NO_CONTENT, NULL, NULL),
3529 GSF_XML_IN_NODE (GROUP_SP_PR, SP_PR_XFRM, XL_NS_DRAW, "xfrm", GSF_XML_NO_CONTENT, NULL, NULL),
3530 GSF_XML_IN_NODE (GROUP_SP, GROUP_SP, XL_NS_SS_DRAW, "grpSp", GSF_XML_NO_CONTENT, NULL, NULL),
3531 GSF_XML_IN_NODE (GROUP_SP, NV_GRP_SP_PR, XL_NS_SS_DRAW, "nvGrpSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3532 GSF_XML_IN_NODE (NV_GRP_SP_PR, C_NV_GRP_SP_PR, XL_NS_SS_DRAW, "cNvGrpSpPr", GSF_XML_NO_CONTENT, NULL, NULL),
3533 GSF_XML_IN_NODE (NV_GRP_SP_PR, C_NV_PR, XL_NS_SS_DRAW, "cNvPr", GSF_XML_NO_CONTENT, NULL, NULL),
3534 GSF_XML_IN_NODE (GROUP_SP, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL, NULL),
3536 GSF_XML_IN_NODE (DRAWING, ONE_CELL, XL_NS_SS_DRAW, "oneCellAnchor", GSF_XML_NO_CONTENT,
3537 &xlsx_draw_anchor_start, &xlsx_drawing_oneCellAnchor_end),
3538 GSF_XML_IN_NODE (ONE_CELL, ANCHOR_FROM, XL_NS_SS_DRAW, "from", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3539 GSF_XML_IN_NODE (ONE_CELL, ONE_CELL_EXT, XL_NS_SS_DRAW, "ext", GSF_XML_NO_CONTENT, &xlsx_drawing_ext, NULL),
3540 GSF_XML_IN_NODE (ONE_CELL, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3541 GSF_XML_IN_NODE (ONE_CELL, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3542 GSF_XML_IN_NODE (ONE_CELL, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3543 GSF_XML_IN_NODE (ONE_CELL, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3544 GSF_XML_IN_NODE (ONE_CELL, CONTENT_PART, XL_NS_SS_DRAW, "contentPart", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3545 GSF_XML_IN_NODE (ONE_CELL, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3546 GSF_XML_IN_NODE (ONE_CELL, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3547 GSF_XML_IN_NODE (DRAWING, ABSOLUTE, XL_NS_SS_DRAW, "absoluteAnchor", GSF_XML_NO_CONTENT,
3548 &xlsx_draw_anchor_start, &xlsx_drawing_absoluteAnchor_end),
3549 GSF_XML_IN_NODE (ABSOLUTE, ABSOLUTE_POS, XL_NS_SS_DRAW, "pos", GSF_XML_NO_CONTENT, &xlsx_drawing_anchor_pos, NULL),
3550 GSF_XML_IN_NODE (ABSOLUTE, ONE_CELL_EXT, XL_NS_SS_DRAW, "ext", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3551 GSF_XML_IN_NODE (ABSOLUTE, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3552 GSF_XML_IN_NODE (ABSOLUTE, GRAPHIC_FRAME, XL_NS_SS_DRAW, "graphicFrame", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3553 GSF_XML_IN_NODE (ABSOLUTE, SHAPE, XL_NS_SS_DRAW, "sp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3554 GSF_XML_IN_NODE (ABSOLUTE, CLIENT_DATA, XL_NS_SS_DRAW, "clientData", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3555 GSF_XML_IN_NODE (ABSOLUTE, CONTENT_PART, XL_NS_SS_DRAW, "contentPart", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3556 GSF_XML_IN_NODE (ABSOLUTE, CXN_SP, XL_NS_SS_DRAW, "cxnSp", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3557 GSF_XML_IN_NODE (ABSOLUTE, PICTURE, XL_NS_SS_DRAW, "pic", GSF_XML_NO_CONTENT, NULL, NULL), /* 2nd Def */
3558 GSF_XML_IN_NODE_END
3561 static void
3562 xlsx_sheet_drawing (GsfXMLIn *xin, xmlChar const **attrs)
3564 xmlChar const *part_id = NULL;
3565 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
3566 if (gsf_xml_in_namecmp (xin, attrs[0], XL_NS_DOC_REL, "id"))
3567 part_id = attrs[1];
3568 if (NULL != part_id)
3569 xlsx_parse_rel_by_id (xin, part_id, xlsx_drawing_dtd, xlsx_ns);
3572 /******************************************************************************
3573 * Legacy drawing, just need to import, but should not be exported *
3574 ******************************************************************************/
3576 /* define an approximate horizontal scale factor to align controls with cells */
3577 #define XLSX_SHEET_HSCALE 1.165
3579 static void
3580 xlsx_vml_group (GsfXMLIn *xin, xmlChar const **attrs)
3582 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3583 char **elts, **cur, *key, *value, *end;
3584 double coords[4], local_coords[4], *cur_offs;
3585 int i;
3586 for (i = 0; i < 4; i++)
3587 coords[i] = local_coords[i] = 0.;
3588 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
3589 if (!strcmp (attrs[0], "style")) {
3590 elts = g_strsplit (attrs[1], ";", 0);
3591 for (cur = elts; *cur; cur++) {
3592 value = strchr (*cur, ':');
3593 if (!value)
3594 continue; /* Hope this does not occur */
3595 *value = 0;
3596 value++;
3597 key = *cur;
3598 while (g_ascii_isspace (*key))
3599 key++;
3600 /* *cur is now the field name and sep is the associated value */
3601 /* for now we get only left, top, width and height, assuming they are in pixels */
3602 /* FIXME: scaling just like in xlsx_CT_Col */
3603 if (!strcmp (key, "margin-left") || !strcmp (key, "left")) {
3604 double dim = g_ascii_strtod (value, &end);
3605 if (!strcmp (end, "pt"))
3606 dim *= 4./3.;
3607 coords[0] = (double) dim * XLSX_SHEET_HSCALE;
3608 } else if (!strcmp (key, "margin-top") || !strcmp (key, "top")) {
3609 double dim = g_ascii_strtod (value, &end);
3610 if (!strcmp (end, "pt"))
3611 dim *= 4./3.;
3612 coords[1] = dim;
3613 } else if (!strcmp (key, "width")) {
3614 double dim = g_ascii_strtod (value, &end);
3615 if (!strcmp (end, "pt"))
3616 dim *= 4./3.;
3617 coords[2] = (double) dim * XLSX_SHEET_HSCALE;
3618 } else if (!strcmp (key, "height")) {
3619 double dim = g_ascii_strtod (value, &end);
3620 if (!strcmp (end, "pt"))
3621 dim *= 4./3.;
3622 coords[3] = dim;
3625 g_strfreev (elts);
3626 } else if (!strcmp (attrs[0], "coordorigin")) {
3627 local_coords[0] = strtol (attrs[1], &end, 10) * XLSX_SHEET_HSCALE;
3628 if (*end == ',')
3629 local_coords[1] = strtol (end + 1, &end, 10);
3630 } else if (!strcmp (attrs[0], "coordsize")) {
3631 local_coords[2] = strtol (attrs[1], &end, 10) * XLSX_SHEET_HSCALE;
3632 if (*end == ',')
3633 local_coords[3] = strtol (end + 1, &end, 10);
3635 /* setting the group local transform */
3636 cur_offs = g_new (double, 4);
3637 memcpy (cur_offs, state->grp_offset, sizeof (double) * 4);
3638 state->grp_stack = g_slist_prepend (state->grp_stack, cur_offs);
3639 /* evaluate new tranform */
3640 if (cur_offs[2] != 0.) {
3641 state->grp_offset[2] = coords[2] / local_coords[2] * cur_offs[2];
3642 state->grp_offset[0] = coords[0] - local_coords[0] + cur_offs[0];
3643 state->grp_offset[3] = coords[3] / local_coords[3] * cur_offs[3];
3644 state->grp_offset[1] = coords[1] - local_coords[1] + cur_offs[1];
3645 } else {
3646 /* Not sure if the offset should be multiplied by the scale, don't do that, all known sample have unit scales */
3647 state->grp_offset[2] = coords[2] / local_coords[2];
3648 state->grp_offset[0] = coords[0] - local_coords[0];
3649 state->grp_offset[3] = coords[3] / local_coords[3];
3650 state->grp_offset[1] = coords[1] - local_coords[1];
3654 static void
3655 xlsx_vml_group_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3657 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3658 /* assuming that a group can't be inside another group, otherwise we need a stack */
3659 memcpy (state->grp_offset, state->grp_stack->data, sizeof (double) * 4);
3660 g_free (state->grp_stack->data);
3661 state->grp_stack = g_slist_delete_link (state->grp_stack, state->grp_stack);
3664 static void
3665 xlsx_vml_shape (GsfXMLIn *xin, xmlChar const **attrs)
3667 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3668 int z = -1;
3670 xlsx_reset_chart_pos (state);
3672 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
3673 if (!strcmp (attrs[0], "style")) {
3674 char **elts = g_strsplit (attrs[1], ";", 0), **cur;
3675 for (cur = elts; *cur; cur++) {
3676 double dim;
3677 char *key, *end;
3678 char *value = strchr (*cur, ':');
3679 if (!value)
3680 continue; /* Hope this does not occur */
3681 *value = 0;
3682 value++;
3683 key = *cur;
3684 while (g_ascii_isspace (*key))
3685 key++;
3686 /* *cur is now the field name and sep is the associated value */
3687 /* for now we get only left, top, width and height, assuming they are in pixels */
3688 /* FIXME: scaling just like in xlsx_CT_Col */
3689 if (!strcmp (key, "margin-left") || !strcmp (key, "left")) {
3690 dim = g_ascii_strtod (value, &end);
3691 state->chart_pos[0] = dim;
3692 } else if (!strcmp (key, "margin-top") || !strcmp (key, "top")) {
3693 dim = g_ascii_strtod (value, &end);
3694 state->chart_pos[1] = dim;
3695 } else if (!strcmp (key, "width")) {
3696 dim = g_ascii_strtod (value, &end);
3697 state->chart_pos[2] = dim;
3698 } else if (!strcmp (key, "height")) {
3699 dim = g_ascii_strtod (value, &end);
3700 state->chart_pos[3] = dim;
3701 } else if (!strcmp (key, "z-index")) {
3702 z = strtol (value, &end, 10);
3705 g_strfreev (elts);
3706 if (state->grp_offset[2] != 0.) {
3707 state->chart_pos[0] += state->grp_offset[0];
3708 state->chart_pos[1] += state->grp_offset[1];
3709 state->chart_pos[2] *= state->grp_offset[2];
3710 state->chart_pos[3] *= state->grp_offset[3];
3712 state->chart_pos[2] += state->chart_pos[0];
3713 state->chart_pos[3] += state->chart_pos[1];
3717 state->zindex = z;
3720 static void
3721 xlsx_vml_drop_style (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3725 static void
3726 xlsx_vml_client_data_start (GsfXMLIn *xin, xmlChar const **attrs)
3728 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3729 GType typ = G_TYPE_NONE;
3730 const char *tname = NULL;
3732 static EnumVal const types[] = {
3733 { "Scroll", 0 },
3734 { "Radio", 1 },
3735 { "Spin", 2 },
3736 { "Button", 3 },
3737 { "Checkbox", 4 },
3738 { "Note", 5 },
3739 { "Dialog", 6 },
3740 { "Drop", 7 },
3741 { "Edit", 8 },
3742 { "GBox", 9 },
3743 { "Label", 10 },
3744 { "LineA", 11 },
3745 { "List", 12 },
3746 { "Movie", 13 },
3747 { "Pict", 14 },
3748 { "RectA", 15 },
3749 { "Shape", 16 },
3750 { "Group", 17 },
3751 { "Rect", 18 },
3752 { NULL, 0 }
3754 static GType gtypes[G_N_ELEMENTS(types) - 1];
3756 if (!gtypes[0]) {
3757 int i = 0;
3758 gtypes[i++] = GNM_SOW_SCROLLBAR_TYPE;
3759 gtypes[i++] = GNM_SOW_RADIO_BUTTON_TYPE;
3760 gtypes[i++] = GNM_SOW_SPIN_BUTTON_TYPE;
3761 gtypes[i++] = GNM_SOW_BUTTON_TYPE;
3762 gtypes[i++] = GNM_SOW_CHECKBOX_TYPE;
3763 gtypes[i++] = G_TYPE_NONE;
3764 gtypes[i++] = G_TYPE_NONE;
3765 gtypes[i++] = GNM_SOW_COMBO_TYPE;
3766 gtypes[i++] = G_TYPE_NONE;
3767 gtypes[i++] = G_TYPE_NONE;
3768 gtypes[i++] = G_TYPE_NONE;
3769 gtypes[i++] = G_TYPE_NONE;
3770 gtypes[i++] = GNM_SOW_LIST_TYPE;
3771 gtypes[i++] = G_TYPE_NONE;
3772 gtypes[i++] = G_TYPE_NONE;
3773 gtypes[i++] = G_TYPE_NONE;
3774 gtypes[i++] = G_TYPE_NONE;
3775 gtypes[i++] = G_TYPE_NONE;
3778 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2) {
3779 int tmp;
3780 if (attr_enum (xin, attrs, "ObjectType", types, &tmp)) {
3781 typ = gtypes[tmp];
3782 tname = attrs[1];
3786 if (state->so) {
3787 g_warning ("New object when one is in progress.");
3788 } else if (typ == G_TYPE_NONE) {
3789 g_printerr ("Unhandled object of type %s\n", tname);
3790 } else {
3791 state->so = GNM_SO (g_object_new (typ, NULL));
3792 state->so_direction = GOD_ANCHOR_DIR_DOWN_RIGHT;
3793 state->pending_objects = g_slist_prepend (state->pending_objects, state->so);
3794 if (state->zindex >= 1)
3795 g_hash_table_insert (state->zorder, state->so, GINT_TO_POINTER (state->zindex));
3799 static void
3800 xlsx_vml_client_data_end (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3802 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3803 if (state->so) {
3804 SheetObjectAnchor anchor;
3805 GnmRange r;
3806 double coords[4];
3807 Sheet *sheet = state->sheet;
3808 int cols = gnm_sheet_get_max_cols (sheet);
3809 int rows = gnm_sheet_get_max_rows (sheet);
3810 int i, pos;
3811 double sum, size;
3813 for (i = 0; i < 4; i++)
3814 if (!go_finite (state->chart_pos[i]))
3815 state->chart_pos[i] = 0;
3817 size = sum = 0;
3818 for (pos = 0; pos < cols; pos++) {
3819 size = sheet_col_get_distance_pts (sheet, pos, pos + 1);
3820 if (sum + size > state->chart_pos[0])
3821 break;
3822 sum += size;
3824 r.start.col = pos;
3825 coords[0] = (state->chart_pos[0] - sum) / size;
3826 while (sum < state->chart_pos[2] && pos < cols) {
3827 if (sum + size > state->chart_pos[2])
3828 break;
3829 sum += size;
3830 size = sheet_col_get_distance_pts (sheet, pos, pos + 1);
3831 pos++;
3833 r.end.col = pos;
3834 coords[2] = (state->chart_pos[2] - sum) / size;
3836 size = sum = 0;
3837 for (pos = 0; pos < cols; pos++) {
3838 size = sheet_row_get_distance_pts (sheet, pos, pos + 1);
3839 if (sum + size > state->chart_pos[1])
3840 break;
3841 sum += size;
3843 r.start.row = pos;
3844 coords[1] = (state->chart_pos[1] - sum) / size;
3845 while (sum < state->chart_pos[3] && pos < rows) {
3846 if (sum + size > state->chart_pos[3])
3847 break;
3848 sum += size;
3849 size = sheet_row_get_distance_pts (sheet, pos, pos + 1);
3850 pos++;
3852 r.end.row = pos;
3853 coords[3] = (state->chart_pos[3] - sum) / size;
3854 sheet_object_anchor_init (&anchor, &r, coords, state->so_direction, state->so_anchor_mode);
3855 sheet_object_set_anchor (state->so, &anchor);
3856 if (GNM_IS_SOW_LIST (state->so) ||
3857 GNM_IS_SOW_COMBO (state->so))
3858 sheet_widget_list_base_set_links (state->so, state->link_texpr, state->texpr);
3859 else if (GNM_IS_SOW_SCROLLBAR (state->so) ||
3860 GNM_IS_SOW_SPINBUTTON (state->so) ||
3861 GNM_IS_SOW_SLIDER (state->so))
3862 sheet_widget_adjustment_set_link (state->so, state->link_texpr);
3863 else if (GNM_IS_SOW_RADIO_BUTTON (state->so)) {
3864 GnmValue *v = value_new_int (state->radio_value++);
3865 sheet_widget_radio_button_set_link (state->so, state->link_texpr);
3866 sheet_widget_radio_button_set_value (state->so, v);
3867 value_release (v);
3869 else if (GNM_IS_SOW_BUTTON (state->so))
3870 sheet_widget_button_set_link (state->so, state->link_texpr);
3871 else if (GNM_IS_SOW_CHECKBOX (state->so))
3872 sheet_widget_checkbox_set_link (state->so, state->link_texpr);
3874 if (state->chart_tx &&
3875 g_object_class_find_property (G_OBJECT_GET_CLASS (state->so), "text") != NULL)
3876 g_object_set (state->so, "text", state->chart_tx, NULL);
3878 state->so = NULL;
3880 if (state->texpr) {
3881 gnm_expr_top_unref (state->texpr);
3882 state->texpr = NULL;
3884 if (state->link_texpr) {
3885 gnm_expr_top_unref (state->link_texpr);
3886 state->link_texpr = NULL;
3889 g_free (state->chart_tx);
3890 state->chart_tx = NULL;
3893 static void
3894 xlsx_vml_firstbutton (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3896 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3897 state->radio_value = 1;
3900 static void
3901 xlsx_vml_fmla_link (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3903 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3904 GnmParsePos pp;
3905 GnmValue *value;
3907 parse_pos_init_sheet (&pp, state->sheet);
3908 value = value_new_cellrange_parsepos_str (&pp, xin->content->str, 0);
3909 if (value)
3910 state->link_texpr = gnm_expr_top_new_constant (value);
3913 static void
3914 xlsx_vml_fmla_range (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3916 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3917 GnmParsePos pp;
3918 GnmValue *value;
3920 parse_pos_init_sheet (&pp, state->sheet);
3921 value = value_new_cellrange_parsepos_str (&pp, xin->content->str, 0);
3922 if (value)
3923 state->texpr = gnm_expr_top_new_constant (value);
3926 static void
3927 xlsx_vml_horiz (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3929 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3930 if (state->so) {
3931 const char *s = xin->content->str;
3932 gboolean horiz;
3933 if (g_ascii_toupper (s[0]) == 'T')
3934 horiz = TRUE;
3935 else if (g_ascii_toupper (s[0]) == 'F')
3936 horiz = FALSE;
3937 else
3938 return; /* Blank means default. */
3939 sheet_widget_adjustment_set_horizontal (state->so, horiz);
3943 static void
3944 xlsx_vml_adj (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3946 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3947 if (GNM_IS_SOW_ADJUSTMENT (state->so)) {
3948 GtkAdjustment *adj = sheet_widget_adjustment_get_adjustment (state->so);
3949 double x = g_ascii_strtod (xin->content->str, NULL);
3950 switch (xin->node->user_data.v_int) {
3951 case 0: gtk_adjustment_set_lower (adj, x); break;
3952 case 1: gtk_adjustment_set_upper (adj, x); break;
3953 case 2: gtk_adjustment_set_step_increment (adj, x); break;
3954 case 3: gtk_adjustment_set_page_increment (adj, x); break;
3955 case 4: gtk_adjustment_set_value (adj, x); break;
3956 default: break;
3961 static void
3962 xlsx_vml_textbox_div (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3964 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3965 const char *text = xin->content->str;
3966 char *newtext = state->chart_tx
3967 ? g_strconcat (state->chart_tx, text, NULL)
3968 : g_strdup (text);
3969 g_free (state->chart_tx);
3970 state->chart_tx = newtext;
3973 static void
3974 xlsx_vml_checked (GsfXMLIn *xin, G_GNUC_UNUSED GsfXMLBlob *blob)
3976 XLSXReadState *state = (XLSXReadState *)xin->user_state;
3977 const char *s = xin->content->str;
3978 gboolean checked = strtol (s, NULL, 10) > 0;
3980 if (GNM_IS_SOW_CHECKBOX (state->so) ||
3981 GNM_IS_SOW_RADIO_BUTTON (state->so)) {
3982 g_object_set (state->so, "active", checked, NULL);
3988 static GsfXMLInNode const xlsx_legacy_drawing_dtd[] = {
3989 GSF_XML_IN_NODE_FULL (START, START, -1, NULL, GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
3990 GSF_XML_IN_NODE_FULL (START, SP_LAYOUT, XL_NS_LEG_OFF, "shapelayout", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
3991 GSF_XML_IN_NODE (SP_LAYOUT, IDMAP, XL_NS_LEG_OFF, "idmap", GSF_XML_NO_CONTENT, NULL, NULL),
3992 GSF_XML_IN_NODE (SP_LAYOUT, REGROUPTABLE, XL_NS_LEG_OFF, "regrouptable", GSF_XML_NO_CONTENT, NULL, NULL),
3993 GSF_XML_IN_NODE (REGROUPTABLE, ENTRY, XL_NS_LEG_OFF, "entry", GSF_XML_NO_CONTENT, NULL, NULL),
3994 GSF_XML_IN_NODE_FULL (START, SP_TYPE, XL_NS_LEG_VML, "shapetype", GSF_XML_NO_CONTENT, FALSE, TRUE, NULL, NULL, 0),
3995 GSF_XML_IN_NODE (SP_TYPE, PATH, XL_NS_LEG_VML, "path", GSF_XML_NO_CONTENT, NULL, NULL),
3996 GSF_XML_IN_NODE (SP_TYPE, STROKE, XL_NS_LEG_VML, "stroke", GSF_XML_NO_CONTENT, NULL, NULL),
3997 GSF_XML_IN_NODE (SP_TYPE, LOCK, XL_NS_LEG_OFF, "lock", GSF_XML_NO_CONTENT, NULL, NULL),
3998 GSF_XML_IN_NODE_FULL (START, SP, XL_NS_LEG_VML, "shape", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_vml_shape, NULL, 0),
3999 GSF_XML_IN_NODE (SP, FILL, XL_NS_LEG_VML, "fill", GSF_XML_NO_CONTENT, NULL, NULL),
4000 GSF_XML_IN_NODE (SP, PATH, XL_NS_LEG_VML, "path", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4001 GSF_XML_IN_NODE (SP, SHADOW, XL_NS_LEG_VML, "shadow", GSF_XML_NO_CONTENT, NULL, NULL),
4002 GSF_XML_IN_NODE (SP, STROKE, XL_NS_LEG_VML, "stroke", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4003 GSF_XML_IN_NODE (SP, TEXTBOX, XL_NS_LEG_VML, "textbox", GSF_XML_NO_CONTENT, NULL, NULL),
4004 GSF_XML_IN_NODE (TEXTBOX, DIV, -1, "div", GSF_XML_CONTENT, NULL, &xlsx_vml_textbox_div),
4005 GSF_XML_IN_NODE (SP, LOCK, XL_NS_LEG_OFF, "lock", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4006 GSF_XML_IN_NODE (SP, CLIENT_DATA, XL_NS_LEG_XL, "ClientData", GSF_XML_NO_CONTENT, &xlsx_vml_client_data_start, &xlsx_vml_client_data_end),
4007 GSF_XML_IN_NODE (CLIENT_DATA, ANCHOR, XL_NS_LEG_XL, "Anchor", GSF_XML_NO_CONTENT, NULL, NULL),
4008 GSF_XML_IN_NODE (CLIENT_DATA, AUTO_FILL, XL_NS_LEG_XL, "AutoFill", GSF_XML_NO_CONTENT, NULL, NULL),
4009 GSF_XML_IN_NODE (CLIENT_DATA, AUTO_LINE, XL_NS_LEG_XL, "AutoLine", GSF_XML_NO_CONTENT, NULL, NULL),
4010 GSF_XML_IN_NODE (CLIENT_DATA, CHECKED, XL_NS_LEG_XL, "Checked", GSF_XML_CONTENT, NULL, &xlsx_vml_checked),
4011 GSF_XML_IN_NODE (CLIENT_DATA, COLUMN, XL_NS_LEG_XL, "Column", GSF_XML_NO_CONTENT, NULL, NULL),
4012 GSF_XML_IN_NODE (CLIENT_DATA, DROP_LINES, XL_NS_LEG_XL, "DropLines", GSF_XML_NO_CONTENT, NULL, NULL),
4013 GSF_XML_IN_NODE (CLIENT_DATA, DROP_STYLE, XL_NS_LEG_XL, "DropStyle", GSF_XML_CONTENT, NULL, &xlsx_vml_drop_style),
4014 GSF_XML_IN_NODE (CLIENT_DATA, DX, XL_NS_LEG_XL, "Dx", GSF_XML_NO_CONTENT, NULL, NULL),
4015 GSF_XML_IN_NODE (CLIENT_DATA, FIRSTBUTTON, XL_NS_LEG_XL, "FirstButton", GSF_XML_CONTENT, NULL, &xlsx_vml_firstbutton),
4016 GSF_XML_IN_NODE (CLIENT_DATA, FMLA_LINK, XL_NS_LEG_XL, "FmlaLink", GSF_XML_CONTENT, NULL, &xlsx_vml_fmla_link),
4017 GSF_XML_IN_NODE (CLIENT_DATA, FMLA_RANGE, XL_NS_LEG_XL, "FmlaRange", GSF_XML_CONTENT, NULL, &xlsx_vml_fmla_range),
4018 GSF_XML_IN_NODE (CLIENT_DATA, HORIZ, XL_NS_LEG_XL, "Horiz", GSF_XML_CONTENT, NULL, &xlsx_vml_horiz),
4019 GSF_XML_IN_NODE_FULL (CLIENT_DATA, INC, XL_NS_LEG_XL, "Inc", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_vml_adj, 2),
4020 GSF_XML_IN_NODE (CLIENT_DATA, LCT, XL_NS_LEG_XL, "LCT", GSF_XML_NO_CONTENT, NULL, NULL),
4021 GSF_XML_IN_NODE_FULL (CLIENT_DATA, XMIN, XL_NS_LEG_XL, "Min", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_vml_adj, 0),
4022 GSF_XML_IN_NODE_FULL (CLIENT_DATA, XMAX, XL_NS_LEG_XL, "Max", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_vml_adj, 1),
4023 GSF_XML_IN_NODE (CLIENT_DATA, MOVE_WITH_CELLS, XL_NS_LEG_XL, "MoveWithCells", GSF_XML_NO_CONTENT, NULL, NULL),
4024 GSF_XML_IN_NODE_FULL (CLIENT_DATA, PAGE, XL_NS_LEG_XL, "Page", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_vml_adj, 3),
4025 GSF_XML_IN_NODE (CLIENT_DATA, PRINT_OBJECT, XL_NS_LEG_XL, "PrintObject", GSF_XML_NO_CONTENT, NULL, NULL),
4026 GSF_XML_IN_NODE (CLIENT_DATA, RECALC_ALWAYS, XL_NS_LEG_XL, "RecalcAlways", GSF_XML_NO_CONTENT, NULL, NULL),
4027 GSF_XML_IN_NODE (CLIENT_DATA, ROW, XL_NS_LEG_XL, "Row", GSF_XML_NO_CONTENT, NULL, NULL),
4028 GSF_XML_IN_NODE (CLIENT_DATA, SEL, XL_NS_LEG_XL, "Sel", GSF_XML_NO_CONTENT, NULL, NULL),
4029 GSF_XML_IN_NODE (CLIENT_DATA, SEL_TYPE, XL_NS_LEG_XL, "SelType", GSF_XML_NO_CONTENT, NULL, NULL),
4030 GSF_XML_IN_NODE (CLIENT_DATA, SIZE_WITH_CELLS, XL_NS_LEG_XL, "SizeWithCells", GSF_XML_NO_CONTENT, NULL, NULL),
4031 GSF_XML_IN_NODE_FULL (CLIENT_DATA, VAL, XL_NS_LEG_XL, "Val", GSF_XML_CONTENT, FALSE, TRUE, NULL, &xlsx_vml_adj, 4),
4032 GSF_XML_IN_NODE_FULL (START, GROUP, XL_NS_LEG_VML, "group", GSF_XML_NO_CONTENT, FALSE, TRUE, &xlsx_vml_group, &xlsx_vml_group_end, 0),
4033 GSF_XML_IN_NODE (GROUP, LOCK, XL_NS_LEG_OFF, "lock", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4034 GSF_XML_IN_NODE (LOCK, SP, XL_NS_LEG_VML, "shape", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4035 GSF_XML_IN_NODE (GROUP, GROUP, XL_NS_LEG_VML, "group", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4036 GSF_XML_IN_NODE (GROUP, SP, XL_NS_LEG_VML, "shape", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4037 GSF_XML_IN_NODE (GROUP, SP_TYPE, XL_NS_LEG_VML, "shapetype", GSF_XML_NO_CONTENT, NULL, NULL), /* already defined */
4038 GSF_XML_IN_NODE_END
4041 static void
4042 xlsx_sheet_legacy_drawing (GsfXMLIn *xin, xmlChar const **attrs)
4044 xmlChar const *part_id = NULL;
4045 for (; attrs != NULL && attrs[0] && attrs[1] ; attrs += 2)
4046 if (gsf_xml_in_namecmp (xin, attrs[0], XL_NS_DOC_REL, "id"))
4047 part_id = attrs[1];
4048 if (NULL != part_id) {
4049 XLSXReadState *state = (XLSXReadState *)xin->user_state;
4050 state->radio_value = 1;
4051 xlsx_parse_rel_by_id (xin, part_id, xlsx_legacy_drawing_dtd, xlsx_ns);