]> git.sur5r.net Git - glabels/blob - glabels2/src/xml-label-191.c
Added compatability parser for files generated with 1.91.
[glabels] / glabels2 / src / xml-label-191.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  label.c:  GLabels xml label 1.91 compat module
5  *
6  *  Copyright (C) 2001-2002  Jim Evins <evins@snaught.com>.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <config.h>
24
25 #include <gnome.h>
26
27 #include <libxml/tree.h>
28 #include <libxml/parser.h>
29 #include <gdk-pixbuf/gdk-pixdata.h>
30
31 #include "label.h"
32 #include "label-object.h"
33 #include "label-text.h"
34 #include "label-box.h"
35 #include "label-line.h"
36 #include "label-ellipse.h"
37 #include "label-image.h"
38 #include "label-barcode.h"
39 #include "paper.h"
40 #include "template.h"
41 #include "base64.h"
42 #include "xml-label.h"
43 #include "xml-label-04.h"
44 #include "xml-template.h"
45 #include "xml.h"
46 #include "util.h"
47
48 #include "debug.h"
49
50 /*========================================================*/
51 /* Private macros and constants.                          */
52 /*========================================================*/
53
54 /*========================================================*/
55 /* Private types.                                         */
56 /*========================================================*/
57
58 /*========================================================*/
59 /* Private globals.                                       */
60 /*========================================================*/
61
62 /*========================================================*/
63 /* Private function prototypes.                           */
64 /*========================================================*/
65
66 static void           xml191_parse_objects        (xmlNodePtr        node,
67                                                    glLabel          *label);
68
69 static void           xml191_parse_object         (xmlNodePtr        node,
70                                                    glLabel          *label);
71
72 static glLabelObject *xml191_parse_text_props     (xmlNodePtr        node,
73                                                    glLabel          *label);
74
75 static glLabelObject *xml191_parse_box_props      (xmlNodePtr        node,
76                                                    glLabel          *label);
77
78 static glLabelObject *xml191_parse_line_props     (xmlNodePtr        node,
79                                                    glLabel          *label);
80
81 static glLabelObject *xml191_parse_ellipse_props  (xmlNodePtr        node,
82                                                    glLabel          *label);
83
84 static glLabelObject *xml191_parse_image_props    (xmlNodePtr        node,
85                                                    glLabel          *label);
86
87 static glLabelObject *xml191_parse_barcode_props  (xmlNodePtr        node,
88                                                    glLabel          *label);
89
90 static void           xml191_parse_merge_fields   (xmlNodePtr        node,
91                                                    glLabel          *label);
92
93 static void           xml191_parse_data           (xmlNodePtr        node,
94                                                    glLabel          *label);
95
96 static void           xml191_parse_pixdata        (xmlNodePtr        node,
97                                                    glLabel          *label);
98
99 static glTemplate    *xml191_parse_sheet          (xmlNodePtr        node);
100
101 static void           xml191_parse_label          (xmlNodePtr        label_node,
102                                                    glTemplate       *template);
103
104 static void           xml191_parse_layout         (xmlNodePtr        layout_node,
105                                                    glTemplate       *template);
106
107 static void           xml191_parse_markup         (xmlNodePtr        markup_node,
108                                                    glTemplate       *template);
109
110 static void           xml191_parse_alias          (xmlNodePtr        alias_node,
111                                                    glTemplate       *template);
112
113
114
115 /****************************************************************************/
116 /* Parse xml root node and create label.                                    */
117 /****************************************************************************/
118 glLabel *
119 gl_xml_label_191_parse (xmlNodePtr        root,
120                         glXMLLabelStatus *status)
121 {
122         xmlNodePtr  node;
123         glLabel    *label;
124         glTemplate *template;
125
126         gl_debug (DEBUG_XML, "START");
127
128         *status = XML_LABEL_OK;
129
130         if (!xmlStrEqual (root->name, "Document")) {
131                 g_warning (_("Bad root node = \"%s\""), root->name);
132                 *status = XML_LABEL_ERROR_OPEN_PARSE;
133                 return NULL;
134         }
135
136         label = GL_LABEL(gl_label_new ());
137
138         /* Pass 1, extract data nodes to pre-load cache. */
139         for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
140                 if (xmlStrEqual (node->name, "Data")) {
141                         xml191_parse_data (node, label);
142                 }
143         }
144
145         /* Pass 2, now extract everything else. */
146         for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
147
148                 if (xmlStrEqual (node->name, "Sheet")) {
149                         template = xml191_parse_sheet (node);
150                         if (!template) {
151                                 *status = XML_LABEL_UNKNOWN_MEDIA;
152                                 return NULL;
153                         }
154                         gl_label_set_template (label, template);
155                         gl_template_free (&template);
156                 } else if (xmlStrEqual (node->name, "Objects")) {
157                         xml191_parse_objects (node, label);
158                 } else if (xmlStrEqual (node->name, "Merge_Fields")) {
159                         xml191_parse_merge_fields (node, label);
160                 } else if (xmlStrEqual (node->name, "Data")) {
161                         /* Handled in pass 1. */
162                 } else {
163                         if (!xmlNodeIsText (node)) {
164                                 g_warning (_("bad node in Document node =  \"%s\""),
165                                            node->name);
166                         }
167                 }
168         }
169
170         gl_debug (DEBUG_XML, "END");
171
172         return label;
173 }
174
175 /*--------------------------------------------------------------------------*/
176 /* PRIVATE.  Parse Objects node.                                            */
177 /*--------------------------------------------------------------------------*/
178 static void
179 xml191_parse_objects (xmlNodePtr  objects_node,
180                       glLabel    *label)
181 {
182         gboolean    rotate_flag;
183         xmlNodePtr  node;
184
185         gl_debug (DEBUG_XML, "START");
186
187         rotate_flag = gl_xml_get_prop_boolean (objects_node, "rotate", FALSE);
188         gl_label_set_rotate_flag (label, rotate_flag);
189
190         for (node = objects_node->xmlChildrenNode; node != NULL; node = node->next) {
191
192                 if (xmlStrEqual (node->name, "Object")) {
193                         xml191_parse_object (node, label);
194                 } else {
195                         if (!xmlNodeIsText (node)) {
196                                 g_warning (_("bad node =  \"%s\""), node->name);
197                         }
198                 }
199         }
200
201         gl_debug (DEBUG_XML, "END");
202 }
203
204 /*--------------------------------------------------------------------------*/
205 /* PRIVATE.  Parse XML Object Node                                          */
206 /*--------------------------------------------------------------------------*/
207 static void
208 xml191_parse_object (xmlNodePtr  object_node,
209                      glLabel    *label)
210 {
211         glLabelObject *object;
212         gdouble        x, y;
213         gchar         *string;
214         gdouble        affine[6];
215
216         gl_debug (DEBUG_XML, "START");
217
218         string = xmlGetProp (object_node, "type");
219
220         if ( xmlStrEqual (string, "Text") ) {
221                 object = xml191_parse_text_props (object_node, label);
222         } else if ( xmlStrEqual (string, "Box") ) {
223                 object = xml191_parse_box_props (object_node, label);
224         } else if ( xmlStrEqual (string, "Line") ) {
225                 object = xml191_parse_line_props (object_node, label);
226         } else if ( xmlStrEqual (string, "Ellipse") ) {
227                 object = xml191_parse_ellipse_props (object_node, label);
228         } else if ( xmlStrEqual (string, "Image") ) {
229                 object = xml191_parse_image_props (object_node, label);
230         } else if ( xmlStrEqual (string, "Barcode") ) {
231                 object = xml191_parse_barcode_props (object_node, label);
232         } else {
233                 g_warning ("Unknown label object type \"%s\"", string);
234                 g_free (string);
235                 return;
236         }
237         g_free (string);
238
239
240         x = gl_xml_get_prop_length (object_node, "x", 0.0);
241         y = gl_xml_get_prop_length (object_node, "y", 0.0);
242
243         gl_label_object_set_position (object, x, y);
244
245
246         affine[0] = gl_xml_get_prop_double (object_node, "a0", 0.0);
247         affine[1] = gl_xml_get_prop_double (object_node, "a1", 0.0);
248         affine[2] = gl_xml_get_prop_double (object_node, "a2", 0.0);
249         affine[3] = gl_xml_get_prop_double (object_node, "a3", 0.0);
250         affine[4] = gl_xml_get_prop_double (object_node, "a4", 0.0);
251         affine[5] = gl_xml_get_prop_double (object_node, "a5", 0.0);
252
253         gl_label_object_set_affine (object, affine);
254
255
256         gl_debug (DEBUG_XML, "END");
257 }
258
259 /*--------------------------------------------------------------------------*/
260 /* PRIVATE.  Parse XML Label->Text Node Properties                          */
261 /*--------------------------------------------------------------------------*/
262 static glLabelObject *
263 xml191_parse_text_props (xmlNodePtr  object_node,
264                          glLabel    *label)
265 {
266         GObject          *object;
267         GList            *lines;
268         gdouble           w, h;
269         gchar            *font_family;
270         gdouble           font_size;
271         GnomeFontWeight   font_weight;
272         gboolean          font_italic_flag;
273         guint             color;
274         GtkJustification  just;
275         xmlNodePtr        line_node, text_node;
276         glTextNode       *node_text;
277         GList            *nodes;
278         gchar            *string;
279
280         gl_debug (DEBUG_XML, "START");
281
282         object = gl_label_text_new (label);
283
284         w = gl_xml_get_prop_length (object_node, "w", 0);
285         h = gl_xml_get_prop_length (object_node, "h", 0);
286
287         font_family = xmlGetProp (object_node, "font_family");
288
289         font_size = gl_xml_get_prop_double (object_node, "font_size", 0.0);
290
291         string = xmlGetProp (object_node, "font_weight");
292         font_weight = gl_util_string_to_weight (string);
293         g_free (string);
294
295         font_italic_flag = gl_xml_get_prop_boolean (object_node, "font_italic", FALSE);
296
297         string = xmlGetProp (object_node, "justify");
298         just = gl_util_string_to_just (string);
299         g_free (string);
300
301         color = gl_xml_get_prop_uint (object_node, "color", 0);
302
303         lines = NULL;
304         for (line_node = object_node->xmlChildrenNode;
305              line_node != NULL;
306              line_node = line_node->next) {
307
308                 if (xmlStrEqual (line_node->name, "Line")) {
309
310                         nodes = NULL;
311                         for (text_node = line_node->xmlChildrenNode;
312                              text_node != NULL; text_node = text_node->next) {
313
314                                 if (xmlStrEqual (text_node->name, "Field")) {
315                                         node_text = g_new0 (glTextNode, 1);
316                                         node_text->field_flag = TRUE;
317                                         node_text->data = xmlGetProp (text_node, "name");
318                                         nodes = g_list_append (nodes, node_text);
319                                 } else if (xmlStrEqual (text_node->name, "Literal")) {
320                                         node_text = g_new0 (glTextNode, 1);
321                                         node_text->field_flag = FALSE;
322                                         node_text->data =
323                                                 xmlNodeGetContent (text_node);
324                                         nodes =
325                                                 g_list_append (nodes, node_text);
326                                 } else if (!xmlNodeIsText (text_node)) {
327                                         g_warning ("Unexpected Text Line child: \"%s\"",
328                                                    text_node->name);
329                                 }
330
331                         }
332                         lines = g_list_append (lines, nodes);
333
334                 } else if (!xmlNodeIsText (line_node)) {
335                         g_warning ("Unexpected Text child: \"%s\"",
336                                    line_node->name);
337                 }
338
339         }
340
341         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
342         gl_label_text_set_lines  (GL_LABEL_TEXT(object), lines);
343         gl_label_text_set_props  (GL_LABEL_TEXT(object),
344                                   font_family, font_size, font_weight,
345                                   font_italic_flag,
346                                   color, just);
347
348         gl_text_node_lines_free (&lines);
349         g_free (font_family);
350
351         gl_debug (DEBUG_XML, "END");
352
353         return GL_LABEL_OBJECT(object);
354 }
355
356 /*--------------------------------------------------------------------------*/
357 /* PRIVATE.  Parse XML Label->Box Node Properties                           */
358 /*--------------------------------------------------------------------------*/
359 static glLabelObject *
360 xml191_parse_box_props (xmlNodePtr  node,
361                         glLabel    *label)
362 {
363         GObject *object;
364         gdouble  line_width;
365         guint    line_color, fill_color;
366         gdouble  w, h;
367
368         gl_debug (DEBUG_XML, "START");
369
370         object = gl_label_box_new (label);
371
372         w = gl_xml_get_prop_length (node, "w", 0);
373         h = gl_xml_get_prop_length (node, "h", 0);
374
375         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
376
377         line_color = gl_xml_get_prop_uint (node, "line_color", 0);
378         fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
379
380         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
381         gl_label_box_set_line_width (GL_LABEL_BOX(object), line_width);
382         gl_label_box_set_line_color (GL_LABEL_BOX(object), line_color);
383         gl_label_box_set_fill_color (GL_LABEL_BOX(object), fill_color);
384
385         gl_debug (DEBUG_XML, "END");
386
387         return GL_LABEL_OBJECT(object);
388 }
389
390 /*--------------------------------------------------------------------------*/
391 /* PRIVATE.  Parse XML Label->Line Node Properties                          */
392 /*--------------------------------------------------------------------------*/
393 static glLabelObject *
394 xml191_parse_line_props (xmlNodePtr  node,
395                          glLabel    *label)
396 {
397         GObject *object;
398         gdouble  line_width;
399         guint    line_color;
400         gdouble  w, h;
401
402         gl_debug (DEBUG_XML, "START");
403
404         object = gl_label_line_new (label);
405
406         w = gl_xml_get_prop_length (node, "dx", 0);
407         h = gl_xml_get_prop_length (node, "dy", 0);
408
409         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
410
411         line_color = gl_xml_get_prop_uint (node, "line_color", 0);
412
413         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
414         gl_label_line_set_line_width (GL_LABEL_LINE(object), line_width);
415         gl_label_line_set_line_color (GL_LABEL_LINE(object), line_color);
416
417         gl_debug (DEBUG_XML, "END");
418
419         return GL_LABEL_OBJECT(object);
420 }
421
422 /*--------------------------------------------------------------------------*/
423 /* PRIVATE.  Parse XML Label->Ellipse Node Properties                       */
424 /*--------------------------------------------------------------------------*/
425 static glLabelObject *
426 xml191_parse_ellipse_props (xmlNodePtr  node,
427                             glLabel    *label)
428 {
429         GObject *object;
430         gdouble  line_width;
431         guint    line_color, fill_color;
432         gdouble  w, h;
433
434         gl_debug (DEBUG_XML, "START");
435
436         object = gl_label_ellipse_new (label);
437
438         w = gl_xml_get_prop_length (node, "w", 0);
439         h = gl_xml_get_prop_length (node, "h", 0);
440
441         line_width = gl_xml_get_prop_length (node, "line_width", 1.0);
442
443         line_color = gl_xml_get_prop_uint (node, "line_color", 0);
444         fill_color = gl_xml_get_prop_uint (node, "fill_color", 0);
445
446         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
447         gl_label_ellipse_set_line_width (GL_LABEL_ELLIPSE(object), line_width);
448         gl_label_ellipse_set_line_color (GL_LABEL_ELLIPSE(object), line_color);
449         gl_label_ellipse_set_fill_color (GL_LABEL_ELLIPSE(object), fill_color);
450
451         gl_debug (DEBUG_XML, "END");
452
453         return GL_LABEL_OBJECT(object);
454 }
455
456 /*--------------------------------------------------------------------------*/
457 /* PRIVATE.  Parse XML Label->Image Node Properties                         */
458 /*--------------------------------------------------------------------------*/
459 static glLabelObject *
460 xml191_parse_image_props (xmlNodePtr  node,
461                           glLabel    *label)
462 {
463         GObject      *object;
464         xmlNodePtr    child;
465         gdouble       w, h;
466         glTextNode   *filename;
467
468         gl_debug (DEBUG_XML, "START");
469
470         object = gl_label_image_new (label);
471
472         w = gl_xml_get_prop_length (node, "w", 0);
473         h = gl_xml_get_prop_length (node, "h", 0);
474
475         filename = g_new0 (glTextNode, 1);
476         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
477                 if (xmlStrEqual (child->name, "Field")) {
478                         filename->field_flag = TRUE;
479                         filename->data = xmlGetProp (child, "name");
480                 } else if (xmlStrEqual (child->name, "File")) {
481                         filename->field_flag = FALSE;
482                         filename->data = xmlGetProp (child, "src");
483                 } else if (!xmlNodeIsText (child)) {
484                         g_warning ("Unexpected Image child: \"%s\"", child->name);
485                 }
486         }
487
488         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
489         gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
490
491         gl_text_node_free (&filename);
492
493         gl_debug (DEBUG_XML, "END");
494
495         return GL_LABEL_OBJECT(object);
496 }
497
498 /*--------------------------------------------------------------------------*/
499 /* PRIVATE.  Parse XML Label->Barcode Node Properties                       */
500 /*--------------------------------------------------------------------------*/
501 static glLabelObject *
502 xml191_parse_barcode_props (xmlNodePtr  node,
503                             glLabel    *label)
504 {
505         GObject            *object;
506         xmlNodePtr          child;
507         gdouble             w, h;
508         gchar              *string;
509         glTextNode         *text_node;
510         glBarcodeStyle      style;
511         gboolean            text_flag;
512         gboolean            checksum_flag;
513         guint               color;
514
515         gl_debug (DEBUG_XML, "START");
516
517         object = gl_label_barcode_new (label);
518
519         w = gl_xml_get_prop_length (node, "w", 0);
520         h = gl_xml_get_prop_length (node, "h", 0);
521
522         color = gl_xml_get_prop_uint (node, "color", 0);
523
524         string = xmlGetProp (node, "style");
525         style = gl_barcode_text_to_style (string);
526         g_free (string);
527
528         text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
529         checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
530
531         text_node = g_new0 (glTextNode, 1);
532         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
533                 if (xmlStrEqual (child->name, "Field")) {
534                         text_node->field_flag = TRUE;
535                         text_node->data = xmlGetProp (child, "name");
536                 } else if (xmlStrEqual (child->name, "Literal")) {
537                         text_node->field_flag = FALSE;
538                         text_node->data = xmlNodeGetContent (child);
539                 } else if (!xmlNodeIsText (child)) {
540                         g_warning ("Unexpected Barcode child: \"%s\"", child->name);
541                 }
542         }
543
544         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
545
546         gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
547         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
548                                     style, text_flag, checksum_flag, color);
549
550         gl_text_node_free (&text_node);
551
552         gl_debug (DEBUG_XML, "END");
553
554         return GL_LABEL_OBJECT(object);
555 }
556
557 /*--------------------------------------------------------------------------*/
558 /* PRIVATE.  Parse XML merge fields tag.                                */
559 /*--------------------------------------------------------------------------*/
560 static void
561 xml191_parse_merge_fields (xmlNodePtr  node,
562                            glLabel    *label)
563 {
564         xmlNodePtr  child;
565         gchar      *string;
566         glMerge    *merge;
567
568         gl_debug (DEBUG_XML, "START");
569
570         string = xmlGetProp (node, "type");
571         merge = gl_merge_new (string);
572         g_free (string);
573
574         string = xmlGetProp (node, "src");
575         gl_merge_set_src (merge, string);
576         g_free (string);
577
578         gl_label_set_merge (label, merge);
579
580         g_object_unref (G_OBJECT(merge));
581
582         gl_debug (DEBUG_XML, "END");
583 }
584
585 /*--------------------------------------------------------------------------*/
586 /* PRIVATE.  Parse XML data tag.                                            */
587 /*--------------------------------------------------------------------------*/
588 static void
589 xml191_parse_data (xmlNodePtr  node,
590                    glLabel    *label)
591 {
592         xmlNodePtr  child;
593
594         gl_debug (DEBUG_XML, "START");
595
596         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
597
598                 if (xmlStrEqual (child->name, "Pixdata")) {
599                         xml191_parse_pixdata (child, label);
600                 } else {
601                         if (!xmlNodeIsText (child)) {
602                                 g_warning (_("bad node in Data node =  \"%s\""),
603                                            child->name);
604                         }
605                 }
606         }
607
608         gl_debug (DEBUG_XML, "END");
609 }
610
611 /*--------------------------------------------------------------------------*/
612 /* PRIVATE.  Parse XML pixbuf data tag.                                     */
613 /*--------------------------------------------------------------------------*/
614 static void
615 xml191_parse_pixdata (xmlNodePtr  node,
616                       glLabel    *label)
617 {
618         gchar      *name, *base64;
619         guchar     *stream;
620         guint       stream_length;
621         gboolean    ret;
622         GdkPixdata *pixdata;
623         GdkPixbuf  *pixbuf;
624         GHashTable *pixbuf_cache;
625
626         gl_debug (DEBUG_XML, "START");
627
628         name = xmlGetProp (node, "name");
629         base64 = xmlNodeGetContent (node);
630
631         stream = gl_base64_decode (base64, &stream_length);
632         pixdata = g_new0 (GdkPixdata, 1);
633         ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
634
635         if (ret) {
636                 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
637
638                 pixbuf_cache = gl_label_get_pixbuf_cache (label);
639                 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
640         }
641
642         g_free (name);
643         g_free (base64);
644         g_free (stream);
645         g_free (pixdata);
646
647         gl_debug (DEBUG_XML, "END");
648 }
649
650 /*--------------------------------------------------------------------------*/
651 /* PRIVATE.  Parse XML template Node.                                       */
652 /*--------------------------------------------------------------------------*/
653 static glTemplate *
654 xml191_parse_sheet (xmlNodePtr sheet_node)
655 {
656         glTemplate            *template;
657         xmlNodePtr             node;
658         gchar                 *description;
659         glPaper               *paper;
660
661         gl_debug (DEBUG_TEMPLATE, "START");
662
663         template = g_new0 (glTemplate, 1);
664
665         template->name  = xmlGetProp (sheet_node, "name");
666         template->alias = g_list_append (template->alias, g_strdup (template->name));
667         gl_debug (DEBUG_TEMPLATE, "Sheet = %s", template->name);
668
669         template->page_size = xmlGetProp (sheet_node, "size");
670         if (xmlStrEqual (template->page_size, "Other")) {
671
672                 template->page_width = gl_xml_get_prop_length (sheet_node, "width", 0);
673                 template->page_height = gl_xml_get_prop_length (sheet_node, "height", 0);
674
675         } else {
676                 paper = gl_paper_from_id (template->page_size);
677                 if (paper == NULL) {
678                         /* This should always be an id, but just in case a name
679                            slips by! */
680                         g_warning (_("Unknown page size id \"%s\", trying as name"),
681                                    template->page_size);
682                         paper = gl_paper_from_name (template->page_size);
683                         g_free (template->page_size);
684                         template->page_size = g_strdup (paper->id);
685                 }
686                 if (paper != NULL) {
687                         template->page_width  = paper->width;
688                         template->page_height = paper->height;
689                 } else {
690                         g_warning (_("Unknown page size id or name \"%s\""),
691                                    template->page_size);
692                 }
693                 gl_paper_free (&paper);
694         }
695
696         description = xmlGetProp (sheet_node, "_description");
697         if (description != NULL) {
698                 template->description = gettext (description);
699         } else {
700                 template->description = xmlGetProp (sheet_node, "description");
701         }
702
703         for (node = sheet_node->xmlChildrenNode; node != NULL;
704              node = node->next) {
705                 if (xmlStrEqual (node->name, "Label")) {
706                         xml191_parse_label (node, template);
707                 } else if (xmlStrEqual (node->name, "Alias")) {
708                         xml191_parse_alias (node, template);
709                 } else {
710                         if (!xmlNodeIsText (node)) {
711                                 g_warning ("bad node =  \"%s\"", node->name);
712                         }
713                 }
714         }
715
716         gl_debug (DEBUG_TEMPLATE, "END");
717
718         return template;
719 }
720
721 /*--------------------------------------------------------------------------*/
722 /* PRIVATE.  Parse XML Sheet->Label Node.                                   */
723 /*--------------------------------------------------------------------------*/
724 static void
725 xml191_parse_label (xmlNodePtr  label_node,
726                     glTemplate *template)
727 {
728         xmlNodePtr  node;
729         gchar      *style;
730
731         gl_debug (DEBUG_TEMPLATE, "START");
732
733         style = xmlGetProp (label_node, "style");
734         if (xmlStrEqual (style, "rectangle")) {
735                 template->label.style = GL_TEMPLATE_STYLE_RECT;
736         } else if (xmlStrEqual (style, "round")) {
737                 template->label.style = GL_TEMPLATE_STYLE_ROUND;
738         } else if (xmlStrEqual (style, "cd")) {
739                 template->label.style = GL_TEMPLATE_STYLE_CD;
740         } else {
741                 template->label.style = GL_TEMPLATE_STYLE_RECT;
742                 g_warning ("Unknown label style in template");
743         }
744         g_free (style);
745
746         switch (template->label.style) {
747
748         case GL_TEMPLATE_STYLE_RECT:
749                 template->label.rect.w = gl_xml_get_prop_length (label_node, "width", 0);
750                 template->label.rect.h = gl_xml_get_prop_length (label_node, "height", 0);
751                 template->label.rect.r = gl_xml_get_prop_length (label_node, "round", 0);
752                 break;
753
754         case GL_TEMPLATE_STYLE_ROUND:
755                 template->label.round.r = gl_xml_get_prop_length (label_node, "radius", 0);
756                 break;
757
758         case GL_TEMPLATE_STYLE_CD:
759                 template->label.cd.r1 = gl_xml_get_prop_length (label_node, "radius", 0);
760                 template->label.cd.r2 = gl_xml_get_prop_length (label_node, "hole", 0);
761                 template->label.cd.w  = gl_xml_get_prop_length (label_node, "width", 0);
762                 template->label.cd.h  = gl_xml_get_prop_length (label_node, "height", 0);
763                 break;
764
765         default:
766                 break;
767
768         }
769
770         for (node = label_node->xmlChildrenNode; node != NULL;
771              node = node->next) {
772                 if (xmlStrEqual (node->name, "Layout")) {
773                         xml191_parse_layout (node, template);
774                 } else if (xmlStrEqual (node->name, "Markup")) {
775                         xml191_parse_markup (node, template);
776                 } else if (!xmlNodeIsText (node)) {
777                         g_warning ("bad node =  \"%s\"", node->name);
778                 }
779         }
780
781         gl_debug (DEBUG_TEMPLATE, "END");
782 }
783
784 /*--------------------------------------------------------------------------*/
785 /* PRIVATE.  Parse XML Sheet->Label->Layout Node.                           */
786 /*--------------------------------------------------------------------------*/
787 static void
788 xml191_parse_layout (xmlNodePtr  layout_node,
789                      glTemplate *template)
790 {
791         gint        nx, ny;
792         gdouble     x0, y0, dx, dy;
793         xmlNodePtr  node;
794
795         gl_debug (DEBUG_TEMPLATE, "START");
796
797         nx = gl_xml_get_prop_int (layout_node, "nx", 1);
798         ny = gl_xml_get_prop_int (layout_node, "ny", 1);
799
800         x0 = gl_xml_get_prop_length (layout_node, "x0", 0);
801         y0 = gl_xml_get_prop_length (layout_node, "y0", 0);
802
803         dx = gl_xml_get_prop_length (layout_node, "dx", 0);
804         dy = gl_xml_get_prop_length (layout_node, "dy", 0);
805
806         for (node = layout_node->xmlChildrenNode; node != NULL;
807              node = node->next) {
808                 if (!xmlNodeIsText (node)) {
809                         g_warning ("bad node =  \"%s\"", node->name);
810                 }
811         }
812
813         template->label.any.layouts =
814                 g_list_append (template->label.any.layouts,
815                                gl_template_layout_new (nx, ny, x0, y0, dx, dy));
816
817         gl_debug (DEBUG_TEMPLATE, "END");
818 }
819
820 /*--------------------------------------------------------------------------*/
821 /* PRIVATE.  Parse XML Sheet->Label->Markup Node.                           */
822 /*--------------------------------------------------------------------------*/
823 static void
824 xml191_parse_markup (xmlNodePtr  markup_node,
825                      glTemplate *template)
826 {
827         gchar      *type;
828         gdouble     size;
829         gdouble     x1, y1, x2, y2;
830         xmlNodePtr  node;
831
832         gl_debug (DEBUG_TEMPLATE, "START");
833
834         type = xmlGetProp (markup_node, "type");
835         if (xmlStrEqual (type, "margin")) {
836
837                 size = gl_xml_get_prop_length (markup_node, "size", 0);
838
839                 template->label.any.markups =
840                         g_list_append (template->label.any.markups,
841                                        gl_template_markup_margin_new (size));
842
843         } else if (xmlStrEqual (type, "line")) {
844
845                 x1 = gl_xml_get_prop_length (markup_node, "x1", 0);
846                 y1 = gl_xml_get_prop_length (markup_node, "y1", 0);
847                 x2 = gl_xml_get_prop_length (markup_node, "x2", 0);
848                 y2 = gl_xml_get_prop_length (markup_node, "y2", 0);
849
850                 template->label.any.markups =
851                         g_list_append (template->label.any.markups,
852                                        gl_template_markup_line_new (x1, y1, x2, y2));
853         }
854         g_free (type);
855
856         for (node = markup_node->xmlChildrenNode; node != NULL;
857              node = node->next) {
858                 if (!xmlNodeIsText (node)) {
859                         g_warning ("bad node =  \"%s\"", node->name);
860                 }
861         }
862
863         gl_debug (DEBUG_TEMPLATE, "END");
864 }
865
866 /*--------------------------------------------------------------------------*/
867 /* PRIVATE.  Parse XML Sheet->Alias Node.                                   */
868 /*--------------------------------------------------------------------------*/
869 static void
870 xml191_parse_alias (xmlNodePtr  alias_node,
871                     glTemplate *template)
872 {
873         gl_debug (DEBUG_TEMPLATE, "START");
874
875         template->alias = g_list_append (template->alias,
876                                         xmlGetProp (alias_node, "name"));
877
878         gl_debug (DEBUG_TEMPLATE, "END");
879 }
880