]> git.sur5r.net Git - glabels/blob - glabels2/src/xml-label.c
Initial flipping support -- still has some problems.
[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         gchar *flip_string;
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         flip_string = xmlGetProp (object_node, "flip");
328         if ( g_strcasecmp (flip_string, "None") == 0 ) {
329                 gl_label_object_set_flip (object, GL_LABEL_OBJECT_FLIP_NONE);
330         } else if ( g_strcasecmp (flip_string, "Horiz") == 0 ) {
331                 gl_label_object_set_flip (object, GL_LABEL_OBJECT_FLIP_HORIZ);
332         } else if ( g_strcasecmp (flip_string, "Vert") == 0 ) {
333                 gl_label_object_set_flip (object, GL_LABEL_OBJECT_FLIP_VERT);
334         } else if ( g_strcasecmp (flip_string, "Both") == 0 ) {
335                 gl_label_object_set_flip (object, GL_LABEL_OBJECT_FLIP_BOTH);
336         } else {
337                 g_warning ("Unknown flip type \"%s\"", flip_string);
338                 return;
339         }
340
341         gl_debug (DEBUG_XML, "END");
342 }
343
344 /*--------------------------------------------------------------------------*/
345 /* PRIVATE.  Parse XML Label->Text Node Properties                          */
346 /*--------------------------------------------------------------------------*/
347 static glLabelObject *
348 xml_parse_text_props (xmlNodePtr object_node,
349                       glLabel * label)
350 {
351         GObject *object;
352         GList *lines;
353         gchar *font_family;
354         gdouble font_size;
355         GnomeFontWeight font_weight;
356         gboolean font_italic_flag;
357         guint color;
358         GtkJustification just;
359         xmlNodePtr line_node, text_node;
360         glTextNode *node_text;
361         GList *nodes;
362
363         gl_debug (DEBUG_XML, "START");
364
365         object = gl_label_text_new (label);
366
367         font_family = xmlGetProp (object_node, "font_family");
368         font_size = g_strtod (xmlGetProp (object_node, "font_size"), NULL);
369         font_weight = gl_util_string_to_weight (xmlGetProp (object_node,
370                                                           "font_weight"));
371         font_italic_flag =
372                 !(g_strcasecmp (xmlGetProp (object_node, "font_italic"), "false") ==
373                   0);
374
375         just = gl_util_string_to_just (xmlGetProp (object_node, "justify"));
376
377         sscanf (xmlGetProp (object_node, "color"), "%x", &color);
378
379         lines = NULL;
380         for (line_node = object_node->xmlChildrenNode;
381              line_node != NULL;
382              line_node = line_node->next) {
383
384                 if (g_strcasecmp (line_node->name, "Line") == 0) {
385
386                         nodes = NULL;
387                         for (text_node = line_node->xmlChildrenNode;
388                              text_node != NULL; text_node = text_node->next) {
389
390                                 if (g_strcasecmp (text_node->name, "Field") ==
391                                     0) {
392                                         node_text = g_new0 (glTextNode, 1);
393                                         node_text->field_flag = TRUE;
394                                         node_text->data =
395                                                 xmlGetProp (text_node, "name");
396                                         nodes =
397                                                 g_list_append (nodes, node_text);
398                                 } else if (xmlNodeIsText (text_node)) {
399                                         node_text = g_new0 (glTextNode, 1);
400                                         node_text->field_flag = FALSE;
401                                         node_text->data =
402                                                 xmlNodeGetContent (text_node);
403                                         nodes =
404                                                 g_list_append (nodes, node_text);
405                                 } else {
406                                         g_warning ("Unexpected Text Line child: \"%s\"",
407                                                    text_node->name);
408                                 }
409
410                         }
411                         lines = g_list_append (lines, nodes);
412
413                 } else if (!xmlNodeIsText (line_node)) {
414                         g_warning ("Unexpected Text child: \"%s\"",
415                                    line_node->name);
416                 }
417
418         }
419
420         gl_label_text_set_lines (GL_LABEL_TEXT(object), lines);
421         gl_label_text_set_props (GL_LABEL_TEXT(object),
422                                  font_family, font_size, font_weight,
423                                  font_italic_flag,
424                                  color, just);
425
426         gl_text_node_lines_free (&lines);
427         g_free (font_family);
428
429         gl_debug (DEBUG_XML, "END");
430
431         return GL_LABEL_OBJECT(object);
432 }
433
434 /*--------------------------------------------------------------------------*/
435 /* PRIVATE.  Parse XML Label->Box Node Properties                           */
436 /*--------------------------------------------------------------------------*/
437 static glLabelObject *
438 xml_parse_box_props (xmlNodePtr node,
439                      glLabel * label)
440 {
441         GObject *object;
442         gdouble line_width;
443         guint line_color, fill_color;
444         gdouble w, h;
445
446         gl_debug (DEBUG_XML, "START");
447
448         object = gl_label_box_new (label);
449
450         w = g_strtod (xmlGetProp (node, "w"), NULL);
451         h = g_strtod (xmlGetProp (node, "h"), NULL);
452
453         line_width = g_strtod (xmlGetProp (node, "line_width"), NULL);
454
455         sscanf (xmlGetProp (node, "line_color"), "%x", &line_color);
456         sscanf (xmlGetProp (node, "fill_color"), "%x", &fill_color);
457
458         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
459         gl_label_box_set_line_width (GL_LABEL_BOX(object), line_width);
460         gl_label_box_set_line_color (GL_LABEL_BOX(object), line_color);
461         gl_label_box_set_fill_color (GL_LABEL_BOX(object), fill_color);
462
463         gl_debug (DEBUG_XML, "END");
464
465         return GL_LABEL_OBJECT(object);
466 }
467
468 /*--------------------------------------------------------------------------*/
469 /* PRIVATE.  Parse XML Label->Line Node Properties                          */
470 /*--------------------------------------------------------------------------*/
471 static glLabelObject *
472 xml_parse_line_props (xmlNodePtr node,
473                       glLabel * label)
474 {
475         GObject *object;
476         gdouble line_width;
477         guint line_color;
478         gdouble w, h;
479
480         gl_debug (DEBUG_XML, "START");
481
482         object = gl_label_line_new (label);
483
484         w = g_strtod (xmlGetProp (node, "dx"), NULL);
485         h = g_strtod (xmlGetProp (node, "dy"), NULL);
486
487         line_width = g_strtod (xmlGetProp (node, "line_width"), NULL);
488
489         sscanf (xmlGetProp (node, "line_color"), "%x", &line_color);
490
491         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
492         gl_label_line_set_line_width (GL_LABEL_LINE(object), line_width);
493         gl_label_line_set_line_color (GL_LABEL_LINE(object), line_color);
494
495         gl_debug (DEBUG_XML, "END");
496
497         return GL_LABEL_OBJECT(object);
498 }
499
500 /*--------------------------------------------------------------------------*/
501 /* PRIVATE.  Parse XML Label->Ellipse Node Properties                       */
502 /*--------------------------------------------------------------------------*/
503 static glLabelObject *
504 xml_parse_ellipse_props (xmlNodePtr node,
505                          glLabel * label)
506 {
507         GObject *object;
508         gdouble line_width;
509         guint line_color, fill_color;
510         gdouble w, h;
511
512         gl_debug (DEBUG_XML, "START");
513
514         object = gl_label_ellipse_new (label);
515
516         w = g_strtod (xmlGetProp (node, "w"), NULL);
517         h = g_strtod (xmlGetProp (node, "h"), NULL);
518
519         line_width = g_strtod (xmlGetProp (node, "line_width"), NULL);
520
521         sscanf (xmlGetProp (node, "line_color"), "%x", &line_color);
522         sscanf (xmlGetProp (node, "fill_color"), "%x", &fill_color);
523
524         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
525         gl_label_ellipse_set_line_width (GL_LABEL_ELLIPSE(object), line_width);
526         gl_label_ellipse_set_line_color (GL_LABEL_ELLIPSE(object), line_color);
527         gl_label_ellipse_set_fill_color (GL_LABEL_ELLIPSE(object), fill_color);
528
529         gl_debug (DEBUG_XML, "END");
530
531         return GL_LABEL_OBJECT(object);
532 }
533
534 /*--------------------------------------------------------------------------*/
535 /* PRIVATE.  Parse XML Label->Image Node Properties                         */
536 /*--------------------------------------------------------------------------*/
537 static glLabelObject *
538 xml_parse_image_props (xmlNodePtr node,
539                        glLabel *label)
540 {
541         GObject *object;
542         gdouble w, h;
543         gchar   *filename;
544
545         gl_debug (DEBUG_XML, "START");
546
547         object = gl_label_image_new (label);
548
549         w = g_strtod (xmlGetProp (node, "w"), NULL);
550         h = g_strtod (xmlGetProp (node, "h"), NULL);
551
552         filename = xmlNodeGetContent (node);
553
554         gl_label_object_set_size (GL_LABEL_OBJECT(object), w, h);
555         gl_label_image_set_filename (GL_LABEL_IMAGE(object), filename);
556
557         g_free (filename);
558
559         gl_debug (DEBUG_XML, "END");
560
561         return GL_LABEL_OBJECT(object);
562 }
563
564 /*--------------------------------------------------------------------------*/
565 /* PRIVATE.  Parse XML Label->Barcode Node Properties                       */
566 /*--------------------------------------------------------------------------*/
567 static glLabelObject *
568 xml_parse_barcode_props (xmlNodePtr node,
569                          glLabel *label)
570 {
571         GObject *object;
572         xmlNodePtr child;
573         glTextNode          *text_node;
574         glBarcodeStyle      style;
575         gboolean            text_flag;
576         guint               color;
577         gdouble             scale;
578
579         gl_debug (DEBUG_XML, "START");
580
581         object = gl_label_barcode_new (label);
582
583         sscanf (xmlGetProp (node, "color"), "%x", &color);
584
585         style = gl_barcode_text_to_style (xmlGetProp (node, "style"));
586         text_flag = !(g_strcasecmp (xmlGetProp (node, "text"), "false") == 0);
587         scale = g_strtod (xmlGetProp (node, "scale"), NULL);
588
589         child = node->xmlChildrenNode;
590         text_node = g_new0 (glTextNode, 1);
591         if (g_strcasecmp (child->name, "Field") == 0) {
592                 text_node->field_flag = TRUE;
593                 text_node->data = xmlGetProp (child, "name");
594         } else if (xmlNodeIsText (child)) {
595                 text_node->field_flag = FALSE;
596                 text_node->data = xmlNodeGetContent (child);
597         } else {
598                 g_warning ("Unexpected Barcode child: \"%s\"", child->name);
599         }
600
601         gl_label_barcode_set_data (GL_LABEL_BARCODE(object), text_node);
602         gl_label_barcode_set_props (GL_LABEL_BARCODE(object),
603                                     style, text_flag, color, scale);
604
605         gl_text_node_free (&text_node);
606
607         gl_debug (DEBUG_XML, "END");
608
609         return GL_LABEL_OBJECT(object);
610 }
611
612 /*--------------------------------------------------------------------------*/
613 /* PRIVATE.  Parse XML merge fields tag.                                */
614 /*--------------------------------------------------------------------------*/
615 static void
616 xml_parse_merge_fields (xmlNodePtr node,
617                         glLabel * label)
618 {
619         xmlNodePtr child;
620         glMerge *merge;
621         glMergeFieldDefinition *field_def;
622
623         gl_debug (DEBUG_XML, "START");
624
625         merge = gl_merge_new ();
626
627         merge->type = gl_merge_text_to_type (xmlGetProp (node, "type"));
628         merge->src = xmlGetProp (node, "src");
629
630         for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
631
632                 if (g_strcasecmp (child->name, "Field") == 0) {
633                         field_def = g_new0 (glMergeFieldDefinition, 1);
634                         field_def->key = xmlGetProp (child, "key");
635                         field_def->loc = xmlGetProp (child, "loc");
636                         merge->field_defs =
637                             g_list_append (merge->field_defs,
638                                            field_def);
639                 } else if (!xmlNodeIsText (child)) {
640                         g_warning ("Unexpected Merge_Fields child: \"%s\"",
641                                    child->name);
642                 }
643
644         }
645
646         gl_label_set_merge (label, merge);
647
648         gl_merge_free (&merge);
649
650         gl_debug (DEBUG_XML, "END");
651 }
652
653 /****************************************************************************/
654 /* Save label to xml label file.                                            */
655 /****************************************************************************/
656 void
657 gl_xml_label_save (glLabel *label,
658                    const gchar *filename,
659                    glXMLLabelStatus *status)
660 {
661         xmlDocPtr doc;
662         gint xml_ret;
663
664         gl_debug (DEBUG_XML, "START");
665
666         doc = xml_label_to_doc (label, status);
667
668         xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
669         xmlFreeDoc (doc);
670         if (xml_ret == -1) {
671
672                 g_warning (_("Problem saving xml file."));
673                 *status = XML_LABEL_ERROR_SAVE_FILE;
674
675         } else {
676
677                 gl_label_set_filename (label, filename);
678                 gl_label_clear_modified (label);
679
680         }
681
682         gl_debug (DEBUG_XML, "END");
683 }
684
685 /****************************************************************************/
686 /* Save label to xml buffer.                                                */
687 /****************************************************************************/
688 gchar *
689 gl_xml_label_save_buffer (glLabel *label,
690                           glXMLLabelStatus *status)
691 {
692         xmlDocPtr doc;
693         gint size;
694         gchar *buffer;
695
696         gl_debug (DEBUG_XML, "START");
697
698         doc = xml_label_to_doc (label, status);
699
700         xmlDocDumpMemory (doc, (xmlChar **)&buffer, &size);
701         xmlFreeDoc (doc);
702
703         gl_label_clear_modified (label);
704
705         gl_debug (DEBUG_XML, "END");
706
707         return buffer;
708 }
709
710 /*--------------------------------------------------------------------------*/
711 /* PRIVATE.  Convert label to xml doc structure.                            */
712 /*--------------------------------------------------------------------------*/
713 static xmlDocPtr
714 xml_label_to_doc (glLabel * label,
715                   glXMLLabelStatus *status)
716 {
717         xmlDocPtr doc;
718         xmlNsPtr ns;
719         glTemplate *template;
720         glMerge *merge;
721
722         gl_debug (DEBUG_XML, "START");
723
724         LIBXML_TEST_VERSION;
725
726         doc = xmlNewDoc ("1.0");
727         doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Document", NULL);
728
729         ns = xmlNewNs (doc->xmlRootNode, NAME_SPACE, "glabels");
730         xmlSetNs (doc->xmlRootNode, ns);
731
732         template = gl_label_get_template (label);
733         gl_template_xml_add_sheet (template, doc->xmlRootNode, ns);
734
735         xml_create_objects (doc->xmlRootNode, ns, label);
736
737         merge = gl_label_get_merge (label);
738         gl_debug (DEBUG_XML, "merge=%p", merge);
739         if (merge->type != GL_MERGE_NONE) {
740                 xml_create_merge_fields (doc->xmlRootNode, ns, label);
741         }
742         gl_merge_free (&merge);
743
744         gl_debug (DEBUG_XML, "END");
745
746         *status = XML_LABEL_OK;
747         return doc;
748 }
749
750 /*--------------------------------------------------------------------------*/
751 /* PRIVATE.  Add XML Label->Objects Node                                    */
752 /*--------------------------------------------------------------------------*/
753 static void
754 xml_create_objects (xmlNodePtr root,
755                     xmlNsPtr ns,
756                     glLabel * label)
757 {
758         xmlNodePtr node;
759         gboolean rotate_flag;
760         GList *p;
761
762         gl_debug (DEBUG_XML, "START");
763
764         rotate_flag = gl_label_get_rotate_flag (label);
765
766         node = xmlNewChild (root, ns, "Objects", NULL);
767         xmlSetProp (node, "id", "0");
768         xmlSetProp (node, "rotate", rotate_flag ? "True" : "False");
769
770         for (p = label->objects; p != NULL; p = p->next) {
771                 xml_create_object (node, ns, GL_LABEL_OBJECT(p->data));
772         }
773
774         gl_debug (DEBUG_XML, "END");
775 }
776
777 /*--------------------------------------------------------------------------*/
778 /* PRIVATE.  Add XML label object Node                                      */
779 /*--------------------------------------------------------------------------*/
780 static void
781 xml_create_object (xmlNodePtr root,
782                    xmlNsPtr ns,
783                    glLabelObject * object)
784 {
785         xmlNodePtr object_node;
786         gdouble x, y;
787         gchar *string;
788
789         gl_debug (DEBUG_XML, "START");
790
791         object_node = xmlNewChild (root, ns, "Object", NULL);
792
793         gl_label_object_get_position (object, &x, &y);
794         string = g_strdup_printf ("%g", x);
795         xmlSetProp (object_node, "x", string);
796         g_free (string);
797         string = g_strdup_printf ("%g", y);
798         xmlSetProp (object_node, "y", string);
799         g_free (string);
800
801         xmlSetProp (object_node, "rotate", "0");
802
803         switch (gl_label_object_get_flip (object)) {
804         case GL_LABEL_OBJECT_FLIP_NONE:
805                 xmlSetProp (object_node, "flip",   "None");
806                 break;
807         case GL_LABEL_OBJECT_FLIP_HORIZ:
808                 xmlSetProp (object_node, "flip",   "Horiz");
809                 break;
810         case GL_LABEL_OBJECT_FLIP_VERT:
811                 xmlSetProp (object_node, "flip",   "Vert");
812                 break;
813         case GL_LABEL_OBJECT_FLIP_BOTH:
814                 xmlSetProp (object_node, "flip",   "Both");
815                 break;
816         default:
817                 g_assert_not_reached ();
818         }
819
820         if ( GL_IS_LABEL_TEXT(object) ) {
821                 xml_create_text_props (object_node, ns, object);
822         } else if ( GL_IS_LABEL_BOX(object) ) {
823                 xml_create_box_props (object_node, ns, object);
824         } else if ( GL_IS_LABEL_LINE(object) ) {
825                 xml_create_line_props (object_node, ns, object);
826         } else if ( GL_IS_LABEL_ELLIPSE(object) ) {
827                 xml_create_ellipse_props (object_node, ns, object);
828         } else if ( GL_IS_LABEL_IMAGE(object) ) {
829                 xml_create_image_props (object_node, ns, object);
830         } else if ( GL_IS_LABEL_BARCODE(object) ) {
831                 xml_create_barcode_props (object_node, ns, object);
832         } else {
833                 g_warning ("Unknown label object");
834         }
835
836         gl_debug (DEBUG_XML, "END");
837 }
838
839 /*--------------------------------------------------------------------------*/
840 /* PRIVATE.  Add XML Label->Text Node Properties                            */
841 /*--------------------------------------------------------------------------*/
842 static void
843 xml_create_text_props (xmlNodePtr object_node,
844                        xmlNsPtr ns,
845                        glLabelObject * object)
846 {
847         xmlNodePtr line_node, field_node;
848         GList *lines;
849         gchar *font_family;
850         gdouble font_size;
851         GnomeFontWeight font_weight;
852         gboolean font_italic_flag;
853         guint color;
854         GtkJustification just;
855         gchar *string;
856         GList *p_line, *p_node;
857         glTextNode *node_text;
858
859         gl_debug (DEBUG_XML, "START");
860
861         xmlSetProp (object_node, "type", "Text");
862
863         lines = gl_label_text_get_lines (GL_LABEL_TEXT(object));
864         gl_label_text_get_props (GL_LABEL_TEXT(object),
865                                  &font_family, &font_size, &font_weight,
866                                  &font_italic_flag,
867                                  &color, &just);
868
869         xmlSetProp (object_node, "font_family", font_family);
870         string = g_strdup_printf ("%g", font_size);
871         xmlSetProp (object_node, "font_size", string);
872         g_free (string);
873         xmlSetProp (object_node, "font_weight",
874                     gl_util_weight_to_string (font_weight));
875         xmlSetProp (object_node, "font_italic",
876                     font_italic_flag?"True":"False");
877
878         xmlSetProp (object_node, "justify", gl_util_just_to_string (just));
879
880         string = g_strdup_printf ("0x%08x", color);
881         xmlSetProp (object_node, "color", string);
882         g_free (string);
883
884         for (p_line = lines; p_line != NULL; p_line = p_line->next) {
885                 line_node = xmlNewChild (object_node, ns, "Line", NULL);
886
887                 for (p_node = (GList *) p_line->data; p_node != NULL;
888                      p_node = p_node->next) {
889                         node_text = (glTextNode *) p_node->data;
890
891                         if (node_text->field_flag) {
892                                 field_node =
893                                     xmlNewChild (line_node, ns, "Field", NULL);
894                                 xmlSetProp (field_node, "name",
895                                             node_text->data);
896                         } else {
897                                 xmlNodeAddContent (line_node, node_text->data);
898                         }
899
900                 }
901
902         }
903
904         gl_text_node_lines_free (&lines);
905         g_free (font_family);
906
907         gl_debug (DEBUG_XML, "END");
908 }
909
910 /*--------------------------------------------------------------------------*/
911 /* PRIVATE.  Add XML Label->Box Node Properties                             */
912 /*--------------------------------------------------------------------------*/
913 static void
914 xml_create_box_props (xmlNodePtr object_node,
915                       xmlNsPtr ns,
916                       glLabelObject * object)
917 {
918         gchar *string;
919         gdouble line_width;
920         guint line_color, fill_color;
921         gdouble w, h;
922
923         gl_debug (DEBUG_XML, "START");
924
925         xmlSetProp (object_node, "type", "Box");
926
927         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
928         line_width = gl_label_box_get_line_width (GL_LABEL_BOX(object));
929         line_color = gl_label_box_get_line_color (GL_LABEL_BOX(object));
930         fill_color = gl_label_box_get_fill_color (GL_LABEL_BOX(object));
931
932         string = g_strdup_printf ("%g", w);
933         xmlSetProp (object_node, "w", string);
934         g_free (string);
935         string = g_strdup_printf ("%g", h);
936         xmlSetProp (object_node, "h", string);
937         g_free (string);
938
939         string = g_strdup_printf ("%g", line_width);
940         xmlSetProp (object_node, "line_width", string);
941         g_free (string);
942
943         string = g_strdup_printf ("0x%08x", line_color);
944         xmlSetProp (object_node, "line_color", string);
945         g_free (string);
946
947         string = g_strdup_printf ("0x%08x", fill_color);
948         xmlSetProp (object_node, "fill_color", string);
949         g_free (string);
950
951         gl_debug (DEBUG_XML, "END");
952 }
953
954 /*--------------------------------------------------------------------------*/
955 /* PRIVATE.  Add XML Label->Line Node Properties                            */
956 /*--------------------------------------------------------------------------*/
957 static void
958 xml_create_line_props (xmlNodePtr object_node,
959                        xmlNsPtr ns,
960                        glLabelObject * object)
961 {
962         gchar *string;
963         gdouble line_width;
964         guint line_color;
965         gdouble w, h;
966
967         gl_debug (DEBUG_XML, "START");
968
969         xmlSetProp (object_node, "type", "Line");
970
971         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
972         line_width = gl_label_line_get_line_width (GL_LABEL_LINE(object));
973         line_color = gl_label_line_get_line_color (GL_LABEL_LINE(object));
974
975         string = g_strdup_printf ("%g", w);
976         xmlSetProp (object_node, "dx", string);
977         g_free (string);
978         string = g_strdup_printf ("%g", h);
979         xmlSetProp (object_node, "dy", string);
980         g_free (string);
981
982         string = g_strdup_printf ("%g", line_width);
983         xmlSetProp (object_node, "line_width", string);
984         g_free (string);
985
986         string = g_strdup_printf ("0x%08x", line_color);
987         xmlSetProp (object_node, "line_color", string);
988         g_free (string);
989
990         gl_debug (DEBUG_XML, "END");
991 }
992
993 /*--------------------------------------------------------------------------*/
994 /* PRIVATE.  Add XML Label->Ellipse Node Properties                         */
995 /*--------------------------------------------------------------------------*/
996 static void
997 xml_create_ellipse_props (xmlNodePtr object_node,
998                           xmlNsPtr ns,
999                           glLabelObject * object)
1000 {
1001         gchar *string;
1002         gdouble line_width;
1003         guint line_color, fill_color;
1004         gdouble w, h;
1005
1006         gl_debug (DEBUG_XML, "START");
1007
1008         xmlSetProp (object_node, "type", "Ellipse");
1009
1010         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1011         line_width = gl_label_ellipse_get_line_width (GL_LABEL_ELLIPSE(object));
1012         line_color = gl_label_ellipse_get_line_color (GL_LABEL_ELLIPSE(object));
1013         fill_color = gl_label_ellipse_get_fill_color (GL_LABEL_ELLIPSE(object));
1014
1015         string = g_strdup_printf ("%g", w);
1016         xmlSetProp (object_node, "w", string);
1017         g_free (string);
1018         string = g_strdup_printf ("%g", h);
1019         xmlSetProp (object_node, "h", string);
1020         g_free (string);
1021
1022         string = g_strdup_printf ("%g", line_width);
1023         xmlSetProp (object_node, "line_width", string);
1024         g_free (string);
1025
1026         string = g_strdup_printf ("0x%08x", line_color);
1027         xmlSetProp (object_node, "line_color", string);
1028         g_free (string);
1029
1030         string = g_strdup_printf ("0x%08x", fill_color);
1031         xmlSetProp (object_node, "fill_color", string);
1032         g_free (string);
1033
1034         gl_debug (DEBUG_XML, "END");
1035 }
1036
1037 /*--------------------------------------------------------------------------*/
1038 /* PRIVATE.  Add XML Label->Image Node Properties                           */
1039 /*--------------------------------------------------------------------------*/
1040 static void
1041 xml_create_image_props (xmlNodePtr object_node,
1042                         xmlNsPtr ns,
1043                         glLabelObject * object)
1044 {
1045         gchar *string;
1046         gdouble w, h;
1047         gchar *filename;
1048
1049         gl_debug (DEBUG_XML, "START");
1050
1051         xmlSetProp (object_node, "type", "Image");
1052
1053         gl_label_object_get_size (GL_LABEL_OBJECT(object), &w, &h);
1054         filename = gl_label_image_get_filename (GL_LABEL_IMAGE(object));
1055
1056         string = g_strdup_printf ("%g", w);
1057         xmlSetProp (object_node, "w", string);
1058         g_free (string);
1059         string = g_strdup_printf ("%g", h);
1060         xmlSetProp (object_node, "h", string);
1061         g_free (string);
1062
1063         xmlNodeSetContent (object_node, filename);
1064
1065         g_free (filename);
1066
1067         gl_debug (DEBUG_XML, "END");
1068 }
1069
1070 /*--------------------------------------------------------------------------*/
1071 /* PRIVATE.  Add XML Label->Barcode Node Properties                         */
1072 /*--------------------------------------------------------------------------*/
1073 static void
1074 xml_create_barcode_props (xmlNodePtr object_node,
1075                           xmlNsPtr ns,
1076                           glLabelObject * object)
1077 {
1078         glTextNode          *text_node;
1079         glBarcodeStyle      style;
1080         gboolean            text_flag;
1081         guint               color;
1082         gdouble             scale;
1083         xmlNodePtr child;
1084         gchar *string;
1085
1086         gl_debug (DEBUG_XML, "START");
1087
1088         xmlSetProp (object_node, "type", "Barcode");
1089
1090         text_node = gl_label_barcode_get_data (GL_LABEL_BARCODE(object));
1091         gl_label_barcode_get_props (GL_LABEL_BARCODE(object),
1092                                     &style, &text_flag, &color, &scale);
1093
1094         string = g_strdup_printf ("0x%08x", color);
1095         xmlSetProp (object_node, "color", string);
1096         g_free (string);
1097
1098         xmlSetProp (object_node, "style", gl_barcode_style_to_text (style));
1099         xmlSetProp (object_node, "text", text_flag?"True":"False");
1100         string = g_strdup_printf ("%g", scale);
1101         xmlSetProp (object_node, "scale", string);
1102         g_free (string);
1103
1104         if (text_node->field_flag) {
1105                 child = xmlNewChild (object_node, ns, "Field", NULL);
1106                 xmlSetProp (child, "name", text_node->data);
1107         } else {
1108                 xmlNodeSetContent (object_node, text_node->data);
1109         }
1110
1111         gl_text_node_free (&text_node);
1112
1113         gl_debug (DEBUG_XML, "END");
1114 }
1115
1116 /*--------------------------------------------------------------------------*/
1117 /* PRIVATE.  Add XML Label Merge Fields Node                                */
1118 /*--------------------------------------------------------------------------*/
1119 static void
1120 xml_create_merge_fields (xmlNodePtr root,
1121                              xmlNsPtr ns,
1122                              glLabel * label)
1123 {
1124         xmlNodePtr node, child;
1125         gchar *string;
1126         GList *p;
1127         glMerge *merge;
1128         glMergeFieldDefinition *field_def;
1129
1130         gl_debug (DEBUG_XML, "START");
1131
1132         merge = gl_label_get_merge (label);
1133
1134         node = xmlNewChild (root, ns, "Merge_Fields", NULL);
1135
1136         string = gl_merge_type_to_text (merge->type);
1137         xmlSetProp (node, "type", string);
1138         g_free (string);
1139
1140         xmlSetProp (node, "src", merge->src);
1141
1142         for (p = merge->field_defs; p != NULL; p = p->next) {
1143                 field_def = (glMergeFieldDefinition *) p->data;
1144
1145                 child = xmlNewChild (node, ns, "Field", NULL);
1146                 xmlSetProp (child, "key", field_def->key);
1147                 xmlSetProp (child, "loc", field_def->loc);
1148         }
1149
1150         gl_merge_free (&merge);
1151
1152         gl_debug (DEBUG_XML, "END");
1153 }
1154