2 * (LIBGLABELS) Template library for GLABELS
4 * xml-template.c: template xml module
6 * Copyright (C) 2001-2004 Jim Evins <evins@snaught.com>.
8 * This file is part of the LIBGLABELS library.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public
21 * License along with this library; if not, write to the Free
22 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 #include "libglabels-private.h"
33 #include "xml-template.h"
35 /*===========================================*/
37 /*===========================================*/
39 /*===========================================*/
41 /*===========================================*/
43 /*===========================================*/
44 /* Local function prototypes */
45 /*===========================================*/
46 static void xml_parse_label_rectangle_node (xmlNodePtr label_node,
47 glTemplate *template);
48 static void xml_parse_label_round_node (xmlNodePtr label_node,
49 glTemplate *template);
50 static void xml_parse_label_cd_node (xmlNodePtr label_node,
51 glTemplate *template);
52 static void xml_parse_layout_node (xmlNodePtr layout_node,
53 glTemplateLabelType *label_type);
54 static void xml_parse_markup_margin_node (xmlNodePtr markup_node,
55 glTemplateLabelType *label_type);
56 static void xml_parse_markup_line_node (xmlNodePtr markup_node,
57 glTemplateLabelType *label_type);
58 static void xml_parse_markup_circle_node (xmlNodePtr markup_node,
59 glTemplateLabelType *label_type);
60 static void xml_parse_alias_node (xmlNodePtr alias_node,
61 glTemplate *template);
63 static void xml_create_label_node (const glTemplateLabelType *label_type,
66 static void xml_create_layout_node (const glTemplateLayout *layout,
69 static void xml_create_markup_margin_node (const glTemplateMarkup *margin,
72 static void xml_create_markup_line_node (const glTemplateMarkup *line,
75 static void xml_create_markup_circle_node (const glTemplateMarkup *circle,
78 static void xml_create_alias_node (const gchar *name,
83 /*****************************************************************************/
84 /* Read templates from template file. */
85 /*****************************************************************************/
87 gl_xml_template_read_templates_from_file (const gchar *utf8_filename)
90 xmlDocPtr templates_doc;
91 GList *templates = NULL;
95 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
97 g_warning ("Utf8 filename conversion error");
101 templates_doc = xmlParseFile (filename);
102 if (!templates_doc) {
103 g_warning ("\"%s\" is not a glabels template file (not XML)",
108 templates = gl_xml_template_parse_templates_doc (templates_doc);
111 xmlFreeDoc (templates_doc);
116 /*****************************************************************************/
117 /* Read templates from templates xml doc tree. */
118 /*****************************************************************************/
120 gl_xml_template_parse_templates_doc (const xmlDocPtr templates_doc)
123 GList *templates = NULL;
124 xmlNodePtr root, node;
125 glTemplate *template;
129 root = xmlDocGetRootElement (templates_doc);
130 if (!root || !root->name) {
131 g_warning ("\"%s\" is not a glabels template file (no root node)",
132 templates_doc->name);
133 xmlFreeDoc (templates_doc);
136 if (!xmlStrEqual (root->name, "Glabels-templates")) {
137 g_warning ("\"%s\" is not a glabels template file (wrong root node)",
138 templates_doc->name);
139 xmlFreeDoc (templates_doc);
143 for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
145 if (xmlStrEqual (node->name, "Template")) {
146 template = gl_xml_template_parse_template_node (node);
147 templates = g_list_append (templates, template);
149 if ( !xmlNodeIsText(node) ) {
150 if (!xmlStrEqual (node->name,"comment")) {
151 g_warning ("bad node = \"%s\"",node->name);
160 /*****************************************************************************/
161 /* Parse XML template Node. */
162 /*****************************************************************************/
164 gl_xml_template_parse_template_node (const xmlNodePtr template_node)
169 gdouble page_width, page_height;
170 glPaper *paper = NULL;
171 glTemplate *template;
174 name = xmlGetProp (template_node, "name");
176 description = xmlGetProp (template_node, "_description");
177 if (description != NULL) {
178 description = gettext (description);
180 description = xmlGetProp (template_node, "description");
183 page_size = xmlGetProp (template_node, "size");
184 if (gl_paper_is_id_other (page_size)) {
186 page_width = gl_xml_get_prop_length (template_node, "width", 0);
187 page_height = gl_xml_get_prop_length (template_node, "height", 0);
190 paper = gl_paper_from_id (page_size);
192 /* This should always be an id, but just in case a name
194 g_warning (_("Unknown page size id \"%s\", trying as name"),
196 paper = gl_paper_from_name (page_size);
198 page_size = g_strdup (paper->id);
201 page_width = paper->width;
202 page_height = paper->height;
204 g_warning (_("Unknown page size id or name \"%s\""),
207 gl_paper_free (paper);
211 template = gl_template_new (name,
214 page_width, page_height);
216 for (node = template_node->xmlChildrenNode; node != NULL;
218 if (xmlStrEqual (node->name, "Label-rectangle")) {
219 xml_parse_label_rectangle_node (node, template);
220 } else if (xmlStrEqual (node->name, "Label-round")) {
221 xml_parse_label_round_node (node, template);
222 } else if (xmlStrEqual (node->name, "Label-cd")) {
223 xml_parse_label_cd_node (node, template);
224 } else if (xmlStrEqual (node->name, "Alias")) {
225 xml_parse_alias_node (node, template);
227 if (!xmlNodeIsText (node)) {
228 if (!xmlStrEqual (node->name,"comment")) {
229 g_warning ("bad node = \"%s\"",node->name);
238 /*--------------------------------------------------------------------------*/
239 /* PRIVATE. Parse XML Template->Label-rectangle Node. */
240 /*--------------------------------------------------------------------------*/
242 xml_parse_label_rectangle_node (xmlNodePtr label_node,
243 glTemplate *template)
248 glTemplateLabelType *label_type;
251 id = xmlGetProp (label_node, "id");
252 waste = gl_xml_get_prop_length (label_node, "waste", 0);
253 w = gl_xml_get_prop_length (label_node, "width", 0);
254 h = gl_xml_get_prop_length (label_node, "height", 0);
255 r = gl_xml_get_prop_length (label_node, "round", 0);
257 label_type = gl_template_rect_label_type_new (id, w, h, r, waste);
258 gl_template_add_label_type (template, label_type);
260 for (node = label_node->xmlChildrenNode; node != NULL;
262 if (xmlStrEqual (node->name, "Layout")) {
263 xml_parse_layout_node (node, label_type);
264 } else if (xmlStrEqual (node->name, "Markup-margin")) {
265 xml_parse_markup_margin_node (node, label_type);
266 } else if (xmlStrEqual (node->name, "Markup-line")) {
267 xml_parse_markup_line_node (node, label_type);
268 } else if (xmlStrEqual (node->name, "Markup-circle")) {
269 xml_parse_markup_circle_node (node, label_type);
270 } else if (!xmlNodeIsText (node)) {
271 if (!xmlStrEqual (node->name,"comment")) {
272 g_warning ("bad node = \"%s\"",node->name);
279 /*--------------------------------------------------------------------------*/
280 /* PRIVATE. Parse XML Template->Label-round Node. */
281 /*--------------------------------------------------------------------------*/
283 xml_parse_label_round_node (xmlNodePtr label_node,
284 glTemplate *template)
289 glTemplateLabelType *label_type;
292 id = xmlGetProp (label_node, "id");
293 waste = gl_xml_get_prop_length (label_node, "waste", 0);
294 r = gl_xml_get_prop_length (label_node, "radius", 0);
296 label_type = gl_template_round_label_type_new (id, r, waste);
297 gl_template_add_label_type (template, label_type);
299 for (node = label_node->xmlChildrenNode; node != NULL;
301 if (xmlStrEqual (node->name, "Layout")) {
302 xml_parse_layout_node (node, label_type);
303 } else if (xmlStrEqual (node->name, "Markup-margin")) {
304 xml_parse_markup_margin_node (node, label_type);
305 } else if (xmlStrEqual (node->name, "Markup-line")) {
306 xml_parse_markup_line_node (node, label_type);
307 } else if (xmlStrEqual (node->name, "Markup-circle")) {
308 xml_parse_markup_circle_node (node, label_type);
309 } else if (!xmlNodeIsText (node)) {
310 if (!xmlStrEqual (node->name,"comment")) {
311 g_warning ("bad node = \"%s\"",node->name);
318 /*--------------------------------------------------------------------------*/
319 /* PRIVATE. Parse XML Template->Label-cd Node. */
320 /*--------------------------------------------------------------------------*/
322 xml_parse_label_cd_node (xmlNodePtr label_node,
323 glTemplate *template)
327 gdouble r1, r2, w, h;
328 glTemplateLabelType *label_type;
331 id = xmlGetProp (label_node, "id");
332 waste = gl_xml_get_prop_length (label_node, "waste", 0);
333 r1 = gl_xml_get_prop_length (label_node, "radius", 0);
334 r2 = gl_xml_get_prop_length (label_node, "hole", 0);
335 w = gl_xml_get_prop_length (label_node, "width", 0);
336 h = gl_xml_get_prop_length (label_node, "height", 0);
338 label_type = gl_template_cd_label_type_new (id, r1, r2, w, h, waste);
339 gl_template_add_label_type (template, label_type);
341 for (node = label_node->xmlChildrenNode; node != NULL;
343 if (xmlStrEqual (node->name, "Layout")) {
344 xml_parse_layout_node (node, label_type);
345 } else if (xmlStrEqual (node->name, "Markup-margin")) {
346 xml_parse_markup_margin_node (node, label_type);
347 } else if (xmlStrEqual (node->name, "Markup-line")) {
348 xml_parse_markup_line_node (node, label_type);
349 } else if (xmlStrEqual (node->name, "Markup-circle")) {
350 xml_parse_markup_circle_node (node, label_type);
351 } else if (!xmlNodeIsText (node)) {
352 if (!xmlStrEqual (node->name,"comment")) {
353 g_warning ("bad node = \"%s\"",node->name);
360 /*--------------------------------------------------------------------------*/
361 /* PRIVATE. Parse XML Template->Label->Layout Node. */
362 /*--------------------------------------------------------------------------*/
364 xml_parse_layout_node (xmlNodePtr layout_node,
365 glTemplateLabelType *label_type)
368 gdouble x0, y0, dx, dy;
371 nx = gl_xml_get_prop_int (layout_node, "nx", 1);
372 ny = gl_xml_get_prop_int (layout_node, "ny", 1);
374 x0 = gl_xml_get_prop_length (layout_node, "x0", 0);
375 y0 = gl_xml_get_prop_length (layout_node, "y0", 0);
377 dx = gl_xml_get_prop_length (layout_node, "dx", 0);
378 dy = gl_xml_get_prop_length (layout_node, "dy", 0);
380 gl_template_add_layout (label_type,
381 gl_template_layout_new (nx, ny, x0, y0, dx, dy));
383 for (node = layout_node->xmlChildrenNode; node != NULL;
385 if (!xmlNodeIsText (node)) {
386 if (!xmlStrEqual (node->name,"comment")) {
387 g_warning ("bad node = \"%s\"",node->name);
394 /*--------------------------------------------------------------------------*/
395 /* PRIVATE. Parse XML Template->Label->Markup-margin Node. */
396 /*--------------------------------------------------------------------------*/
398 xml_parse_markup_margin_node (xmlNodePtr markup_node,
399 glTemplateLabelType *label_type)
404 size = gl_xml_get_prop_length (markup_node, "size", 0);
406 gl_template_add_markup (label_type,
407 gl_template_markup_margin_new (size));
409 for (node = markup_node->xmlChildrenNode; node != NULL;
411 if (!xmlNodeIsText (node)) {
412 if (!xmlStrEqual (node->name,"comment")) {
413 g_warning ("bad node = \"%s\"",node->name);
420 /*--------------------------------------------------------------------------*/
421 /* PRIVATE. Parse XML Template->Label->Markup-line Node. */
422 /*--------------------------------------------------------------------------*/
424 xml_parse_markup_line_node (xmlNodePtr markup_node,
425 glTemplateLabelType *label_type)
427 gdouble x1, y1, x2, y2;
430 x1 = gl_xml_get_prop_length (markup_node, "x1", 0);
431 y1 = gl_xml_get_prop_length (markup_node, "y1", 0);
432 x2 = gl_xml_get_prop_length (markup_node, "x2", 0);
433 y2 = gl_xml_get_prop_length (markup_node, "y2", 0);
435 gl_template_add_markup (label_type,
436 gl_template_markup_line_new (x1, y1, x2, y2));
438 for (node = markup_node->xmlChildrenNode; node != NULL;
440 if (!xmlNodeIsText (node)) {
441 if (!xmlStrEqual (node->name,"comment")) {
442 g_warning ("bad node = \"%s\"",node->name);
449 /*--------------------------------------------------------------------------*/
450 /* PRIVATE. Parse XML Template->Label->Markup-circle Node. */
451 /*--------------------------------------------------------------------------*/
453 xml_parse_markup_circle_node (xmlNodePtr markup_node,
454 glTemplateLabelType *label_type)
459 x0 = gl_xml_get_prop_length (markup_node, "x0", 0);
460 y0 = gl_xml_get_prop_length (markup_node, "y0", 0);
461 r = gl_xml_get_prop_length (markup_node, "radius", 0);
463 gl_template_add_markup (label_type,
464 gl_template_markup_circle_new (x0, y0, r));
466 for (node = markup_node->xmlChildrenNode; node != NULL;
468 if (!xmlNodeIsText (node)) {
469 if (!xmlStrEqual (node->name,"comment")) {
470 g_warning ("bad node = \"%s\"",node->name);
477 /*--------------------------------------------------------------------------*/
478 /* PRIVATE. Parse XML Template->Alias Node. */
479 /*--------------------------------------------------------------------------*/
481 xml_parse_alias_node (xmlNodePtr alias_node,
482 glTemplate *template)
486 name = xmlGetProp (alias_node, "name");
488 gl_template_add_alias (template, name);
493 /****************************************************************************/
494 /* Write a list of templates to XML file. */
495 /****************************************************************************/
497 gl_xml_template_write_templates_to_file (GList *templates,
498 const gchar *utf8_filename)
504 glTemplate *template;
507 doc = xmlNewDoc ("1.0");
508 doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-templates", NULL);
510 ns = xmlNewNs (doc->xmlRootNode, GL_XML_NAME_SPACE, NULL);
511 xmlSetNs (doc->xmlRootNode, ns);
513 for (p=templates; p!=NULL; p=p->next) {
514 template = (glTemplate *)p->data;
515 gl_xml_template_create_template_node (template, doc->xmlRootNode, ns);
518 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
520 g_warning (_("Utf8 conversion error."));
522 xmlSetDocCompressMode (doc, 0);
523 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
527 g_warning (_("Problem saving xml file."));
535 /****************************************************************************/
536 /* Write single template to XML file. */
537 /****************************************************************************/
539 gl_xml_template_write_template_to_file (const glTemplate *template,
540 const gchar *utf8_filename)
542 GList *templates = NULL;
544 templates = g_list_append (templates, (gpointer)template);
546 gl_xml_template_write_templates_to_file (templates, utf8_filename);
548 g_list_free (templates);
551 /****************************************************************************/
552 /* Add XML Template Node */
553 /****************************************************************************/
555 gl_xml_template_create_template_node (const glTemplate *template,
561 glTemplateLabelType *label_type;
563 node = xmlNewChild (root, ns, "Template", NULL);
565 xmlSetProp (node, "name", template->name);
567 xmlSetProp (node, "size", template->page_size);
568 if (xmlStrEqual (template->page_size, "Other")) {
570 gl_xml_set_prop_length (node, "width", template->page_width);
571 gl_xml_set_prop_length (node, "height", template->page_height);
575 xmlSetProp (node, "description", template->description);
577 for ( p=template->label_types; p != NULL; p=p->next ) {
578 label_type = (glTemplateLabelType *)p->data;
579 xml_create_label_node (label_type, node, ns);
582 for ( p=template->aliases; p != NULL; p=p->next ) {
583 if (!xmlStrEqual (template->name, p->data)) {
584 xml_create_alias_node ( p->data, node, ns );
590 /*--------------------------------------------------------------------------*/
591 /* PRIVATE. Add XML Template->Label Node. */
592 /*--------------------------------------------------------------------------*/
594 xml_create_label_node (const glTemplateLabelType *label_type,
600 glTemplateMarkup *markup;
601 glTemplateLayout *layout;
603 switch (label_type->shape) {
605 case GL_TEMPLATE_SHAPE_RECT:
606 node = xmlNewChild(root, ns, "Label-rectangle", NULL);
607 xmlSetProp (node, "id", label_type->id);
608 gl_xml_set_prop_length (node, "width", label_type->size.rect.w);
609 gl_xml_set_prop_length (node, "height", label_type->size.rect.h);
610 gl_xml_set_prop_length (node, "round", label_type->size.rect.r);
611 gl_xml_set_prop_length (node, "waste", label_type->waste);
614 case GL_TEMPLATE_SHAPE_ROUND:
615 node = xmlNewChild(root, ns, "Label-round", NULL);
616 xmlSetProp (node, "id", label_type->id);
617 gl_xml_set_prop_length (node, "radius", label_type->size.round.r);
618 gl_xml_set_prop_length (node, "waste", label_type->waste);
621 case GL_TEMPLATE_SHAPE_CD:
622 node = xmlNewChild(root, ns, "Label-cd", NULL);
623 xmlSetProp (node, "id", label_type->id);
624 gl_xml_set_prop_length (node, "radius", label_type->size.cd.r1);
625 gl_xml_set_prop_length (node, "hole", label_type->size.cd.r2);
626 if (label_type->size.cd.w != 0.0) {
627 gl_xml_set_prop_length (node, "width", label_type->size.cd.w);
629 if (label_type->size.cd.h != 0.0) {
630 gl_xml_set_prop_length (node, "height", label_type->size.cd.h);
632 gl_xml_set_prop_length (node, "waste", label_type->waste);
636 g_warning ("Unknown label style");
642 for ( p=label_type->layouts; p != NULL; p=p->next ) {
643 layout = (glTemplateLayout *)p->data;
644 xml_create_layout_node (layout, node, ns);
647 for ( p=label_type->markups; p != NULL; p=p->next ) {
648 markup = (glTemplateMarkup *)p->data;
649 switch (markup->type) {
650 case GL_TEMPLATE_MARKUP_MARGIN:
651 xml_create_markup_margin_node (markup, node, ns);
653 case GL_TEMPLATE_MARKUP_LINE:
654 xml_create_markup_line_node (markup, node, ns);
656 case GL_TEMPLATE_MARKUP_CIRCLE:
657 xml_create_markup_circle_node (markup, node, ns);
660 g_warning ("Unknown markup type");
667 /*--------------------------------------------------------------------------*/
668 /* PRIVATE. Add XML Template->Label->Layout Node. */
669 /*--------------------------------------------------------------------------*/
671 xml_create_layout_node (const glTemplateLayout *layout,
677 node = xmlNewChild(root, ns, "Layout", NULL);
678 gl_xml_set_prop_int (node, "nx", layout->nx);
679 gl_xml_set_prop_int (node, "ny", layout->ny);
680 gl_xml_set_prop_length (node, "x0", layout->x0);
681 gl_xml_set_prop_length (node, "y0", layout->y0);
682 gl_xml_set_prop_length (node, "dx", layout->dx);
683 gl_xml_set_prop_length (node, "dy", layout->dy);
687 /*--------------------------------------------------------------------------*/
688 /* PRIVATE. Add XML Template->Label->Markup-margin Node. */
689 /*--------------------------------------------------------------------------*/
691 xml_create_markup_margin_node (const glTemplateMarkup *markup,
697 node = xmlNewChild(root, ns, "Markup-margin", NULL);
699 gl_xml_set_prop_length (node, "size", markup->data.margin.size);
703 /*--------------------------------------------------------------------------*/
704 /* PRIVATE. Add XML Template->Label->Markup-line Node. */
705 /*--------------------------------------------------------------------------*/
707 xml_create_markup_line_node (const glTemplateMarkup *markup,
713 node = xmlNewChild(root, ns, "Markup-line", NULL);
715 gl_xml_set_prop_length (node, "x1", markup->data.line.x1);
716 gl_xml_set_prop_length (node, "y1", markup->data.line.y1);
717 gl_xml_set_prop_length (node, "x2", markup->data.line.x2);
718 gl_xml_set_prop_length (node, "y2", markup->data.line.y2);
722 /*--------------------------------------------------------------------------*/
723 /* PRIVATE. Add XML Template->Label->Markup-circle Node. */
724 /*--------------------------------------------------------------------------*/
726 xml_create_markup_circle_node (const glTemplateMarkup *markup,
732 node = xmlNewChild(root, ns, "Markup-circle", NULL);
734 gl_xml_set_prop_length (node, "x0", markup->data.circle.x0);
735 gl_xml_set_prop_length (node, "y0", markup->data.circle.y0);
736 gl_xml_set_prop_length (node, "radius", markup->data.circle.r);
740 /*--------------------------------------------------------------------------*/
741 /* PRIVATE. Add XML Template->Alias Node. */
742 /*--------------------------------------------------------------------------*/
744 xml_create_alias_node (const gchar *name,
750 node = xmlNewChild (root, ns, "Alias", NULL);
751 xmlSetProp (node, "name", name);