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