2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * xml-template.c: template xml module
6 * Copyright (C) 2001-2003 Jim Evins <evins@snaught.com>.
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.
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.
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
31 #include "xml-template.h"
35 /*===========================================*/
37 /*===========================================*/
39 /*===========================================*/
41 /*===========================================*/
43 /*===========================================*/
44 /* Local function prototypes */
45 /*===========================================*/
46 static void xml_parse_label_rectangle (xmlNodePtr layout_node,
47 glTemplate *template);
48 static void xml_parse_label_round (xmlNodePtr layout_node,
49 glTemplate *template);
50 static void xml_parse_label_cd (xmlNodePtr layout_node,
51 glTemplate *template);
52 static void xml_parse_layout (xmlNodePtr label_node,
53 glTemplate *template);
54 static void xml_parse_markup_margin (xmlNodePtr markup_node,
55 glTemplate *template);
56 static void xml_parse_markup_line (xmlNodePtr markup_node,
57 glTemplate *template);
58 static void xml_parse_markup_circle (xmlNodePtr markup_node,
59 glTemplate *template);
60 static void xml_parse_alias (xmlNodePtr alias_node,
61 glTemplate *template);
63 static void xml_add_label (const glTemplate *template,
66 static void xml_add_layout (glTemplateLayout *layout,
69 static void xml_add_markup_margin (glTemplateMarkupMargin *margin,
72 static void xml_add_markup_line (glTemplateMarkupLine *line,
75 static void xml_add_markup_circle (glTemplateMarkupCircle *circle,
78 static void xml_add_alias (gchar *name,
83 /*****************************************************************************/
84 /* Read templates from template file. */
85 /*****************************************************************************/
87 gl_xml_template_read_templates_from_file (GList *templates,
91 xmlNodePtr root, node;
94 gl_debug (DEBUG_TEMPLATE, "START");
98 doc = xmlParseFile (xml_filename);
100 g_warning ("\"%s\" is not a glabels template file (not XML)",
105 root = xmlDocGetRootElement (doc);
106 if (!root || !root->name) {
107 g_warning ("\"%s\" is not a glabels template file (no root node)",
112 if (!xmlStrEqual (root->name, "Glabels-templates")) {
113 g_warning ("\"%s\" is not a glabels template file (wrong root node)",
119 for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
121 if (xmlStrEqual (node->name, "Template")) {
122 template = gl_xml_template_parse_template (node);
123 templates = g_list_append (templates, template);
125 if ( !xmlNodeIsText(node) ) {
126 if (!xmlStrEqual (node->name,"comment")) {
127 g_warning ("bad node = \"%s\"",node->name);
135 gl_debug (DEBUG_TEMPLATE, "END");
139 /*****************************************************************************/
140 /* Parse XML template Node. */
141 /*****************************************************************************/
143 gl_xml_template_parse_template (xmlNodePtr template_node)
145 glTemplate *template;
150 gl_debug (DEBUG_TEMPLATE, "START");
152 template = g_new0 (glTemplate, 1);
154 template->name = xmlGetProp (template_node, "name");
155 template->alias = g_list_append (template->alias, g_strdup (template->name));
156 gl_debug (DEBUG_TEMPLATE, "Template = %s", template->name);
158 template->page_size = xmlGetProp (template_node, "size");
159 if (xmlStrEqual (template->page_size, "Other")) {
161 template->page_width = gl_xml_get_prop_length (template_node, "width", 0);
162 template->page_height = gl_xml_get_prop_length (template_node, "height", 0);
165 paper = gl_paper_from_id (template->page_size);
167 /* This should always be an id, but just in case a name
169 g_warning (_("Unknown page size id \"%s\", trying as name"),
170 template->page_size);
171 paper = gl_paper_from_name (template->page_size);
172 g_free (template->page_size);
173 template->page_size = g_strdup (paper->id);
176 template->page_width = paper->width;
177 template->page_height = paper->height;
179 g_warning (_("Unknown page size id or name \"%s\""),
180 template->page_size);
182 gl_paper_free (&paper);
185 description = xmlGetProp (template_node, "_description");
186 if (description != NULL) {
187 template->description = gettext (description);
189 template->description = xmlGetProp (template_node, "description");
192 for (node = template_node->xmlChildrenNode; node != NULL;
194 if (xmlStrEqual (node->name, "Label-rectangle")) {
195 xml_parse_label_rectangle (node, template);
196 } else if (xmlStrEqual (node->name, "Label-round")) {
197 xml_parse_label_round (node, template);
198 } else if (xmlStrEqual (node->name, "Label-cd")) {
199 xml_parse_label_cd (node, template);
200 } else if (xmlStrEqual (node->name, "Alias")) {
201 xml_parse_alias (node, template);
203 if (!xmlNodeIsText (node)) {
204 if (!xmlStrEqual (node->name,"comment")) {
205 g_warning ("bad node = \"%s\"",node->name);
211 gl_debug (DEBUG_TEMPLATE, "END");
216 /*--------------------------------------------------------------------------*/
217 /* PRIVATE. Parse XML Template->Label-rectangle Node. */
218 /*--------------------------------------------------------------------------*/
220 xml_parse_label_rectangle (xmlNodePtr label_node,
221 glTemplate *template)
225 gl_debug (DEBUG_TEMPLATE, "START");
227 template->label.style = GL_TEMPLATE_STYLE_RECT;
229 template->label.rect.w = gl_xml_get_prop_length (label_node, "width", 0);
230 template->label.rect.h = gl_xml_get_prop_length (label_node, "height", 0);
231 template->label.rect.r = gl_xml_get_prop_length (label_node, "round", 0);
233 template->label.rect.waste = gl_xml_get_prop_length (label_node, "waste", 0);
235 for (node = label_node->xmlChildrenNode; node != NULL;
237 if (xmlStrEqual (node->name, "Layout")) {
238 xml_parse_layout (node, template);
239 } else if (xmlStrEqual (node->name, "Markup-margin")) {
240 xml_parse_markup_margin (node, template);
241 } else if (xmlStrEqual (node->name, "Markup-line")) {
242 xml_parse_markup_line (node, template);
243 } else if (xmlStrEqual (node->name, "Markup-circle")) {
244 xml_parse_markup_circle (node, template);
245 } else if (!xmlNodeIsText (node)) {
246 if (!xmlStrEqual (node->name,"comment")) {
247 g_warning ("bad node = \"%s\"",node->name);
252 gl_debug (DEBUG_TEMPLATE, "END");
255 /*--------------------------------------------------------------------------*/
256 /* PRIVATE. Parse XML Template->Label-round Node. */
257 /*--------------------------------------------------------------------------*/
259 xml_parse_label_round (xmlNodePtr label_node,
260 glTemplate *template)
264 gl_debug (DEBUG_TEMPLATE, "START");
266 template->label.style = GL_TEMPLATE_STYLE_ROUND;
268 template->label.round.r = gl_xml_get_prop_length (label_node, "radius", 0);
270 template->label.round.waste = gl_xml_get_prop_length (label_node, "waste", 0);
272 for (node = label_node->xmlChildrenNode; node != NULL;
274 if (xmlStrEqual (node->name, "Layout")) {
275 xml_parse_layout (node, template);
276 } else if (xmlStrEqual (node->name, "Markup-margin")) {
277 xml_parse_markup_margin (node, template);
278 } else if (xmlStrEqual (node->name, "Markup-line")) {
279 xml_parse_markup_line (node, template);
280 } else if (!xmlNodeIsText (node)) {
281 if (!xmlStrEqual (node->name,"comment")) {
282 g_warning ("bad node = \"%s\"",node->name);
287 gl_debug (DEBUG_TEMPLATE, "END");
290 /*--------------------------------------------------------------------------*/
291 /* PRIVATE. Parse XML Template->Label-cd Node. */
292 /*--------------------------------------------------------------------------*/
294 xml_parse_label_cd (xmlNodePtr label_node,
295 glTemplate *template)
299 gl_debug (DEBUG_TEMPLATE, "START");
301 template->label.style = GL_TEMPLATE_STYLE_CD;
303 template->label.cd.r1 = gl_xml_get_prop_length (label_node, "radius", 0);
304 template->label.cd.r2 = gl_xml_get_prop_length (label_node, "hole", 0);
305 template->label.cd.w = gl_xml_get_prop_length (label_node, "width", 0);
306 template->label.cd.h = gl_xml_get_prop_length (label_node, "height", 0);
308 template->label.cd.waste = gl_xml_get_prop_length (label_node, "waste", 0);
310 for (node = label_node->xmlChildrenNode; node != NULL;
312 if (xmlStrEqual (node->name, "Layout")) {
313 xml_parse_layout (node, template);
314 } else if (xmlStrEqual (node->name, "Markup-margin")) {
315 xml_parse_markup_margin (node, template);
316 } else if (xmlStrEqual (node->name, "Markup-line")) {
317 xml_parse_markup_line (node, template);
318 } else if (!xmlNodeIsText (node)) {
319 if (!xmlStrEqual (node->name,"comment")) {
320 g_warning ("bad node = \"%s\"",node->name);
325 gl_debug (DEBUG_TEMPLATE, "END");
328 /*--------------------------------------------------------------------------*/
329 /* PRIVATE. Parse XML Template->Label->Layout Node.` */
330 /*--------------------------------------------------------------------------*/
332 xml_parse_layout (xmlNodePtr layout_node,
333 glTemplate *template)
336 gdouble x0, y0, dx, dy;
339 gl_debug (DEBUG_TEMPLATE, "START");
341 nx = gl_xml_get_prop_int (layout_node, "nx", 1);
342 ny = gl_xml_get_prop_int (layout_node, "ny", 1);
344 x0 = gl_xml_get_prop_length (layout_node, "x0", 0);
345 y0 = gl_xml_get_prop_length (layout_node, "y0", 0);
347 dx = gl_xml_get_prop_length (layout_node, "dx", 0);
348 dy = gl_xml_get_prop_length (layout_node, "dy", 0);
350 for (node = layout_node->xmlChildrenNode; node != NULL;
352 if (!xmlNodeIsText (node)) {
353 if (!xmlStrEqual (node->name,"comment")) {
354 g_warning ("bad node = \"%s\"",node->name);
359 template->label.any.layouts =
360 g_list_append (template->label.any.layouts,
361 gl_template_layout_new (nx, ny, x0, y0, dx, dy));
363 gl_debug (DEBUG_TEMPLATE, "END");
366 /*--------------------------------------------------------------------------*/
367 /* PRIVATE. Parse XML Template->Label->Markup-margin Node. */
368 /*--------------------------------------------------------------------------*/
370 xml_parse_markup_margin (xmlNodePtr markup_node,
371 glTemplate *template)
376 gl_debug (DEBUG_TEMPLATE, "START");
378 size = gl_xml_get_prop_length (markup_node, "size", 0);
380 template->label.any.markups =
381 g_list_append (template->label.any.markups,
382 gl_template_markup_margin_new (size));
384 for (node = markup_node->xmlChildrenNode; node != NULL;
386 if (!xmlNodeIsText (node)) {
387 if (!xmlStrEqual (node->name,"comment")) {
388 g_warning ("bad node = \"%s\"",node->name);
393 gl_debug (DEBUG_TEMPLATE, "END");
396 /*--------------------------------------------------------------------------*/
397 /* PRIVATE. Parse XML Template->Label->Markup-line Node. */
398 /*--------------------------------------------------------------------------*/
400 xml_parse_markup_line (xmlNodePtr markup_node,
401 glTemplate *template)
403 gdouble x1, y1, x2, y2;
406 gl_debug (DEBUG_TEMPLATE, "START");
408 x1 = gl_xml_get_prop_length (markup_node, "x1", 0);
409 y1 = gl_xml_get_prop_length (markup_node, "y1", 0);
410 x2 = gl_xml_get_prop_length (markup_node, "x2", 0);
411 y2 = gl_xml_get_prop_length (markup_node, "y2", 0);
413 template->label.any.markups =
414 g_list_append (template->label.any.markups,
415 gl_template_markup_line_new (x1, y1, x2, y2));
417 for (node = markup_node->xmlChildrenNode; node != NULL;
419 if (!xmlNodeIsText (node)) {
420 if (!xmlStrEqual (node->name,"comment")) {
421 g_warning ("bad node = \"%s\"",node->name);
426 gl_debug (DEBUG_TEMPLATE, "END");
429 /*--------------------------------------------------------------------------*/
430 /* PRIVATE. Parse XML Template->Label->Markup-circle Node. */
431 /*--------------------------------------------------------------------------*/
433 xml_parse_markup_circle (xmlNodePtr markup_node,
434 glTemplate *template)
439 gl_debug (DEBUG_TEMPLATE, "START");
441 x0 = gl_xml_get_prop_length (markup_node, "x0", 0);
442 y0 = gl_xml_get_prop_length (markup_node, "y0", 0);
443 r = gl_xml_get_prop_length (markup_node, "radius", 0);
445 template->label.any.markups =
446 g_list_append (template->label.any.markups,
447 gl_template_markup_circle_new (x0, y0, r));
449 for (node = markup_node->xmlChildrenNode; node != NULL;
451 if (!xmlNodeIsText (node)) {
452 if (!xmlStrEqual (node->name,"comment")) {
453 g_warning ("bad node = \"%s\"",node->name);
458 gl_debug (DEBUG_TEMPLATE, "END");
461 /*--------------------------------------------------------------------------*/
462 /* PRIVATE. Parse XML Template->Alias Node. */
463 /*--------------------------------------------------------------------------*/
465 xml_parse_alias (xmlNodePtr alias_node,
466 glTemplate *template)
468 gl_debug (DEBUG_TEMPLATE, "START");
470 template->alias = g_list_append (template->alias,
471 xmlGetProp (alias_node, "name"));
473 gl_debug (DEBUG_TEMPLATE, "END");
476 /****************************************************************************/
477 /* Write single template to XML file. */
478 /****************************************************************************/
480 gl_xml_template_write_template_to_file (const glTemplate *template,
481 const gchar *utf8_filename)
488 gl_debug (DEBUG_TEMPLATE, "START");
490 doc = xmlNewDoc ("1.0");
491 doc->xmlRootNode = xmlNewDocNode (doc, NULL, "Glabels-templates", NULL);
493 ns = xmlNewNs (doc->xmlRootNode, XML_NAME_SPACE, NULL);
494 xmlSetNs (doc->xmlRootNode, ns);
496 gl_xml_template_add_template (template, doc->xmlRootNode, ns);
498 filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
500 g_warning (_("Utf8 conversion error."));
502 xmlSetDocCompressMode (doc, 0);
503 xml_ret = xmlSaveFormatFile (filename, doc, TRUE);
507 g_warning (_("Problem saving xml file."));
513 gl_debug (DEBUG_TEMPLATE, "END");
516 /****************************************************************************/
517 /* Add XML Template Node */
518 /****************************************************************************/
520 gl_xml_template_add_template (const glTemplate *template,
527 gl_debug (DEBUG_TEMPLATE, "START");
529 node = xmlNewChild (root, ns, "Template", NULL);
531 xmlSetProp (node, "name", template->name);
533 xmlSetProp (node, "size", template->page_size);
534 if (xmlStrEqual (template->page_size, "Other")) {
536 gl_xml_set_prop_length (node, "width", template->page_width);
537 gl_xml_set_prop_length (node, "height", template->page_height);
541 xmlSetProp (node, "description", template->description);
543 xml_add_label (template, node, ns);
545 for ( p=template->alias; p != NULL; p=p->next ) {
546 if (!xmlStrEqual (template->name, p->data)) {
547 xml_add_alias( p->data, node, ns );
551 gl_debug (DEBUG_TEMPLATE, "END");
554 /*--------------------------------------------------------------------------*/
555 /* PRIVATE. Add XML Template->Label Node. */
556 /*--------------------------------------------------------------------------*/
558 xml_add_label (const glTemplate *template,
564 glTemplateMarkup *markup;
565 glTemplateLayout *layout;
567 gl_debug (DEBUG_TEMPLATE, "START");
569 switch (template->label.style) {
571 case GL_TEMPLATE_STYLE_RECT:
572 node = xmlNewChild(root, ns, "Label-rectangle", NULL);
573 xmlSetProp (node, "id", "0");
574 gl_xml_set_prop_length (node, "width", template->label.rect.w);
575 gl_xml_set_prop_length (node, "height", template->label.rect.h);
576 gl_xml_set_prop_length (node, "round", template->label.rect.r);
577 gl_xml_set_prop_length (node, "waste", template->label.rect.waste);
580 case GL_TEMPLATE_STYLE_ROUND:
581 node = xmlNewChild(root, ns, "Label-round", NULL);
582 xmlSetProp (node, "id", "0");
583 gl_xml_set_prop_length (node, "radius", template->label.round.r);
584 gl_xml_set_prop_length (node, "waste", template->label.round.waste);
587 case GL_TEMPLATE_STYLE_CD:
588 node = xmlNewChild(root, ns, "Label-cd", NULL);
589 xmlSetProp (node, "id", "0");
590 gl_xml_set_prop_length (node, "radius", template->label.cd.r1);
591 gl_xml_set_prop_length (node, "hole", template->label.cd.r2);
592 if (template->label.cd.w != 0.0) {
593 gl_xml_set_prop_length (node, "width", template->label.cd.w);
595 if (template->label.cd.h != 0.0) {
596 gl_xml_set_prop_length (node, "height", template->label.cd.h);
598 gl_xml_set_prop_length (node, "waste", template->label.cd.waste);
602 g_warning ("Unknown label style");
608 for ( p=template->label.any.markups; p != NULL; p=p->next ) {
609 markup = (glTemplateMarkup *)p->data;
610 switch (markup->type) {
611 case GL_TEMPLATE_MARKUP_MARGIN:
612 xml_add_markup_margin ((glTemplateMarkupMargin *)markup,
615 case GL_TEMPLATE_MARKUP_LINE:
616 xml_add_markup_line ((glTemplateMarkupLine *)markup,
619 case GL_TEMPLATE_MARKUP_CIRCLE:
620 xml_add_markup_circle ((glTemplateMarkupCircle *)markup,
624 g_warning ("Unknown markup type");
629 for ( p=template->label.any.layouts; p != NULL; p=p->next ) {
630 layout = (glTemplateLayout *)p->data;
631 xml_add_layout (layout, node, ns);
634 gl_debug (DEBUG_TEMPLATE, "END");
637 /*--------------------------------------------------------------------------*/
638 /* PRIVATE. Add XML Template->Label->Layout Node. */
639 /*--------------------------------------------------------------------------*/
641 xml_add_layout (glTemplateLayout *layout,
647 gl_debug (DEBUG_TEMPLATE, "START");
649 node = xmlNewChild(root, ns, "Layout", NULL);
650 gl_xml_set_prop_int (node, "nx", layout->nx);
651 gl_xml_set_prop_int (node, "ny", layout->ny);
652 gl_xml_set_prop_length (node, "x0", layout->x0);
653 gl_xml_set_prop_length (node, "y0", layout->y0);
654 gl_xml_set_prop_length (node, "dx", layout->dx);
655 gl_xml_set_prop_length (node, "dy", layout->dy);
657 gl_debug (DEBUG_TEMPLATE, "END");
660 /*--------------------------------------------------------------------------*/
661 /* PRIVATE. Add XML Template->Label->Markup-margin Node. */
662 /*--------------------------------------------------------------------------*/
664 xml_add_markup_margin (glTemplateMarkupMargin *margin,
670 gl_debug (DEBUG_TEMPLATE, "START");
672 node = xmlNewChild(root, ns, "Markup-margin", NULL);
674 gl_xml_set_prop_length (node, "size", margin->size);
676 gl_debug (DEBUG_TEMPLATE, "END");
679 /*--------------------------------------------------------------------------*/
680 /* PRIVATE. Add XML Template->Label->Markup-line Node. */
681 /*--------------------------------------------------------------------------*/
683 xml_add_markup_line (glTemplateMarkupLine *line,
689 gl_debug (DEBUG_TEMPLATE, "START");
691 node = xmlNewChild(root, ns, "Markup-line", NULL);
693 gl_xml_set_prop_length (node, "x1", line->x1);
694 gl_xml_set_prop_length (node, "y1", line->y1);
695 gl_xml_set_prop_length (node, "x2", line->x2);
696 gl_xml_set_prop_length (node, "y2", line->y2);
698 gl_debug (DEBUG_TEMPLATE, "END");
701 /*--------------------------------------------------------------------------*/
702 /* PRIVATE. Add XML Template->Label->Markup-circle Node. */
703 /*--------------------------------------------------------------------------*/
705 xml_add_markup_circle (glTemplateMarkupCircle *circle,
711 gl_debug (DEBUG_TEMPLATE, "START");
713 node = xmlNewChild(root, ns, "Markup-circle", NULL);
715 gl_xml_set_prop_length (node, "x0", circle->x0);
716 gl_xml_set_prop_length (node, "y0", circle->y0);
717 gl_xml_set_prop_length (node, "radius", circle->r);
719 gl_debug (DEBUG_TEMPLATE, "END");
722 /*--------------------------------------------------------------------------*/
723 /* PRIVATE. Add XML Template->Alias Node. */
724 /*--------------------------------------------------------------------------*/
726 xml_add_alias (gchar *name,
732 gl_debug (DEBUG_TEMPLATE, "START");
734 node = xmlNewChild (root, ns, "Alias", NULL);
735 xmlSetProp (node, "name", name);
737 gl_debug (DEBUG_TEMPLATE, "END");