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