]> git.sur5r.net Git - glabels/blob - glabels2/libglabels/xml-template.c
2007-09-27 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / libglabels / xml-template.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (LIBGLABELS) Template library for GLABELS
5  *
6  *  xml-template.c:  template xml module
7  *
8  *  Copyright (C) 2001-2006  Jim Evins <evins@snaught.com>.
9  *
10  *  This file is part of the LIBGLABELS library.
11  *
12  *  This library is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Library General Public
14  *  License as published by the Free Software Foundation; either
15  *  version 2 of the License, or (at your option) any later version.
16  *
17  *  This library is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  *  Library General Public License for more details.
21  *
22  *  You should have received a copy of the GNU Library General Public
23  *  License along with this library; if not, write to the Free
24  *  Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  *  MA 02111-1307, USA
26  */
27 #include <config.h>
28
29 #include "xml-template.h"
30
31 #include <glib/gi18n.h>
32 #include <glib/gmessages.h>
33 #include <string.h>
34 #include <libintl.h>
35
36 #include "libglabels-private.h"
37
38 #include "paper.h"
39 #include "xml.h"
40
41 /*===========================================*/
42 /* Private types                             */
43 /*===========================================*/
44
45 /*===========================================*/
46 /* Private globals                           */
47 /*===========================================*/
48
49 /*===========================================*/
50 /* Local function prototypes                 */
51 /*===========================================*/
52 static void  xml_parse_meta_node            (xmlNodePtr              label_node,
53                                              lglTemplate            *template);
54 static void  xml_parse_label_rectangle_node (xmlNodePtr              label_node,
55                                              lglTemplate            *template);
56 static void  xml_parse_label_round_node     (xmlNodePtr              label_node,
57                                              lglTemplate            *template);
58 static void  xml_parse_label_cd_node        (xmlNodePtr              label_node,
59                                              lglTemplate            *template);
60 static void  xml_parse_layout_node          (xmlNodePtr              layout_node,
61                                              lglTemplateFrame       *frame);
62 static void  xml_parse_markup_margin_node   (xmlNodePtr              markup_node,
63                                              lglTemplateFrame       *frame);
64 static void  xml_parse_markup_line_node     (xmlNodePtr              markup_node,
65                                              lglTemplateFrame       *frame);
66 static void  xml_parse_markup_circle_node   (xmlNodePtr              markup_node,
67                                              lglTemplateFrame       *frame);
68 static void  xml_parse_markup_rect_node     (xmlNodePtr              markup_node,
69                                              lglTemplateFrame       *frame);
70 static void  xml_parse_alias_node           (xmlNodePtr              alias_node,
71                                              lglTemplate            *template);
72
73 static void  xml_create_meta_node           (const gchar                  *category,
74                                              xmlNodePtr                    root,
75                                              const xmlNsPtr                ns);
76 static void  xml_create_label_node          (const lglTemplateFrame       *frame,
77                                              xmlNodePtr                    root,
78                                              const xmlNsPtr                ns);
79 static void  xml_create_layout_node         (const lglTemplateLayout      *layout,
80                                              xmlNodePtr                    root,
81                                              const xmlNsPtr                ns);
82 static void  xml_create_markup_margin_node  (const lglTemplateMarkup      *margin,
83                                              xmlNodePtr                    root,
84                                              const xmlNsPtr                ns);
85 static void  xml_create_markup_line_node    (const lglTemplateMarkup      *line,
86                                              xmlNodePtr                    root,
87                                              const xmlNsPtr                ns);
88 static void  xml_create_markup_circle_node  (const lglTemplateMarkup      *circle,
89                                              xmlNodePtr                    root,
90                                              const xmlNsPtr                ns);
91 static void  xml_create_markup_rect_node    (const lglTemplateMarkup      *circle,
92                                              xmlNodePtr                    root,
93                                              const xmlNsPtr                ns);
94 static void  xml_create_alias_node          (const gchar                  *name,
95                                              xmlNodePtr                    root,
96                                              const xmlNsPtr                ns);
97
98
99 /**
100  * lgl_xml_template_read_templates_from_file:
101  * @utf8_filename:       Filename of papers file (name encoded as UTF-8)
102  *
103  * Read glabels templates from template file.
104  *
105  * Returns: a list of #lglTemplate structures.
106  *
107  */
108 GList *
109 lgl_xml_template_read_templates_from_file (const gchar *utf8_filename)
110 {
111         gchar      *filename;
112         xmlDocPtr   templates_doc;
113         GList      *templates = NULL;
114
115         LIBXML_TEST_VERSION;
116
117         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
118         if (!filename) {
119                 g_message ("Utf8 filename conversion error");
120                 return NULL;
121         }
122
123         templates_doc = xmlParseFile (filename);
124         if (!templates_doc) {
125                 g_message ("\"%s\" is not a glabels template file (not XML)",
126                       filename);
127                 return templates;
128         }
129
130         templates = lgl_xml_template_parse_templates_doc (templates_doc);
131
132         g_free (filename);
133         xmlFreeDoc (templates_doc);
134
135         return templates;
136 }
137
138
139 /**
140  * lgl_xml_template_parse_templates_doc:
141  * @templates_doc:  libxml #xmlDocPtr tree, representing template file.
142  *
143  * Read glabels templates from a libxml #xmlDocPtr tree.
144  *
145  * Returns: a list of #lglTemplate structures.
146  *
147  */
148 GList *
149 lgl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
150 {
151         
152         GList       *templates = NULL;
153         xmlNodePtr   root, node;
154         lglTemplate *template;
155
156         LIBXML_TEST_VERSION;
157
158         root = xmlDocGetRootElement (templates_doc);
159         if (!root || !root->name) {
160                 g_message ("\"%s\" is not a glabels template file (no root node)",
161                            templates_doc->URL);
162                 return templates;
163         }
164         if (!lgl_xml_is_node (root, "Glabels-templates")) {
165                 g_message ("\"%s\" is not a glabels template file (wrong root node)",
166                       templates_doc->URL);
167                 return templates;
168         }
169
170         for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
171
172                 if (lgl_xml_is_node (node, "Template")) {
173                         template = lgl_xml_template_parse_template_node (node);
174                         templates = g_list_append (templates, template);
175                 } else {
176                         if ( !xmlNodeIsText(node) ) {
177                                 if (!lgl_xml_is_node (node,"comment")) {
178                                         g_message ("bad node =  \"%s\"",node->name);
179                                 }
180                         }
181                 }
182         }
183
184         return templates;
185 }
186
187
188 /**
189  * lgl_xml_template_parse_template_node:
190  * @template_node:  libxml #xmlNodePtr template node from a #xmlDocPtr tree.
191  *
192  * Read a single glabels template from a libxml #xmlNodePtr node.
193  *
194  * Returns: a pointer to a newly created #lglTemplate structure.
195  *
196  */
197 lglTemplate *
198 lgl_xml_template_parse_template_node (const xmlNodePtr template_node)
199 {
200         gchar                 *name;
201         gchar                 *description;
202         gchar                 *page_size;
203         gdouble                page_width, page_height;
204         lglPaper               *paper = NULL;
205         lglTemplate           *template;
206         xmlNodePtr             node;
207
208         name = lgl_xml_get_prop_string (template_node, "name", NULL);
209         description = lgl_xml_get_prop_i18n_string (template_node, "description", NULL);
210         page_size = lgl_xml_get_prop_string (template_node, "size", NULL);
211
212         if (lgl_paper_is_id_other (page_size)) {
213
214                 page_width = lgl_xml_get_prop_length (template_node, "width", 0);
215                 page_height = lgl_xml_get_prop_length (template_node, "height", 0);
216
217         } else {
218                 paper = lgl_paper_from_id (page_size);
219                 if (paper == NULL) {
220                         /* This should always be an id, but just in case a name
221                            slips by! */
222                         g_message (_("Unknown page size id \"%s\", trying as name"),
223                                    page_size);
224                         paper = lgl_paper_from_name (page_size);
225                         g_free (page_size);
226                         page_size = g_strdup (paper->id);
227                 }
228                 if (paper != NULL) {
229                         page_width  = paper->width;
230                         page_height = paper->height;
231                 } else {
232                         g_message (_("Unknown page size id or name \"%s\""),
233                                    page_size);
234                 }
235                 lgl_paper_free (paper);
236                 paper = NULL;
237         }
238
239         template = lgl_template_new (name,
240                                     description,
241                                     page_size,
242                                     page_width, page_height);
243
244         for (node = template_node->xmlChildrenNode; node != NULL;
245              node = node->next) {
246                 if (lgl_xml_is_node (node, "Meta")) {
247                         xml_parse_meta_node (node, template);
248                 } else if (lgl_xml_is_node (node, "Label-rectangle")) {
249                         xml_parse_label_rectangle_node (node, template);
250                 } else if (lgl_xml_is_node (node, "Label-round")) {
251                         xml_parse_label_round_node (node, template);
252                 } else if (lgl_xml_is_node (node, "Label-cd")) {
253                         xml_parse_label_cd_node (node, template);
254                 } else if (lgl_xml_is_node (node, "Alias")) {
255                         xml_parse_alias_node (node, template);
256                 } else {
257                         if (!xmlNodeIsText (node)) {
258                                 if (!lgl_xml_is_node (node,"comment")) {
259                                         g_message ("bad node =  \"%s\"",node->name);
260                                 }
261                         }
262                 }
263         }
264
265         g_free (name);
266         g_free (description);
267         g_free (page_size);
268
269         return template;
270 }
271
272 /*--------------------------------------------------------------------------*/
273 /* PRIVATE.  Parse XML Template->Meta Node.                                 */
274 /*--------------------------------------------------------------------------*/
275 static void
276 xml_parse_meta_node (xmlNodePtr   meta_node,
277                      lglTemplate *template)
278 {
279         gchar               *category;
280
281         category = lgl_xml_get_prop_string (meta_node, "category", NULL);
282
283         if (category != NULL)
284         {
285                 lgl_template_add_category (template, category);
286                 g_free (category);
287         }
288 }
289
290 /*--------------------------------------------------------------------------*/
291 /* PRIVATE.  Parse XML Template->Label-rectangle Node.                      */
292 /*--------------------------------------------------------------------------*/
293 static void
294 xml_parse_label_rectangle_node (xmlNodePtr   label_node,
295                                 lglTemplate *template)
296 {
297         gchar               *id;
298         gchar               *tmp;
299         gdouble              x_waste, y_waste;
300         gdouble              w, h, r;
301         lglTemplateFrame    *frame;
302         xmlNodePtr           node;
303
304         id      = lgl_xml_get_prop_string (label_node, "id", NULL);
305
306         if ((tmp = lgl_xml_get_prop_string (label_node, "waste", NULL))) {
307                 /* Handle single "waste" property. */
308                 x_waste = y_waste = lgl_xml_get_prop_length (label_node, "waste", 0);
309                 g_free (tmp);
310         } else {
311                 x_waste = lgl_xml_get_prop_length (label_node, "x_waste", 0);
312                 y_waste = lgl_xml_get_prop_length (label_node, "y_waste", 0);
313         }
314
315         w       = lgl_xml_get_prop_length (label_node, "width", 0);
316         h       = lgl_xml_get_prop_length (label_node, "height", 0);
317         r       = lgl_xml_get_prop_length (label_node, "round", 0);
318
319         frame = lgl_template_frame_rect_new ((gchar *)id, w, h, r, x_waste, y_waste);
320         lgl_template_add_frame (template, frame);
321
322         for (node = label_node->xmlChildrenNode; node != NULL;
323              node = node->next) {
324                 if (lgl_xml_is_node (node, "Layout")) {
325                         xml_parse_layout_node (node, frame);
326                 } else if (lgl_xml_is_node (node, "Markup-margin")) {
327                         xml_parse_markup_margin_node (node, frame);
328                 } else if (lgl_xml_is_node (node, "Markup-line")) {
329                         xml_parse_markup_line_node (node, frame);
330                 } else if (lgl_xml_is_node (node, "Markup-circle")) {
331                         xml_parse_markup_circle_node (node, frame);
332                 } else if (lgl_xml_is_node (node, "Markup-rect")) {
333                         xml_parse_markup_rect_node (node, frame);
334                 } else if (!xmlNodeIsText (node)) {
335                         if (!lgl_xml_is_node (node, "comment")) {
336                                 g_message ("bad node =  \"%s\"",node->name);
337                         }
338                 }
339         }
340
341         g_free (id);
342 }
343
344 /*--------------------------------------------------------------------------*/
345 /* PRIVATE.  Parse XML Template->Label-round Node.                          */
346 /*--------------------------------------------------------------------------*/
347 static void
348 xml_parse_label_round_node (xmlNodePtr   label_node,
349                             lglTemplate *template)
350 {
351         gchar               *id;
352         gdouble              waste;
353         gdouble              r;
354         lglTemplateFrame    *frame;
355         xmlNodePtr           node;
356
357         id    = lgl_xml_get_prop_string (label_node, "id", NULL);
358         waste = lgl_xml_get_prop_length (label_node, "waste", 0);
359         r     = lgl_xml_get_prop_length (label_node, "radius", 0);
360
361         frame = lgl_template_frame_round_new ((gchar *)id, r, waste);
362         lgl_template_add_frame (template, frame);
363
364         for (node = label_node->xmlChildrenNode; node != NULL;
365              node = node->next) {
366                 if (lgl_xml_is_node (node, "Layout")) {
367                         xml_parse_layout_node (node, frame);
368                 } else if (lgl_xml_is_node (node, "Markup-margin")) {
369                         xml_parse_markup_margin_node (node, frame);
370                 } else if (lgl_xml_is_node (node, "Markup-line")) {
371                         xml_parse_markup_line_node (node, frame);
372                 } else if (lgl_xml_is_node (node, "Markup-circle")) {
373                         xml_parse_markup_circle_node (node, frame);
374                 } else if (lgl_xml_is_node (node, "Markup-rect")) {
375                         xml_parse_markup_rect_node (node, frame);
376                 } else if (!xmlNodeIsText (node)) {
377                         if (!lgl_xml_is_node (node, "comment")) {
378                                 g_message ("bad node =  \"%s\"",node->name);
379                         }
380                 }
381         }
382
383         g_free (id);
384 }
385
386 /*--------------------------------------------------------------------------*/
387 /* PRIVATE.  Parse XML Template->Label-cd Node.                             */
388 /*--------------------------------------------------------------------------*/
389 static void
390 xml_parse_label_cd_node (xmlNodePtr   label_node,
391                          lglTemplate *template)
392 {
393         gchar               *id;
394         gdouble              waste;
395         gdouble              r1, r2, w, h;
396         lglTemplateFrame    *frame;
397         xmlNodePtr           node;
398
399         id    = lgl_xml_get_prop_string (label_node, "id", NULL);
400         waste = lgl_xml_get_prop_length (label_node, "waste", 0);
401         r1    = lgl_xml_get_prop_length (label_node, "radius", 0);
402         r2    = lgl_xml_get_prop_length (label_node, "hole", 0);
403         w     = lgl_xml_get_prop_length (label_node, "width", 0);
404         h     = lgl_xml_get_prop_length (label_node, "height", 0);
405
406         frame = lgl_template_frame_cd_new ((gchar *)id, r1, r2, w, h, waste);
407         lgl_template_add_frame (template, frame);
408
409         for (node = label_node->xmlChildrenNode; node != NULL;
410              node = node->next) {
411                 if (lgl_xml_is_node (node, "Layout")) {
412                         xml_parse_layout_node (node, frame);
413                 } else if (lgl_xml_is_node (node, "Markup-margin")) {
414                         xml_parse_markup_margin_node (node, frame);
415                 } else if (lgl_xml_is_node (node, "Markup-line")) {
416                         xml_parse_markup_line_node (node, frame);
417                 } else if (lgl_xml_is_node (node, "Markup-circle")) {
418                         xml_parse_markup_circle_node (node, frame);
419                 } else if (lgl_xml_is_node (node, "Markup-rect")) {
420                         xml_parse_markup_rect_node (node, frame);
421                 } else if (!xmlNodeIsText (node)) {
422                         if (!lgl_xml_is_node (node, "comment")) {
423                                 g_message ("bad node =  \"%s\"",node->name);
424                         }
425                 }
426         }
427
428         g_free (id);
429 }
430
431 /*--------------------------------------------------------------------------*/
432 /* PRIVATE.  Parse XML Template->Label->Layout Node.                        */
433 /*--------------------------------------------------------------------------*/
434 static void
435 xml_parse_layout_node (xmlNodePtr          layout_node,
436                        lglTemplateFrame   *frame)
437 {
438         gint        nx, ny;
439         gdouble     x0, y0, dx, dy;
440         xmlNodePtr  node;
441
442         nx = lgl_xml_get_prop_int (layout_node, "nx", 1);
443         ny = lgl_xml_get_prop_int (layout_node, "ny", 1);
444
445         x0 = lgl_xml_get_prop_length (layout_node, "x0", 0);
446         y0 = lgl_xml_get_prop_length (layout_node, "y0", 0);
447
448         dx = lgl_xml_get_prop_length (layout_node, "dx", 0);
449         dy = lgl_xml_get_prop_length (layout_node, "dy", 0);
450
451         lgl_template_add_layout (frame, lgl_template_layout_new (nx, ny, x0, y0, dx, dy));
452
453         for (node = layout_node->xmlChildrenNode; node != NULL;
454              node = node->next) {
455                 if (!xmlNodeIsText (node)) {
456                         if (!lgl_xml_is_node (node, "comment")) {
457                                 g_message ("bad node =  \"%s\"",node->name);
458                         }
459                 }
460         }
461
462 }
463
464 /*--------------------------------------------------------------------------*/
465 /* PRIVATE.  Parse XML Template->Label->Markup-margin Node.                 */
466 /*--------------------------------------------------------------------------*/
467 static void
468 xml_parse_markup_margin_node (xmlNodePtr          markup_node,
469                               lglTemplateFrame   *frame)
470 {
471         gdouble     size;
472         xmlNodePtr  node;
473
474         size = lgl_xml_get_prop_length (markup_node, "size", 0);
475
476         lgl_template_add_markup (frame, lgl_template_markup_margin_new (size));
477
478         for (node = markup_node->xmlChildrenNode; node != NULL;
479              node = node->next) {
480                 if (!xmlNodeIsText (node)) {
481                         if (!lgl_xml_is_node (node, "comment")) {
482                                 g_message ("bad node =  \"%s\"",node->name);
483                         }
484                 }
485         }
486
487 }
488
489 /*--------------------------------------------------------------------------*/
490 /* PRIVATE.  Parse XML Template->Label->Markup-line Node.                   */
491 /*--------------------------------------------------------------------------*/
492 static void
493 xml_parse_markup_line_node (xmlNodePtr          markup_node,
494                             lglTemplateFrame   *frame)
495 {
496         gdouble     x1, y1, x2, y2;
497         xmlNodePtr  node;
498
499         x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
500         y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
501         x2 = lgl_xml_get_prop_length (markup_node, "x2", 0);
502         y2 = lgl_xml_get_prop_length (markup_node, "y2", 0);
503
504         lgl_template_add_markup (frame, lgl_template_markup_line_new (x1, y1, x2, y2));
505
506         for (node = markup_node->xmlChildrenNode; node != NULL;
507              node = node->next) {
508                 if (!xmlNodeIsText (node)) {
509                         if (!lgl_xml_is_node (node, "comment")) {
510                                 g_message ("bad node =  \"%s\"",node->name);
511                         }
512                 }
513         }
514
515 }
516
517 /*--------------------------------------------------------------------------*/
518 /* PRIVATE.  Parse XML Template->Label->Markup-circle Node.                 */
519 /*--------------------------------------------------------------------------*/
520 static void
521 xml_parse_markup_circle_node (xmlNodePtr          markup_node,
522                               lglTemplateFrame   *frame)
523 {
524         gdouble     x0, y0, r;
525         xmlNodePtr  node;
526
527         x0 = lgl_xml_get_prop_length (markup_node, "x0", 0);
528         y0 = lgl_xml_get_prop_length (markup_node, "y0", 0);
529         r  = lgl_xml_get_prop_length (markup_node, "radius", 0);
530
531         lgl_template_add_markup (frame, lgl_template_markup_circle_new (x0, y0, r));
532
533         for (node = markup_node->xmlChildrenNode; node != NULL;
534              node = node->next) {
535                 if (!xmlNodeIsText (node)) {
536                         if (!lgl_xml_is_node (node, "comment")) {
537                                 g_message ("bad node =  \"%s\"",node->name);
538                         }
539                 }
540         }
541
542 }
543
544 /*--------------------------------------------------------------------------*/
545 /* PRIVATE.  Parse XML Template->Label->Markup-rect Node.                   */
546 /*--------------------------------------------------------------------------*/
547 static void
548 xml_parse_markup_rect_node (xmlNodePtr          markup_node,
549                             lglTemplateFrame   *frame)
550 {
551         gdouble     x1, y1, w, h, r;
552         xmlNodePtr  node;
553
554         x1 = lgl_xml_get_prop_length (markup_node, "x1", 0);
555         y1 = lgl_xml_get_prop_length (markup_node, "y1", 0);
556         w  = lgl_xml_get_prop_length (markup_node, "w", 0);
557         h  = lgl_xml_get_prop_length (markup_node, "h", 0);
558         r  = lgl_xml_get_prop_length (markup_node, "r", 0);
559
560         lgl_template_add_markup (frame, lgl_template_markup_rect_new (x1, y1, w, h, r));
561
562         for (node = markup_node->xmlChildrenNode; node != NULL;
563              node = node->next) {
564                 if (!xmlNodeIsText (node)) {
565                         if (!lgl_xml_is_node (node, "comment")) {
566                                 g_message ("bad node =  \"%s\"",node->name);
567                         }
568                 }
569         }
570
571 }
572
573 /*--------------------------------------------------------------------------*/
574 /* PRIVATE.  Parse XML Template->Alias Node.                                */
575 /*--------------------------------------------------------------------------*/
576 static void
577 xml_parse_alias_node (xmlNodePtr   alias_node,
578                       lglTemplate *template)
579 {
580         gchar       *name;
581
582         name = lgl_xml_get_prop_string (alias_node, "name", NULL);
583
584         lgl_template_add_alias (template, (gchar *)name);
585
586         g_free (name);
587 }
588
589 /**
590  * lgl_xml_template_write_templates_to_file:
591  * @templates:      List of #lglTemplate structures
592  * @utf8_filename:  Filename of templates file (name encoded as UTF-8)
593  *
594  * Write a list of #lglTemplate structures to a glabels XML template file.
595  *
596  */
597 void
598 lgl_xml_template_write_templates_to_file (GList       *templates,
599                                           const gchar *utf8_filename)
600 {
601         xmlDocPtr    doc;
602         xmlNsPtr     ns;
603         gint         xml_ret;
604         GList       *p;
605         lglTemplate *template;
606         gchar       *filename;
607
608         doc = xmlNewDoc ((xmlChar *)"1.0");
609         doc->xmlRootNode = xmlNewDocNode (doc, NULL, (xmlChar *)"Glabels-templates", NULL);
610
611         ns = xmlNewNs (doc->xmlRootNode, (xmlChar *)LGL_XML_NAME_SPACE, NULL);
612         xmlSetNs (doc->xmlRootNode, ns);
613
614         for (p=templates; p!=NULL; p=p->next) {
615                 template = (lglTemplate *)p->data;
616                 lgl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
617         }
618
619         filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
620         if (!filename)
621                 g_message (_("Utf8 conversion error."));
622         else {
623                 xmlSetDocCompressMode (doc, 0);
624                 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
625                 xmlFreeDoc (doc);
626                 if (xml_ret == -1) {
627
628                         g_message (_("Problem saving xml file."));
629
630                 }
631                 g_free (filename);
632         }
633
634 }
635
636
637 /**
638  * lgl_xml_template_write_template_to_file:
639  * @template:       #lglTemplate structure to be written
640  * @utf8_filename:  Filename of templates file (name encoded as UTF-8)
641  *
642  * Write a single #lglTemplate structures to a glabels XML template file.
643  *
644  */
645 void
646 lgl_xml_template_write_template_to_file (const lglTemplate  *template,
647                                          const gchar        *utf8_filename)
648 {
649         GList     *templates = NULL;
650
651         templates = g_list_append (templates, (gpointer)template);
652
653         lgl_xml_template_write_templates_to_file (templates, utf8_filename);
654
655         g_list_free (templates);
656 }
657
658
659 /**
660  * lgl_xml_template_create_template_node:
661  * @template:       #lglTemplate structure to be written
662  * @root:           parent node to receive new child node
663  * @ns:             a libxml #xmlNsPtr
664  *
665  * Add a single #lglTemplate child node to given #xmlNodePtr.
666  *
667  */
668 void
669 lgl_xml_template_create_template_node (const lglTemplate *template,
670                                        xmlNodePtr         root,
671                                        const xmlNsPtr     ns)
672 {
673         xmlNodePtr          node;
674         GList              *p;
675         lglTemplateFrame   *frame;
676
677         node = xmlNewChild (root, ns, (xmlChar *)"Template", NULL);
678
679         lgl_xml_set_prop_string (node, "name", template->name);
680
681         lgl_xml_set_prop_string (node, "size", template->page_size);
682         if (xmlStrEqual ((xmlChar *)template->page_size, (xmlChar *)"Other")) {
683
684                 lgl_xml_set_prop_length (node, "width", template->page_width);
685                 lgl_xml_set_prop_length (node, "height", template->page_height);
686
687         }
688
689         lgl_xml_set_prop_string (node, "description", template->description);
690
691         for ( p=template->categories; p != NULL; p=p->next ) {
692                 xml_create_meta_node ( p->data, node, ns );
693         }
694         for ( p=template->frames; p != NULL; p=p->next ) {
695                 frame = (lglTemplateFrame *)p->data;
696                 xml_create_label_node (frame, node, ns);
697         }
698
699         for ( p=template->aliases; p != NULL; p=p->next ) {
700                 if (!xmlStrEqual ((xmlChar *)template->name, (xmlChar *)p->data)) {
701                         xml_create_alias_node ( p->data, node, ns );
702                 }
703         }
704
705 }
706
707 /*--------------------------------------------------------------------------*/
708 /* PRIVATE.  Add XML Template->Meta Node.                                   */
709 /*--------------------------------------------------------------------------*/
710 static void
711 xml_create_meta_node (const gchar      *category,
712                       xmlNodePtr        root,
713                       const xmlNsPtr    ns)
714 {
715         xmlNodePtr node;
716
717         node = xmlNewChild (root, ns, (xmlChar *)"Meta", NULL);
718         lgl_xml_set_prop_string (node, "category", category);
719
720 }
721
722 /*--------------------------------------------------------------------------*/
723 /* PRIVATE.  Add XML Template->Label Node.                                  */
724 /*--------------------------------------------------------------------------*/
725 static void
726 xml_create_label_node (const lglTemplateFrame  *frame,
727                        xmlNodePtr               root,
728                        const xmlNsPtr           ns)
729 {
730         xmlNodePtr        node;
731         GList            *p;
732         lglTemplateMarkup *markup;
733         lglTemplateLayout *layout;
734
735         switch (frame->shape) {
736
737         case LGL_TEMPLATE_FRAME_SHAPE_RECT:
738                 node = xmlNewChild(root, ns, (xmlChar *)"Label-rectangle", NULL);
739                 lgl_xml_set_prop_string (node, "id",      frame->all.id);
740                 lgl_xml_set_prop_length (node, "width",   frame->rect.w);
741                 lgl_xml_set_prop_length (node, "height",  frame->rect.h);
742                 lgl_xml_set_prop_length (node, "round",   frame->rect.r);
743                 lgl_xml_set_prop_length (node, "x_waste", frame->rect.x_waste);
744                 lgl_xml_set_prop_length (node, "y_waste", frame->rect.y_waste);
745                 break;
746
747         case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
748                 node = xmlNewChild(root, ns, (xmlChar *)"Label-round", NULL);
749                 lgl_xml_set_prop_string (node, "id",      frame->all.id);
750                 lgl_xml_set_prop_length (node, "radius",  frame->round.r);
751                 lgl_xml_set_prop_length (node, "waste",   frame->round.waste);
752                 break;
753
754         case LGL_TEMPLATE_FRAME_SHAPE_CD:
755                 node = xmlNewChild(root, ns, (xmlChar *)"Label-cd", NULL);
756                 lgl_xml_set_prop_string (node, "id",     frame->all.id);
757                 lgl_xml_set_prop_length (node, "radius", frame->cd.r1);
758                 lgl_xml_set_prop_length (node, "hole",   frame->cd.r2);
759                 if (frame->cd.w != 0.0) {
760                         lgl_xml_set_prop_length (node, "width",  frame->cd.w);
761                 }
762                 if (frame->cd.h != 0.0) {
763                         lgl_xml_set_prop_length (node, "height", frame->cd.h);
764                 }
765                 lgl_xml_set_prop_length (node, "waste",  frame->cd.waste);
766                 break;
767
768         default:
769                 g_message ("Unknown label style");
770                 return;
771                 break;
772
773         }
774
775         for ( p=frame->all.markups; p != NULL; p=p->next ) {
776                 markup = (lglTemplateMarkup *)p->data;
777                 switch (markup->type) {
778                 case LGL_TEMPLATE_MARKUP_MARGIN:
779                         xml_create_markup_margin_node (markup, node, ns);
780                         break;
781                 case LGL_TEMPLATE_MARKUP_LINE:
782                         xml_create_markup_line_node (markup, node, ns);
783                         break;
784                 case LGL_TEMPLATE_MARKUP_CIRCLE:
785                         xml_create_markup_circle_node (markup, node, ns);
786                         break;
787                 case LGL_TEMPLATE_MARKUP_RECT:
788                         xml_create_markup_rect_node (markup, node, ns);
789                         break;
790                 default:
791                         g_message ("Unknown markup type");
792                         break;
793                 }
794         }
795
796         for ( p=frame->all.layouts; p != NULL; p=p->next ) {
797                 layout = (lglTemplateLayout *)p->data;
798                 xml_create_layout_node (layout, node, ns);
799         }
800
801 }
802
803 /*--------------------------------------------------------------------------*/
804 /* PRIVATE.  Add XML Template->Label->Layout Node.                          */
805 /*--------------------------------------------------------------------------*/
806 static void
807 xml_create_layout_node (const lglTemplateLayout *layout,
808                         xmlNodePtr               root,
809                         const xmlNsPtr           ns)
810 {
811         xmlNodePtr  node;
812
813         node = xmlNewChild(root, ns, (xmlChar *)"Layout", NULL);
814         lgl_xml_set_prop_int (node, "nx", layout->nx);
815         lgl_xml_set_prop_int (node, "ny", layout->ny);
816         lgl_xml_set_prop_length (node, "x0", layout->x0);
817         lgl_xml_set_prop_length (node, "y0", layout->y0);
818         lgl_xml_set_prop_length (node, "dx", layout->dx);
819         lgl_xml_set_prop_length (node, "dy", layout->dy);
820
821 }
822
823 /*--------------------------------------------------------------------------*/
824 /* PRIVATE.  Add XML Template->Label->Markup-margin Node.                   */
825 /*--------------------------------------------------------------------------*/
826 static void
827 xml_create_markup_margin_node (const lglTemplateMarkup  *markup,
828                                xmlNodePtr                root,
829                                const xmlNsPtr            ns)
830 {
831         xmlNodePtr  node;
832
833         node = xmlNewChild(root, ns, (xmlChar *)"Markup-margin", NULL);
834
835         lgl_xml_set_prop_length (node, "size", markup->margin.size);
836
837 }
838
839 /*--------------------------------------------------------------------------*/
840 /* PRIVATE.  Add XML Template->Label->Markup-line Node.                     */
841 /*--------------------------------------------------------------------------*/
842 static void
843 xml_create_markup_line_node (const lglTemplateMarkup *markup,
844                              xmlNodePtr               root,
845                              const xmlNsPtr           ns)
846 {
847         xmlNodePtr  node;
848
849         node = xmlNewChild(root, ns, (xmlChar *)"Markup-line", NULL);
850
851         lgl_xml_set_prop_length (node, "x1", markup->line.x1);
852         lgl_xml_set_prop_length (node, "y1", markup->line.y1);
853         lgl_xml_set_prop_length (node, "x2", markup->line.x2);
854         lgl_xml_set_prop_length (node, "y2", markup->line.y2);
855
856 }
857
858 /*--------------------------------------------------------------------------*/
859 /* PRIVATE.  Add XML Template->Label->Markup-circle Node.                   */
860 /*--------------------------------------------------------------------------*/
861 static void
862 xml_create_markup_circle_node (const lglTemplateMarkup *markup,
863                                xmlNodePtr               root,
864                                const xmlNsPtr           ns)
865 {
866         xmlNodePtr  node;
867
868         node = xmlNewChild(root, ns, (xmlChar *)"Markup-circle", NULL);
869
870         lgl_xml_set_prop_length (node, "x0",     markup->circle.x0);
871         lgl_xml_set_prop_length (node, "y0",     markup->circle.y0);
872         lgl_xml_set_prop_length (node, "radius", markup->circle.r);
873
874 }
875
876 /*--------------------------------------------------------------------------*/
877 /* PRIVATE.  Add XML Template->Label->Markup-rect Node.                     */
878 /*--------------------------------------------------------------------------*/
879 static void
880 xml_create_markup_rect_node (const lglTemplateMarkup *markup,
881                              xmlNodePtr               root,
882                              const xmlNsPtr           ns)
883 {
884         xmlNodePtr  node;
885
886         node = xmlNewChild(root, ns, (xmlChar *)"Markup-rect", NULL);
887
888         lgl_xml_set_prop_length (node, "x1", markup->rect.x1);
889         lgl_xml_set_prop_length (node, "y1", markup->rect.y1);
890         lgl_xml_set_prop_length (node, "w",  markup->rect.w);
891         lgl_xml_set_prop_length (node, "h",  markup->rect.h);
892         lgl_xml_set_prop_length (node, "r",  markup->rect.r);
893
894 }
895
896 /*--------------------------------------------------------------------------*/
897 /* PRIVATE.  Add XML Template->Alias Node.                                  */
898 /*--------------------------------------------------------------------------*/
899 static void
900 xml_create_alias_node (const gchar      *name,
901                        xmlNodePtr        root,
902                        const xmlNsPtr    ns)
903 {
904         xmlNodePtr node;
905
906         node = xmlNewChild (root, ns, (xmlChar *)"Alias", NULL);
907         lgl_xml_set_prop_string (node, "name", name);
908
909 }
910