]> git.sur5r.net Git - glabels/blob - glabels2/src/xml-label.c
Made all comparisons case sensitive.
[glabels] / glabels2 / src / xml-label.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  label.c:  GLabels xml label 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 "template.h"
40 #include "base64.h"
41 #include "xml-label.h"
42 #include "xml-label-04.h"
43 #include "xml-template.h"
44 #include "xml.h"
45 #include "util.h"
46
47 #include "debug.h"
48
49 /*========================================================*/
50 /* Private macros and constants.                          */
51 /*========================================================*/
52 #define NAME_SPACE "http://snaught.com/glabels/1.92/"
53 #define COMPAT01_NAME_SPACE "http://snaught.com/glabels/0.1/"
54 #define COMPAT04_NAME_SPACE "http://snaught.com/glabels/0.4/"
55
56 /*========================================================*/
57 /* Private types.                                         */
58 /*========================================================*/
59
60 /*========================================================*/
61 /* Private globals.                                       */
62 /*========================================================*/
63
64 /*========================================================*/
65 /* Private function prototypes.                           */
66 /*========================================================*/
67
68 static glLabel       *xml_doc_to_label         (xmlDocPtr         doc,
69                                                 glXMLLabelStatus *status);
70
71 static glLabel       *xml_parse_label          (xmlNodePtr        root,
72                                                 glXMLLabelStatus *status);
73
74 static void           xml_parse_objects        (xmlNodePtr        node,
75                                                 glLabel          *label);
76
77 static void           xml_parse_object         (xmlNodePtr        node,
78                                                 glLabel          *label);
79
80 static glLabelObject *xml_parse_text_props     (xmlNodePtr        node,
81                                                 glLabel          *label);
82
83 static glLabelObject *xml_parse_box_props      (xmlNodePtr        node,
84                                                 glLabel          *label);
85
86 static glLabelObject *xml_parse_line_props     (xmlNodePtr        node,
87                                                 glLabel          *label);
88
89 static glLabelObject *xml_parse_ellipse_props  (xmlNodePtr        node,
90                                                 glLabel          *label);
91
92 static glLabelObject *xml_parse_image_props    (xmlNodePtr        node,
93                                                 glLabel          *label);
94
95 static glLabelObject *xml_parse_barcode_props  (xmlNodePtr        node,
96                                                 glLabel          *label);
97
98 static void           xml_parse_merge_fields   (xmlNodePtr        node,
99                                                 glLabel          *label);
100
101 static void           xml_parse_data           (xmlNodePtr        node,
102                                                 glLabel          *label);
103
104 static void           xml_parse_pixdata        (xmlNodePtr        node,
105                                                 glLabel          *label);
106
107
108 static xmlDocPtr      xml_label_to_doc         (glLabel          *label,
109                                                 glXMLLabelStatus *status);
110
111 static void           xml_create_objects       (xmlNodePtr        root,
112                                                 xmlNsPtr          ns,
113                                                 glLabel          *label);
114
115 static void           xml_create_object        (xmlNodePtr        root,
116                                                 xmlNsPtr          ns,
117                                                 glLabelObject    *object);
118
119 static void           xml_create_text_props    (xmlNodePtr        root,
120                                                 xmlNsPtr          ns,
121                                                 glLabelObject    *object);
122
123 static void           xml_create_box_props     (xmlNodePtr        root,
124                                                 xmlNsPtr          ns,
125                                                 glLabelObject    *object);
126
127 static void           xml_create_line_props    (xmlNodePtr        root,
128                                                 xmlNsPtr          ns,
129                                                 glLabelObject    *object);
130
131 static void           xml_create_ellipse_props (xmlNodePtr        root,
132                                                 xmlNsPtr          ns,
133                                                 glLabelObject    *object);
134
135 static void           xml_create_image_props   (xmlNodePtr        root,
136                                                 xmlNsPtr          ns,
137                                                 glLabelObject    *object);
138
139 static void           xml_create_barcode_props (xmlNodePtr        root,
140                                                 xmlNsPtr          ns,
141                                                 glLabelObject    *object);
142
143 static void           xml_create_merge_fields  (xmlNodePtr        root,
144                                                 xmlNsPtr          ns,
145                                                 glLabel          *label);
146
147 static void           xml_create_data          (xmlNodePtr        root,
148                                                 xmlNsPtr          ns,
149                                                 glLabel          *label);
150
151 static void           xml_create_pixdata       (xmlNodePtr        root,
152                                                 xmlNsPtr          ns,
153                                                 glLabel          *label,
154                                                 gchar            *name);
155
156
157 /****************************************************************************/
158 /* Open and read label from xml file.                                       */
159 /****************************************************************************/
160 glLabel *
161 gl_xml_label_open (const gchar      *filename,
162                    glXMLLabelStatus *status)
163 {
164         xmlDocPtr  doc;
165         glLabel   *label;
166
167         gl_debug (DEBUG_XML, "START");
168
169         doc = xmlParseFile (filename);
170         if (!doc) {
171                 g_warning (_("xmlParseFile error"));
172                 *status = XML_LABEL_ERROR_OPEN_PARSE;
173                 return NULL;
174         }
175
176         label = xml_doc_to_label (doc, status);
177
178         xmlFreeDoc (doc);
179
180         if (label) {
181                 gl_label_set_filename (label, filename);
182                 gl_label_clear_modified (label);
183         }
184
185         gl_debug (DEBUG_XML, "END");
186
187         return label;
188 }
189
190 /****************************************************************************/
191 /* Read label from xml buffer.                                              */
192 /****************************************************************************/
193 glLabel *
194 gl_xml_label_open_buffer (const gchar      *buffer,
195                           glXMLLabelStatus *status)
196 {
197         xmlDocPtr  doc;
198         glLabel   *label;
199
200         gl_debug (DEBUG_XML, "START");
201
202         doc = xmlParseDoc ((xmlChar *) buffer);
203         if (!doc) {
204                 g_warning (_("xmlParseFile error"));
205                 *status = XML_LABEL_ERROR_OPEN_PARSE;
206                 return NULL;
207         }
208
209         label = xml_doc_to_label (doc, status);
210
211         xmlFreeDoc (doc);
212
213         if (label) {
214                 gl_label_clear_modified (label);
215         }
216
217         gl_debug (DEBUG_XML, "END");
218
219         return label;
220 }
221
222 /*--------------------------------------------------------------------------*/
223 /* PRIVATE.  Parse xml doc structure and create label.                      */
224 /*--------------------------------------------------------------------------*/
225 static glLabel *
226 xml_doc_to_label (xmlDocPtr         doc,
227                   glXMLLabelStatus *status)
228 {
229         xmlNodePtr  root, node;
230         xmlNsPtr    ns;
231         glLabel    *label;
232
233         gl_debug (DEBUG_XML, "START");
234
235         LIBXML_TEST_VERSION;
236
237         *status = XML_LABEL_OK;
238
239         root = xmlDocGetRootElement (doc);
240         if (!root || !root->name) {
241                 g_warning (_("No document root"));
242                 *status = XML_LABEL_ERROR_OPEN_PARSE;
243                 return NULL;
244         }
245
246         ns = xmlSearchNsByHref (doc, root, NAME_SPACE);
247         if (ns != NULL) {
248                 label = xml_parse_label (root, status);
249         } else {
250                 /* Try compatability mode 0.1 */
251                 ns = xmlSearchNsByHref (doc, root, COMPAT01_NAME_SPACE);
252                 if (ns != NULL) {
253                         g_warning (_("Importing from glabels 0.1 format"));
254                         g_warning ("TODO");
255                         label = NULL; /* TODO */
256                 } else {
257                         /* Try compatability mode 0.4 */
258                         ns = xmlSearchNsByHref (doc, root,
259                                                 COMPAT04_NAME_SPACE);
260                         if (ns != NULL) {
261                                 g_warning (_("Importing from glabels 0.4 format"));
262                                 label = gl_xml_label_04_parse (root, status);
263                         } else {
264                                 g_warning (_("bad document, unknown glabels Namespace"));
265                                 *status = XML_LABEL_ERROR_OPEN_PARSE;
266                                 return NULL;
267                         }
268                 }
269         }
270
271         gl_debug (DEBUG_XML, "END");
272
273         return label;
274 }
275
276 /*--------------------------------------------------------------------------*/
277 /* PRIVATE.  Parse xml root node and create label.                          */
278 /*--------------------------------------------------------------------------*/
279 static glLabel *
280 xml_parse_label (xmlNodePtr        root,
281                  glXMLLabelStatus *status)
282 {
283         xmlNodePtr  node;
284         glLabel    *label;
285         glTemplate *template;
286
287         gl_debug (DEBUG_XML, "START");
288
289         *status = XML_LABEL_OK;
290
291         if (!xmlStrEqual (root->name, "Document")) {
292                 g_warning (_("Bad root node = \"%s\""), root->name);
293                 *status = XML_LABEL_ERROR_OPEN_PARSE;
294                 return NULL;
295         }
296
297         label = GL_LABEL(gl_label_new ());
298
299         /* Pass 1, extract data nodes to pre-load cache. */
300         for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
301                 if (xmlStrEqual (node->name, "Data")) {
302                         xml_parse_data (node, label);
303                 }
304         }
305
306         /* Pass 2, now extract everything else. */
307         for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
308
309                 if (xmlStrEqual (node->name, "Sheet")) {
310                         template = gl_xml_template_parse_sheet (node);
311                         if (!template) {
312                                 *status = XML_LABEL_UNKNOWN_MEDIA;
313                                 return NULL;
314                         }
315                         gl_label_set_template (label, template);
316                         gl_template_free (&template);
317                 } else if (xmlStrEqual (node->name, "Objects")) {
318                         xml_parse_objects (node, label);
319                 } else if (xmlStrEqual (node->name, "Merge_Fields")) {
320                         xml_parse_merge_fields (node, label);
321                 } else if (xmlStrEqual (node->name, "Data")) {
322                         /* Handled in pass 1. */
323                 } else {
324                         if (!xmlNodeIsText (node)) {
325                                 g_warning (_("bad node in Document node =  \"%s\""),
326                                            node->name);
327                         }
328                 }
329         }
330
331         gl_debug (DEBUG_XML, "END");
332
333         return label;
334 }
335
336 /*--------------------------------------------------------------------------*/
337 /* PRIVATE.  Parse Objects node.                                            */
338 /*--------------------------------------------------------------------------*/
339 static void
340 xml_parse_objects (xmlNodePtr  objects_node,
341                    glLabel    *label)
342 {
343         gboolean    rotate_flag;
344         xmlNodePtr  node;
345
346         gl_debug (DEBUG_XML, "START");
347
348         rotate_flag = gl_xml_get_prop_boolean (objects_node, "rotate", FALSE);
349         gl_label_set_rotate_flag (label, rotate_flag);
350
351         for (node = objects_node->xmlChildrenNode; node != NULL; node = node->next) {
352
353                 if (xmlStrEqual (node->name, "Object")) {
354                         xml_parse_object (node, label);
355                 } else {
356                         if (!xmlNodeIsText (node)) {
357                                 g_warning (_("bad node =  \"%s\""), node->name);
358                         }
359                 }
360         }
361
362         gl_debug (DEBUG_XML, "END");
363 }
364
365 /*--------------------------------------------------------------------------*/
366 /* PRIVATE.  Parse XML Object Node                                          */
367 /*--------------------------------------------------------------------------*/
368 static void
369 xml_parse_object (xmlNodePtr  object_node,
370                   glLabel    *label)
371 {
372         glLabelObject *object;
373         gdouble        x, y;
374         gchar         *string;
375         gdouble        affine[6];
376
377         gl_debug (DEBUG_XML, "START");
378
379         string = xmlGetProp (object_node, "type");
380
381         if ( xmlStrEqual (string, "Text") ) {
382                 object = xml_parse_text_props (object_node, label);
383         } else if ( xmlStrEqual (string, "Box") ) {
384                 object = xml_parse_box_props (object_node, label);
385         } else if ( xmlStrEqual (string, "Line") ) {
386                 object = xml_parse_line_props (object_node, label);
387         } else if ( xmlStrEqual (string, "Ellipse") ) {
388                 object = xml_parse_ellipse_props (object_node, label);
389         } else if ( xmlStrEqual (string, "Image") ) {
390                 object = xml_parse_image_props (object_node, label);
391         } else if ( xmlStrEqual (string, "Barcode") ) {
392                 object = xml_parse_barcode_props (object_node, label);
393         } else {
394                 g_warning ("Unknown label object type \"%s\"", string);
395                 g_free (string);
396                 return;
397         }
398         g_free (string);
399
400
401         x = gl_xml_get_prop_double (object_node, "x", 0.0);
402         y = gl_xml_get_prop_double (object_node, "y", 0.0);
403
404         gl_label_object_set_position (object, x, y);
405
406
407         affine[0] = gl_xml_get_prop_double (object_node, "a0", 0.0);
408         affine[1] = gl_xml_get_prop_double (object_node, "a1", 0.0);
409         affine[2] = gl_xml_get_prop_double (object_node, "a2", 0.0);
410         affine[3] = gl_xml_get_prop_double (object_node, "a3", 0.0);
411         affine[4] = gl_xml_get_prop_double (object_node, "a4", 0.0);
412         affine[5] = gl_xml_get_prop_double (object_node, "a5", 0.0);
413
414         gl_label_object_set_affine (object, affine);
415
416
417         gl_debug (DEBUG_XML, "END");
418 }
419
420 /*--------------------------------------------------------------------------*/
421 /* PRIVATE.  Parse XML Label->Text Node Properties                          */
422 /*--------------------------------------------------------------------------*/
423 static glLabelObject *
424 xml_parse_text_props (xmlNodePtr  object_node,
425                       glLabel    *label)
426 {
427         GObject          *object;
428         GList            *lines;
429         gdouble           w, h;
430         gchar            *font_family;
431         gdouble           font_size;
432         GnomeFontWeight   font_weight;
433         gboolean          font_italic_flag;
434         guint             color;
435         GtkJustification  just;
436         xmlNodePtr        line_node, text_node;
437         glTextNode       *node_text;
438         GList            *nodes;
439         gchar            *string;
440
441         gl_debug (DEBUG_XML, "START");
442
443         object = gl_label_text_new (label);
444
445         w = gl_xml_get_prop_double (object_node, "w", 0);
446         h = gl_xml_get_prop_double (object_node, "h", 0);
447
448         font_family = xmlGetProp (object_node, "font_family");
449
450         font_size = gl_xml_get_prop_double (object_node, "font_size", 0.0);
451
452         string = xmlGetProp (object_node, "font_weight");
453         font_weight = gl_util_string_to_weight (string);
454         g_free (string);
455
456         font_italic_flag = gl_xml_get_prop_boolean (object_node, "font_italic", FALSE);
457
458         string = xmlGetProp (object_node, "justify");
459         just = gl_util_string_to_just (string);
460         g_free (string);
461
462         color = gl_xml_get_prop_uint_hex (object_node, "color", 0);
463
464         lines = NULL;
465         for (line_node = object_node->xmlChildrenNode;
466              line_node != NULL;
467              line_node = line_node->next) {
468
469                 if (xmlStrEqual (line_node->name, "Line")) {
470
471                         nodes = NULL;
472                         for (text_node = line_node->xmlChildrenNode;
473                              text_node != NULL; text_node = text_node->next) {
474
475                                 if (xmlStrEqual (text_node->name, "Field")) {
476                                         node_text = g_new0 (glTextNode, 1);
477                                         node_text->field_flag = TRUE;
478                                         node_text->data = xmlGetProp (text_node, "name");
479                                         nodes = g_list_append (nodes, node_text);
480                                 } else if (xmlStrEqual (text_node->name, "Literal")) {
481                                         node_text = g_new0 (glTextNode, 1);
482                                         node_text->field_flag = FALSE;
483                                         node_text->data =
484                                                 xmlNodeGetContent (text_node);
485                                         nodes =
486                                                 g_list_append (nodes, node_text);
487                                 } else if (!xmlNodeIsText) {
488                                         g_warning ("Unexpected Text Line child: \"%s\"",
489                                                    text_node->name);
490                                 }
491
492                         }
493                         lines = g_list_append (lines, nodes);
494
495                 } else if (!xmlNodeIsText (line_node)) {
496                         g_warning ("Unexpected Text child: \"%s\"",
497                                    line_node->name);
498                 }
499
500         }
501
502         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
503         gl_label_text_set_lines  (GL_LABEL_TEXT(object), lines);
504         gl_label_text_set_props  (GL_LABEL_TEXT(object),
505                                   font_family, font_size, font_weight,
506                                   font_italic_flag,
507                                   color, just);
508
509         gl_text_node_lines_free (&lines);
510         g_free (font_family);
511
512         gl_debug (DEBUG_XML, "END");
513
514         return GL_LABEL_OBJECT(object);
515 }
516
517 /*--------------------------------------------------------------------------*/
518 /* PRIVATE.  Parse XML Label->Box Node Properties                           */
519 /*--------------------------------------------------------------------------*/
520 static glLabelObject *
521 xml_parse_box_props (xmlNodePtr  node,
522                      glLabel    *label)
523 {
524         GObject *object;
525         gdouble  line_width;
526         guint    line_color, fill_color;
527         gdouble  w, h;
528
529         gl_debug (DEBUG_XML, "START");
530
531         object = gl_label_box_new (label);
532
533         w = gl_xml_get_prop_double (node, "w", 0);
534         h = gl_xml_get_prop_double (node, "h", 0);
535
536         line_width = gl_xml_get_prop_double (node, "line_width", 1.0);
537
538         line_color = gl_xml_get_prop_uint_hex (node, "line_color", 0);
539         fill_color = gl_xml_get_prop_uint_hex (node, "fill_color", 0);
540
541         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
542         gl_label_box_set_line_width (GL_LABEL_BOX(object), line_width);
543         gl_label_box_set_line_color (GL_LABEL_BOX(object), line_color);
544         gl_label_box_set_fill_color (GL_LABEL_BOX(object), fill_color);
545
546         gl_debug (DEBUG_XML, "END");
547
548         return GL_LABEL_OBJECT(object);
549 }
550
551 /*--------------------------------------------------------------------------*/
552 /* PRIVATE.  Parse XML Label->Line Node Properties                          */
553 /*--------------------------------------------------------------------------*/
554 static glLabelObject *
555 xml_parse_line_props (xmlNodePtr  node,
556                       glLabel    *label)
557 {
558         GObject *object;
559         gdouble  line_width;
560         guint    line_color;
561         gdouble  w, h;
562
563         gl_debug (DEBUG_XML, "START");
564
565         object = gl_label_line_new (label);
566
567         w = gl_xml_get_prop_double (node, "dx", 0);
568         h = gl_xml_get_prop_double (node, "dy", 0);
569
570         line_width = gl_xml_get_prop_double (node, "line_width", 1.0);
571
572         line_color = gl_xml_get_prop_uint_hex (node, "line_color", 0);
573
574         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
575         gl_label_line_set_line_width (GL_LABEL_LINE(object), line_width);
576         gl_label_line_set_line_color (GL_LABEL_LINE(object), line_color);
577
578         gl_debug (DEBUG_XML, "END");
579
580         return GL_LABEL_OBJECT(object);
581 }
582
583 /*--------------------------------------------------------------------------*/
584 /* PRIVATE.  Parse XML Label->Ellipse Node Properties                       */
585 /*--------------------------------------------------------------------------*/
586 static glLabelObject *
587 xml_parse_ellipse_props (xmlNodePtr  node,
588                          glLabel    *label)
589 {
590         GObject *object;
591         gdouble  line_width;
592         guint    line_color, fill_color;
593         gdouble  w, h;
594
595         gl_debug (DEBUG_XML, "START");
596
597         object = gl_label_ellipse_new (label);
598
599         w = gl_xml_get_prop_double (node, "w", 0);
600         h = gl_xml_get_prop_double (node, "h", 0);
601
602         line_width = gl_xml_get_prop_double (node, "line_width", 1.0);
603
604         line_color = gl_xml_get_prop_uint_hex (node, "line_color", 0);
605         fill_color = gl_xml_get_prop_uint_hex (node, "fill_color", 0);
606
607         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
608         gl_label_ellipse_set_line_width (GL_LABEL_ELLIPSE(object), line_width);
609         gl_label_ellipse_set_line_color (GL_LABEL_ELLIPSE(object), line_color);
610         gl_label_ellipse_set_fill_color (GL_LABEL_ELLIPSE(object), fill_color);
611
612         gl_debug (DEBUG_XML, "END");
613
614         return GL_LABEL_OBJECT(object);
615 }
616
617 /*--------------------------------------------------------------------------*/
618 /* PRIVATE.  Parse XML Label->Image Node Properties                         */
619 /*--------------------------------------------------------------------------*/
620 static glLabelObject *
621 xml_parse_image_props (xmlNodePtr  node,
622                        glLabel    *label)
623 {
624         GObject      *object;
625         xmlNodePtr    child;
626         gdouble       w, h;
627         glTextNode   *filename;
628
629         gl_debug (DEBUG_XML, "START");
630
631         object = gl_label_image_new (label);
632
633         w = gl_xml_get_prop_double (node, "w", 0);
634         h = gl_xml_get_prop_double (node, "h", 0);
635
636         filename = g_new0 (glTextNode, 1);
637         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
638                 if (xmlStrEqual (child->name, "Field")) {
639                         filename->field_flag = TRUE;
640                         filename->data = xmlGetProp (child, "name");
641                 } else if (xmlStrEqual (child->name, "File")) {
642                         filename->field_flag = FALSE;
643                         filename->data = xmlGetProp (child, "src");
644                 } else if (!xmlNodeIsText (child)) {
645                         g_warning ("Unexpected Image child: \"%s\"", child->name);
646                 }
647         }
648
649         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
650         gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
651
652         gl_text_node_free (&filename);
653
654         gl_debug (DEBUG_XML, "END");
655
656         return GL_LABEL_OBJECT(object);
657 }
658
659 /*--------------------------------------------------------------------------*/
660 /* PRIVATE.  Parse XML Label->Barcode Node Properties                       */
661 /*--------------------------------------------------------------------------*/
662 static glLabelObject *
663 xml_parse_barcode_props (xmlNodePtr  node,
664                          glLabel    *label)
665 {
666         GObject            *object;
667         xmlNodePtr          child;
668         gdouble             w, h;
669         gchar              *string;
670         glTextNode         *text_node;
671         glBarcodeStyle      style;
672         gboolean            text_flag;
673         gboolean            checksum_flag;
674         guint               color;
675
676         gl_debug (DEBUG_XML, "START");
677
678         object = gl_label_barcode_new (label);
679
680         w = gl_xml_get_prop_double (node, "w", 0);
681         h = gl_xml_get_prop_double (node, "h", 0);
682
683         color = gl_xml_get_prop_uint_hex (node, "color", 0);
684
685         string = xmlGetProp (node, "style");
686         style = gl_barcode_text_to_style (string);
687         g_free (string);
688
689         text_flag = gl_xml_get_prop_boolean (node, "text", FALSE);
690         checksum_flag = gl_xml_get_prop_boolean (node, "checksum", TRUE);
691
692         text_node = g_new0 (glTextNode, 1);
693         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
694                 if (xmlStrEqual (child->name, "Field")) {
695                         text_node->field_flag = TRUE;
696                         text_node->data = xmlGetProp (child, "name");
697                 } else if (xmlStrEqual (child->name, "Literal")) {
698                         text_node->field_flag = FALSE;
699                         text_node->data = xmlNodeGetContent (child);
700                 } else if (!xmlNodeIsText (child)) {
701                         g_warning ("Unexpected Barcode child: \"%s\"", child->name);
702                 }
703         }
704
705         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
706
707         gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
708         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
709                                     style, text_flag, checksum_flag, color);
710
711         gl_text_node_free (&text_node);
712
713         gl_debug (DEBUG_XML, "END");
714
715         return GL_LABEL_OBJECT(object);
716 }
717
718 /*--------------------------------------------------------------------------*/
719 /* PRIVATE.  Parse XML merge fields tag.                                */
720 /*--------------------------------------------------------------------------*/
721 static void
722 xml_parse_merge_fields (xmlNodePtr  node,
723                         glLabel    *label)
724 {
725         xmlNodePtr  child;
726         gchar      *string;
727         glMerge    *merge;
728
729         gl_debug (DEBUG_XML, "START");
730
731         string = xmlGetProp (node, "type");
732         merge = gl_merge_new (string);
733         g_free (string);
734
735         string = xmlGetProp (node, "src");
736         gl_merge_set_src (merge, string);
737         g_free (string);
738
739         gl_label_set_merge (label, merge);
740
741         g_object_unref (G_OBJECT(merge));
742
743         gl_debug (DEBUG_XML, "END");
744 }
745
746 /*--------------------------------------------------------------------------*/
747 /* PRIVATE.  Parse XML data tag.                                            */
748 /*--------------------------------------------------------------------------*/
749 static void
750 xml_parse_data (xmlNodePtr  node,
751                 glLabel    *label)
752 {
753         xmlNodePtr  child;
754
755         gl_debug (DEBUG_XML, "START");
756
757         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
758
759                 if (xmlStrEqual (child->name, "Pixdata")) {
760                         xml_parse_pixdata (child, label);
761                 } else {
762                         if (!xmlNodeIsText (child)) {
763                                 g_warning (_("bad node in Data node =  \"%s\""),
764                                            child->name);
765                         }
766                 }
767         }
768
769         gl_debug (DEBUG_XML, "END");
770 }
771
772 /*--------------------------------------------------------------------------*/
773 /* PRIVATE.  Parse XML pixbuf data tag.                                     */
774 /*--------------------------------------------------------------------------*/
775 static void
776 xml_parse_pixdata (xmlNodePtr  node,
777                    glLabel    *label)
778 {
779         gchar      *name, *base64;
780         guchar     *stream;
781         guint       stream_length;
782         gboolean    ret;
783         GdkPixdata *pixdata;
784         GdkPixbuf  *pixbuf;
785         GHashTable *pixbuf_cache;
786
787         gl_debug (DEBUG_XML, "START");
788
789         name = xmlGetProp (node, "name");
790         base64 = xmlNodeGetContent (node);
791
792         stream = gl_base64_decode (base64, &stream_length);
793         pixdata = g_new0 (GdkPixdata, 1);
794         ret = gdk_pixdata_deserialize (pixdata, stream_length, stream, NULL);
795
796         if (ret) {
797                 pixbuf = gdk_pixbuf_from_pixdata (pixdata, TRUE, NULL);
798
799                 pixbuf_cache = gl_label_get_pixbuf_cache (label);
800                 gl_pixbuf_cache_add_pixbuf (pixbuf_cache, name, pixbuf);
801         }
802
803         g_free (name);
804         g_free (base64);
805         g_free (stream);
806         g_free (pixdata);
807
808         gl_debug (DEBUG_XML, "END");
809 }
810
811 /****************************************************************************/
812 /* Save label to xml label file.                                            */
813 /****************************************************************************/
814 void
815 gl_xml_label_save (glLabel          *label,
816                    const gchar      *filename,
817                    glXMLLabelStatus *status)
818 {
819         xmlDocPtr doc;
820         gint      xml_ret;
821
822         gl_debug (DEBUG_XML, "START");
823
824         doc = xml_label_to_doc (label, status);
825
826         xmlSetDocCompressMode (doc, 9);
827         xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
828         xmlFreeDoc (doc);
829         if (xml_ret == -1) {
830
831                 g_warning (_("Problem saving xml file."));
832                 *status = XML_LABEL_ERROR_SAVE_FILE;
833
834         } else {
835
836                 gl_label_set_filename (label, filename);
837                 gl_label_clear_modified (label);
838
839         }
840
841         gl_debug (DEBUG_XML, "END");
842 }
843
844 /****************************************************************************/
845 /* Save label to xml buffer.                                                */
846 /****************************************************************************/
847 gchar *
848 gl_xml_label_save_buffer (glLabel          *label,
849                           glXMLLabelStatus *status)
850 {
851         xmlDocPtr  doc;
852         gint       size;
853         gchar     *buffer;
854
855         gl_debug (DEBUG_XML, "START");
856
857         doc = xml_label_to_doc (label, status);
858
859         xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
860         xmlFreeDoc (doc);
861
862         gl_label_clear_modified (label);
863
864         gl_debug (DEBUG_XML, "END");
865
866         return buffer;
867 }
868
869 /*--------------------------------------------------------------------------*/
870 /* PRIVATE.  Convert label to xml doc structure.                            */
871 /*--------------------------------------------------------------------------*/
872 static xmlDocPtr
873 xml_label_to_doc (glLabel          *label,
874                   glXMLLabelStatus *status)
875 {
876         xmlDocPtr   doc;
877         xmlNsPtr    ns;
878         glTemplate *template;
879         glMerge    *merge;
880
881         gl_debug (DEBUG_XML, "START");
882
883         LIBXML_TEST_VERSION;
884
885         doc = xmlNewDoc ("1.0");
886         doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Document", NULL);
887
888         ns = xmlNewNs (doc->xmlRootNode, NAME_SPACE, "glabels");
889         xmlSetNs (doc->xmlRootNode, ns);
890
891         template = gl_label_get_template (label);
892         gl_xml_template_add_sheet (template, doc->xmlRootNode, ns);
893
894         xml_create_objects (doc->xmlRootNode, ns, label);
895
896         merge = gl_label_get_merge (label);
897         gl_debug (DEBUG_XML, "merge=%p", merge);
898         if (merge != NULL) {
899                 xml_create_merge_fields (doc->xmlRootNode, ns, label);
900                 g_object_unref (G_OBJECT(merge));
901         }
902
903         xml_create_data (doc->xmlRootNode, ns, label);
904
905         gl_debug (DEBUG_XML, "END");
906
907         *status = XML_LABEL_OK;
908         return doc;
909 }
910
911 /*--------------------------------------------------------------------------*/
912 /* PRIVATE.  Add XML Label->Objects Node                                    */
913 /*--------------------------------------------------------------------------*/
914 static void
915 xml_create_objects (xmlNodePtr  root,
916                     xmlNsPtr    ns,
917                     glLabel    *label)
918 {
919         xmlNodePtr  node;
920         gboolean    rotate_flag;
921         GList      *p;
922
923         gl_debug (DEBUG_XML, "START");
924
925         rotate_flag = gl_label_get_rotate_flag (label);
926
927         node = xmlNewChild (root, ns, "Objects", NULL);
928         xmlSetProp (node, "id", "0");
929         gl_xml_set_prop_boolean (node, "rotate", rotate_flag);
930
931         for (p = label->objects; p != NULL; p = p->next) {
932                 xml_create_object (node, ns, GL_LABEL_OBJECT(p->data));
933         }
934
935         gl_debug (DEBUG_XML, "END");
936 }
937
938 /*--------------------------------------------------------------------------*/
939 /* PRIVATE.  Add XML label object Node                                      */
940 /*--------------------------------------------------------------------------*/
941 static void
942 xml_create_object (xmlNodePtr     root,
943                    xmlNsPtr       ns,
944                    glLabelObject *object)
945 {
946         xmlNodePtr  object_node;
947         gdouble     x, y;
948         gdouble     affine[6];
949
950         gl_debug (DEBUG_XML, "START");
951
952         object_node = xmlNewChild (root, ns, "Object", NULL);
953
954         gl_label_object_get_position (object, &x, &y);
955         gl_xml_set_prop_double (object_node, "x", x);
956         gl_xml_set_prop_double (object_node, "y", y);
957
958         gl_label_object_get_affine (object, affine);
959         gl_xml_set_prop_double (object_node, "a0", affine[0]);
960         gl_xml_set_prop_double (object_node, "a1", affine[1]);
961         gl_xml_set_prop_double (object_node, "a2", affine[2]);
962         gl_xml_set_prop_double (object_node, "a3", affine[3]);
963         gl_xml_set_prop_double (object_node, "a4", affine[4]);
964         gl_xml_set_prop_double (object_node, "a5", affine[5]);
965
966         if ( GL_IS_LABEL_TEXT(object) ) {
967                 xml_create_text_props (object_node, ns, object);
968         } else if ( GL_IS_LABEL_BOX(object) ) {
969                 xml_create_box_props (object_node, ns, object);
970         } else if ( GL_IS_LABEL_LINE(object) ) {
971                 xml_create_line_props (object_node, ns, object);
972         } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
973                 xml_create_ellipse_props (object_node, ns, object);
974         } else if ( GL_IS_LABEL_IMAGE(object) ) {
975                 xml_create_image_props (object_node, ns, object);
976         } else if ( GL_IS_LABEL_BARCODE(object) ) {
977                 xml_create_barcode_props (object_node, ns, object);
978         } else {
979                 g_warning ("Unknown label object");
980         }
981
982         gl_debug (DEBUG_XML, "END");
983 }
984
985 /*--------------------------------------------------------------------------*/
986 /* PRIVATE.  Add XML Label->Text Node Properties                            */
987 /*--------------------------------------------------------------------------*/
988 static void
989 xml_create_text_props (xmlNodePtr     object_node,
990                        xmlNsPtr       ns,
991                        glLabelObject *object)
992 {
993         xmlNodePtr        line_node, field_node, literal_node;
994         GList            *lines;
995         gdouble           w, h;
996         gchar            *font_family;
997         gdouble           font_size;
998         GnomeFontWeight   font_weight;
999         gboolean          font_italic_flag;
1000         guint             color;
1001         GtkJustification  just;
1002         GList            *p_line, *p_node;
1003         glTextNode       *node_text;
1004
1005         gl_debug (DEBUG_XML, "START");
1006
1007         xmlSetProp (object_node, "type", "Text");
1008
1009         gl_label_text_get_box ( GL_LABEL_TEXT(object), &w, &h);
1010         lines = gl_label_text_get_lines (GL_LABEL_TEXT(object));
1011         gl_label_text_get_props (GL_LABEL_TEXT(object),
1012                                  &font_family, &font_size, &font_weight,
1013                                  &font_italic_flag,
1014                                  &color, &just);
1015
1016         gl_xml_set_prop_double (object_node, "w", w);
1017         gl_xml_set_prop_double (object_node, "h", h);
1018
1019         xmlSetProp (object_node, "font_family", font_family);
1020         gl_xml_set_prop_double (object_node, "font_size", font_size);
1021         xmlSetProp (object_node, "font_weight",
1022                     gl_util_weight_to_string (font_weight));
1023         gl_xml_set_prop_boolean (object_node, "font_italic", font_italic_flag);
1024
1025         xmlSetProp (object_node, "justify", gl_util_just_to_string (just));
1026
1027         gl_xml_set_prop_uint_hex (object_node, "color", color);
1028
1029         for (p_line = lines; p_line != NULL; p_line = p_line->next) {
1030                 line_node = xmlNewChild (object_node, ns, "Line", NULL);
1031
1032                 for (p_node = (GList *) p_line->data; p_node != NULL;
1033                      p_node = p_node->next) {
1034                         node_text = (glTextNode *) p_node->data;
1035
1036                         if (node_text->field_flag) {
1037                                 field_node =
1038                                     xmlNewChild (line_node, ns, "Field", NULL);
1039                                 xmlSetProp (field_node, "name",
1040                                             node_text->data);
1041                         } else {
1042                                 literal_node =
1043                                     xmlNewChild (line_node, ns,
1044                                                  "Literal", node_text->data);
1045                         }
1046
1047                 }
1048
1049         }
1050
1051         gl_text_node_lines_free (&lines);
1052         g_free (font_family);
1053
1054         gl_debug (DEBUG_XML, "END");
1055 }
1056
1057 /*--------------------------------------------------------------------------*/
1058 /* PRIVATE.  Add XML Label->Box Node Properties                             */
1059 /*--------------------------------------------------------------------------*/
1060 static void
1061 xml_create_box_props (xmlNodePtr     object_node,
1062                       xmlNsPtr       ns,
1063                       glLabelObject *object)
1064 {
1065         gdouble  line_width;
1066         guint    line_color, fill_color;
1067         gdouble  w, h;
1068
1069         gl_debug (DEBUG_XML, "START");
1070
1071         xmlSetProp (object_node, "type", "Box");
1072
1073         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1074         line_width = gl_label_box_get_line_width (GL_LABEL_BOX(object));
1075         line_color = gl_label_box_get_line_color (GL_LABEL_BOX(object));
1076         fill_color = gl_label_box_get_fill_color (GL_LABEL_BOX(object));
1077
1078         gl_xml_set_prop_double (object_node, "w", w);
1079         gl_xml_set_prop_double (object_node, "h", h);
1080
1081         gl_xml_set_prop_double (object_node, "line_width", line_width);
1082
1083         gl_xml_set_prop_uint_hex (object_node, "line_color", line_color);
1084         gl_xml_set_prop_uint_hex (object_node, "fill_color", fill_color);
1085
1086         gl_debug (DEBUG_XML, "END");
1087 }
1088
1089 /*--------------------------------------------------------------------------*/
1090 /* PRIVATE.  Add XML Label->Line Node Properties                            */
1091 /*--------------------------------------------------------------------------*/
1092 static void
1093 xml_create_line_props (xmlNodePtr     object_node,
1094                        xmlNsPtr       ns,
1095                        glLabelObject *object)
1096 {
1097         gdouble  line_width;
1098         guint    line_color;
1099         gdouble  w, h;
1100
1101         gl_debug (DEBUG_XML, "START");
1102
1103         xmlSetProp (object_node, "type", "Line");
1104
1105         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1106         line_width = gl_label_line_get_line_width (GL_LABEL_LINE(object));
1107         line_color = gl_label_line_get_line_color (GL_LABEL_LINE(object));
1108
1109         gl_xml_set_prop_double (object_node, "dx", w);
1110         gl_xml_set_prop_double (object_node, "dy", h);
1111
1112         gl_xml_set_prop_double (object_node, "line_width", line_width);
1113
1114         gl_xml_set_prop_uint_hex (object_node, "line_color", line_color);
1115
1116         gl_debug (DEBUG_XML, "END");
1117 }
1118
1119 /*--------------------------------------------------------------------------*/
1120 /* PRIVATE.  Add XML Label->Ellipse Node Properties                         */
1121 /*--------------------------------------------------------------------------*/
1122 static void
1123 xml_create_ellipse_props (xmlNodePtr     object_node,
1124                           xmlNsPtr       ns,
1125                           glLabelObject *object)
1126 {
1127         gdouble  line_width;
1128         guint    line_color, fill_color;
1129         gdouble  w, h;
1130
1131         gl_debug (DEBUG_XML, "START");
1132
1133         xmlSetProp (object_node, "type", "Ellipse");
1134
1135         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1136         line_width = gl_label_ellipse_get_line_width (GL_LABEL_ELLIPSE(object));
1137         line_color = gl_label_ellipse_get_line_color (GL_LABEL_ELLIPSE(object));
1138         fill_color = gl_label_ellipse_get_fill_color (GL_LABEL_ELLIPSE(object));
1139
1140         gl_xml_set_prop_double (object_node, "w", w);
1141         gl_xml_set_prop_double (object_node, "h", h);
1142
1143         gl_xml_set_prop_double (object_node, "line_width", line_width);
1144
1145         gl_xml_set_prop_uint_hex (object_node, "line_color", line_color);
1146         gl_xml_set_prop_uint_hex (object_node, "fill_color", fill_color);
1147
1148         gl_debug (DEBUG_XML, "END");
1149 }
1150
1151 /*--------------------------------------------------------------------------*/
1152 /* PRIVATE.  Add XML Label->Image Node Properties                           */
1153 /*--------------------------------------------------------------------------*/
1154 static void
1155 xml_create_image_props (xmlNodePtr     object_node,
1156                         xmlNsPtr       ns,
1157                         glLabelObject *object)
1158 {
1159         gdouble     w, h;
1160         glTextNode *filename;
1161         xmlNodePtr  child;
1162
1163         gl_debug (DEBUG_XML, "START");
1164
1165         xmlSetProp (object_node, "type", "Image");
1166
1167         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1168         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1169
1170         gl_xml_set_prop_double (object_node, "w", w);
1171         gl_xml_set_prop_double (object_node, "h", h);
1172
1173         if (filename->field_flag) {
1174                 child = xmlNewChild (object_node, ns, "Field", NULL);
1175                 xmlSetProp (child, "name", filename->data);
1176         } else {
1177                 child = xmlNewChild (object_node, ns, "File", NULL);
1178                 xmlSetProp (child, "src", filename->data);
1179         }
1180
1181         gl_text_node_free (&filename);
1182
1183         gl_debug (DEBUG_XML, "END");
1184 }
1185
1186 /*--------------------------------------------------------------------------*/
1187 /* PRIVATE.  Add XML Label->Barcode Node Properties                         */
1188 /*--------------------------------------------------------------------------*/
1189 static void
1190 xml_create_barcode_props (xmlNodePtr     object_node,
1191                           xmlNsPtr       ns,
1192                           glLabelObject *object)
1193 {
1194         gdouble     w, h;
1195         glTextNode          *text_node;
1196         glBarcodeStyle      style;
1197         gboolean            text_flag;
1198         gboolean            checksum_flag;
1199         guint               color;
1200         xmlNodePtr          child;
1201
1202         gl_debug (DEBUG_XML, "START");
1203
1204         xmlSetProp (object_node, "type", "Barcode");
1205
1206         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1207                
1208         gl_xml_set_prop_double (object_node, "w", w);
1209         gl_xml_set_prop_double (object_node, "h", h);
1210                         
1211
1212         text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1213         gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1214                                     &style, &text_flag, &checksum_flag, &color);
1215
1216         gl_xml_set_prop_uint_hex (object_node, "color", color);
1217
1218         xmlSetProp (object_node, "style", gl_barcode_style_to_text (style));
1219         gl_xml_set_prop_boolean (object_node, "text", text_flag);
1220         gl_xml_set_prop_boolean (object_node, "checksum", checksum_flag);
1221
1222         if (text_node->field_flag) {
1223                 child = xmlNewChild (object_node, ns, "Field", NULL);
1224                 xmlSetProp (child, "name", text_node->data);
1225         } else {
1226                 child = xmlNewChild (object_node, ns, "Literal", text_node->data);
1227         }
1228
1229         gl_text_node_free (&text_node);
1230
1231         gl_debug (DEBUG_XML, "END");
1232 }
1233
1234 /*--------------------------------------------------------------------------*/
1235 /* PRIVATE.  Add XML Label Merge Fields Node                                */
1236 /*--------------------------------------------------------------------------*/
1237 static void
1238 xml_create_merge_fields (xmlNodePtr  root,
1239                          xmlNsPtr    ns,
1240                          glLabel    *label)
1241 {
1242         xmlNodePtr  node, child;
1243         gchar      *string;
1244         GList      *p;
1245         glMerge    *merge;
1246
1247         gl_debug (DEBUG_XML, "START");
1248
1249         merge = gl_label_get_merge (label);
1250
1251         node = xmlNewChild (root, ns, "Merge_Fields", NULL);
1252
1253         string = gl_merge_get_name (merge);
1254         xmlSetProp (node, "type", string);
1255         g_free (string);
1256
1257         string = gl_merge_get_src (merge);
1258         xmlSetProp (node, "src", string);
1259         g_free (string);
1260
1261         g_object_unref (G_OBJECT(merge));
1262
1263         gl_debug (DEBUG_XML, "END");
1264 }
1265
1266 /*--------------------------------------------------------------------------*/
1267 /* PRIVATE.  Add XML Label Data Node                                        */
1268 /*--------------------------------------------------------------------------*/
1269 static void
1270 xml_create_data (xmlNodePtr  root,
1271                  xmlNsPtr    ns,
1272                  glLabel    *label)
1273 {
1274         xmlNodePtr  node;
1275         GList      *name_list, *p;
1276         GHashTable *pixbuf_cache;
1277
1278         gl_debug (DEBUG_XML, "START");
1279
1280         node = xmlNewChild (root, ns, "Data", NULL);
1281
1282         pixbuf_cache = gl_label_get_pixbuf_cache (label);
1283         name_list = gl_pixbuf_cache_get_name_list (pixbuf_cache);
1284
1285         for (p = name_list; p != NULL; p=p->next) {
1286                 xml_create_pixdata (node, ns, label, p->data);
1287         }
1288
1289         gl_pixbuf_cache_free_name_list (name_list);
1290
1291
1292         gl_debug (DEBUG_XML, "END");
1293 }
1294
1295 /*--------------------------------------------------------------------------*/
1296 /* PRIVATE.  Add XML Label Data Pixbuf Node                                 */
1297 /*--------------------------------------------------------------------------*/
1298 static void
1299 xml_create_pixdata (xmlNodePtr  root,
1300                     xmlNsPtr    ns,
1301                     glLabel    *label,
1302                     gchar      *name)
1303 {
1304         xmlNodePtr  node;
1305         GHashTable *pixbuf_cache;
1306         GdkPixbuf  *pixbuf;
1307         GdkPixdata *pixdata;
1308         guchar     *stream;
1309         guint       stream_length;
1310         gchar      *base64;
1311
1312         gl_debug (DEBUG_XML, "START");
1313
1314         pixbuf_cache = gl_label_get_pixbuf_cache (label);
1315
1316         pixbuf = gl_pixbuf_cache_get_pixbuf (pixbuf_cache, name);
1317         if ( pixbuf != NULL ) {
1318
1319                 pixdata = g_new0 (GdkPixdata, 1);
1320                 gdk_pixdata_from_pixbuf (pixdata, pixbuf, TRUE);
1321                 stream = gdk_pixdata_serialize (pixdata, &stream_length);
1322                 base64 = gl_base64_encode (stream, stream_length);
1323
1324                 node = xmlNewChild (root, ns, "Pixdata", base64);
1325                 xmlSetProp (node, "name", name);
1326                 xmlSetProp (node, "encoding", "base64");
1327
1328                 gl_pixbuf_cache_remove_pixbuf (pixbuf_cache, name);
1329
1330                 g_free (pixdata->pixel_data);
1331                 g_free (pixdata);
1332                 g_free (stream);
1333                 g_free (base64);
1334         }
1335
1336
1337         gl_debug (DEBUG_XML, "END");
1338 }
1339