]> git.sur5r.net Git - glabels/blob - glabels2/src/template.c
Initial revision
[glabels] / glabels2 / src / template.c
1 /*
2  *  (GLABELS) Label and Business Card Creation program for GNOME
3  *
4  *  template.c:  template 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 <string.h>
26 #include <libgnomeprint/gnome-print-paper.h>
27
28 #include "template.h"
29
30 #include "debug.h"
31
32 #ifdef PACKAGE_DATA_DIR
33 #define GL_DATA_DIR (PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "glabels")
34 #else
35 #define GL_DATA_DIR gnome_datadir_file("glabels")
36 #endif
37
38 #define FULL_PAGE "Full-page"
39
40 /*===========================================*/
41 /* Private types                             */
42 /*===========================================*/
43
44 /*===========================================*/
45 /* Private globals                           */
46 /*===========================================*/
47
48 static GList *templates = NULL;
49
50 /*===========================================*/
51 /* Local function prototypes                 */
52 /*===========================================*/
53 static glTemplate *template_full_page (const gchar *page_size);
54
55 static GList *read_templates (void);
56
57 static gchar *get_home_data_dir (void);
58 static GList *read_template_files_from_dir (GList * templates,
59                                             const gchar * dirname);
60 static GList *read_templates_from_file (GList * templates,
61                                         gchar * xml_filename);
62
63 static void xml_parse_label (xmlNodePtr label_node, glTemplate * template);
64 static void xml_parse_layout (xmlNodePtr layout_node, glTemplate * template);
65 static void xml_parse_markup (xmlNodePtr markup_node, glTemplate * template);
66 static void xml_parse_alias (xmlNodePtr alias_node, glTemplate * template);
67
68 static void xml_add_label (glTemplate *template, xmlNodePtr root, xmlNsPtr ns);
69 static void xml_add_layout (glTemplate *template, xmlNodePtr root, xmlNsPtr ns);
70 static void xml_add_markup_margin (glTemplate *template, xmlNodePtr root, xmlNsPtr ns);
71 static void xml_add_alias (gchar *name, xmlNodePtr root, xmlNsPtr ns);
72
73 /*****************************************************************************/
74 /* Initialize module.                                                        */
75 /*****************************************************************************/
76 void
77 gl_template_init (void)
78 {
79         GList *page_sizes, *p;
80
81         gl_debug (DEBUG_TEMPLATE, "START");
82
83         templates = read_templates ();
84
85         page_sizes = gl_template_get_page_size_list ();
86         for ( p=page_sizes; p != NULL; p=p->next ) {
87                 templates = g_list_append (templates,
88                                            template_full_page (p->data));
89         }
90         gl_template_free_page_size_list (&page_sizes);
91
92         gl_debug (DEBUG_TEMPLATE, "END");
93 }
94
95 /*****************************************************************************/
96 /* Get a list of valid page size names                                       */
97 /*****************************************************************************/
98 GList *
99 gl_template_get_page_size_list (void)
100 {
101         GList *names = NULL;
102         GList *p, *paper_list;
103         GnomePrintPaper *paper;
104
105         gl_debug (DEBUG_TEMPLATE, "START");
106
107         paper_list = gnome_print_paper_get_list();
108         for ( p=paper_list; p != NULL; p=p->next ) {
109                 paper = (GnomePrintPaper *)p->data;
110                 if ( g_strcasecmp(paper->name, "custom") != 0 ) {
111                         names = g_list_append (names, g_strdup (paper->name));
112                 }
113         }
114
115         gl_debug (DEBUG_TEMPLATE, "END");
116         return names;
117 }
118
119 /*****************************************************************************/
120 /* Free a list of page size names.                                           */
121 /*****************************************************************************/
122 void
123 gl_template_free_page_size_list (GList ** names)
124 {
125         GList *p_name;
126
127         gl_debug (DEBUG_TEMPLATE, "START");
128
129         for (p_name = *names; p_name != NULL; p_name = p_name->next) {
130                 g_free (p_name->data);
131                 p_name->data = NULL;
132         }
133
134         g_list_free (*names);
135         *names = NULL;
136
137         gl_debug (DEBUG_TEMPLATE, "END");
138 }
139
140 /*****************************************************************************/
141 /* Get a list of valid template names for given page size                    */
142 /*****************************************************************************/
143 GList *
144 gl_template_get_name_list (const gchar * page_size)
145 {
146         GList *p_tmplt, *p_name;
147         glTemplate *template;
148         gchar *str;
149         GList *names = NULL;
150
151         gl_debug (DEBUG_TEMPLATE, "START");
152
153         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next) {
154                 template = (glTemplate *) p_tmplt->data;
155                 if (g_strcasecmp (page_size, template->page_size) == 0) {
156                         for (p_name = template->name; p_name != NULL;
157                              p_name = p_name->next) {
158                                 str = g_strdup_printf("%s: %s",
159                                                       (gchar *) p_name->data,
160                                                       template->description);
161                                 names = g_list_insert_sorted (names, str,
162                                                              (GCompareFunc)g_strcasecmp);
163                         }
164                 }
165         }
166
167         gl_debug (DEBUG_TEMPLATE, "templates = %p", templates);
168         gl_debug (DEBUG_TEMPLATE, "names = %p", names);
169
170         gl_debug (DEBUG_TEMPLATE, "END");
171         return names;
172 }
173
174 /*****************************************************************************/
175 /* Free a list of template names.                                            */
176 /*****************************************************************************/
177 void
178 gl_template_free_name_list (GList ** names)
179 {
180         GList *p_name;
181
182         gl_debug (DEBUG_TEMPLATE, "START");
183
184         for (p_name = *names; p_name != NULL; p_name = p_name->next) {
185                 g_free (p_name->data);
186                 p_name->data = NULL;
187         }
188
189         g_list_free (*names);
190         *names = NULL;
191
192         gl_debug (DEBUG_TEMPLATE, "END");
193 }
194
195 /*****************************************************************************/
196 /* Return a template structure from a name.                                  */
197 /*****************************************************************************/
198 glTemplate *
199 gl_template_from_name (const gchar * name)
200 {
201         GList *p_tmplt, *p_name;
202         glTemplate *template;
203         gchar **split_name;
204
205         gl_debug (DEBUG_TEMPLATE, "START");
206
207         if (name == NULL) {
208                 /* If no name, return first template as a default */
209                 return (glTemplate *) templates->data;
210         }
211
212         split_name = g_strsplit (name, ":", 2);
213
214         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next) {
215                 template = (glTemplate *) p_tmplt->data;
216                 for (p_name = template->name; p_name != NULL;
217                      p_name = p_name->next) {
218                         if (g_strcasecmp (p_name->data, split_name[0]) == 0) {
219                                 g_strfreev (split_name);
220                                 gl_debug (DEBUG_TEMPLATE, "END");
221                                 return gl_template_dup (template);
222                         }
223                 }
224         }
225
226         g_strfreev (split_name);
227
228         gl_debug (DEBUG_TEMPLATE, "END");
229         return NULL;
230 }
231
232 /*****************************************************************************/
233 /* Copy a template.                                                          */
234 /*****************************************************************************/
235 glTemplate *gl_template_dup (const glTemplate *orig_template)
236 {
237         glTemplate *template;
238         GList *p;
239
240         gl_debug (DEBUG_TEMPLATE, "START");
241
242         template = g_new0 (glTemplate,1);
243
244         /* Shallow copy first */
245         *template = *orig_template;
246
247         /* Now the deep stuff */
248         template->name = NULL;
249         for ( p=orig_template->name; p != NULL; p=p->next ) {
250                 template->name = g_list_append (template->name,
251                                                 g_strdup (p->data));
252         }
253         template->description = g_strdup (orig_template->description);
254         template->page_size = g_strdup (orig_template->page_size);
255
256         gl_debug (DEBUG_TEMPLATE, "END");
257         return template;
258 }
259
260 /*****************************************************************************/
261 /* Free up a template.                                                       */
262 /*****************************************************************************/
263 void gl_template_free (glTemplate **template)
264 {
265         GList *p;
266
267         gl_debug (DEBUG_TEMPLATE, "START");
268
269         if ( *template != NULL ) {
270
271                 for ( p=(*template)->name; p != NULL; p=p->next ) {
272                         g_free (p->data);
273                         p->data = NULL;
274                 }
275                 g_list_free ((*template)->name);
276                 (*template)->name = NULL;
277
278                 g_free ((*template)->description);
279                 (*template)->description = NULL;
280
281                 g_free ((*template)->page_size);
282                 (*template)->page_size = NULL;
283
284                 g_free (*template);
285                 *template = NULL;
286
287         }
288
289         gl_debug (DEBUG_TEMPLATE, "END");
290 }
291
292 /*--------------------------------------------------------------------------*/
293 /* PRIVATE.  Make a template for a full page of the given page size.        */
294 /*--------------------------------------------------------------------------*/
295 static glTemplate *
296 template_full_page (const gchar *page_size)
297 {
298         const GnomePrintPaper *paper;
299         glTemplate *template;
300
301         paper = gnome_print_paper_get_by_name (page_size);
302         if ( paper == NULL ) {
303                 return NULL;
304         }
305
306         template = g_new0 (glTemplate, 1);
307
308         template->name        = g_list_append (template->name,
309                                                g_strdup_printf("*%s", page_size));
310         template->page_size   = g_strdup(page_size);
311         template->description = g_strdup(FULL_PAGE);
312
313         template->style = GL_TEMPLATE_STYLE_RECT;
314
315         template->nx = 1;
316         template->ny = 1;
317
318         template->label_width  = paper->width;
319         template->label_height = paper->height;
320         template->label_round  = 0.0;
321
322         template->label_margin = 5.0;
323
324         return template;
325 }
326
327 /*--------------------------------------------------------------------------*/
328 /* PRIVATE.  Read templates from various  files.                            */
329 /*--------------------------------------------------------------------------*/
330 static GList *
331 read_templates (void)
332 {
333         gchar *home_data_dir = get_home_data_dir ();
334         GList *templates = NULL;
335
336         gl_debug (DEBUG_TEMPLATE, "START");
337
338         LIBXML_TEST_VERSION;
339
340         templates = read_template_files_from_dir (templates, GL_DATA_DIR);
341         templates = read_template_files_from_dir (templates, home_data_dir);
342
343         g_free (home_data_dir);
344
345         if (templates == NULL) {
346                 g_warning (_("No template files found!"));
347         }
348
349         gl_debug (DEBUG_TEMPLATE, "END");
350         return templates;
351 }
352
353 /*--------------------------------------------------------------------------*/
354 /* PRIVATE.  get '~/.glabels' directory path.                               */
355 /*--------------------------------------------------------------------------*/
356 static gchar *
357 get_home_data_dir (void)
358 {
359         gchar *dir = gnome_util_prepend_user_home (".glabels");
360
361         gl_debug (DEBUG_TEMPLATE, "START");
362
363         /* Try to create ~/.glabels directory.  If it exists, no problem. */
364         mkdir (dir, 0775);
365
366         gl_debug (DEBUG_TEMPLATE, "END");
367         return dir;
368 }
369
370 /*--------------------------------------------------------------------------*/
371 /* PRIVATE.  Read all template files from given directory.  Append to list. */
372 /*--------------------------------------------------------------------------*/
373 static GList *
374 read_template_files_from_dir (GList * templates,
375                               const gchar * dirname)
376 {
377         GDir *dp;
378         const gchar *filename, *extension;
379         gchar *full_filename = NULL;
380         GError *gerror = NULL;
381
382         gl_debug (DEBUG_TEMPLATE, "START");
383
384         if (dirname == NULL)
385                 return templates;
386
387         dp = g_dir_open (dirname, 0, &gerror);
388         if (gerror != NULL) {
389                 g_warning ("cannot open data directory: %s", gerror->message );
390                 gl_debug (DEBUG_TEMPLATE, "END");
391                 return templates;
392         }
393
394         while ((filename = g_dir_read_name (dp)) != NULL) {
395
396                 extension = strrchr (filename, '.');
397
398                 if (extension != NULL) {
399
400                         if (strcasecmp (extension, ".template") == 0) {
401
402                                 full_filename =
403                                     g_build_filename (dirname, filename, NULL);
404                                 templates =
405                                     read_templates_from_file (templates,
406                                                               full_filename);
407                                 g_free (full_filename);
408
409                         }
410
411                 }
412
413         }
414
415         g_dir_close (dp);
416
417         gl_debug (DEBUG_TEMPLATE, "END");
418         return templates;
419 }
420
421 /*--------------------------------------------------------------------------*/
422 /* PRIVATE.  Read templates from template file.                             */
423 /*--------------------------------------------------------------------------*/
424 static GList *
425 read_templates_from_file (GList * templates,
426                           gchar * xml_filename)
427 {
428         xmlDocPtr doc;
429         xmlNodePtr root, node;
430         glTemplate *template;
431
432         gl_debug (DEBUG_TEMPLATE, "START");
433
434         doc = xmlParseFile (xml_filename);
435         if (!doc) {
436                 g_warning ("\"%s\" is not a glabels template file (not XML)",
437                       xml_filename);
438                 return templates;
439         }
440
441         root = xmlDocGetRootElement (doc);
442         if (!root || !root->name) {
443                 g_warning ("\"%s\" is not a glabels template file (no root node)",
444                       xml_filename);
445                 xmlFreeDoc (doc);
446                 return templates;
447         }
448         if (g_strcasecmp (root->name, "glabels-templates") != 0) {
449                 g_warning ("\"%s\" is not a glabels template file (wrong root node)",
450                       xml_filename);
451                 xmlFreeDoc (doc);
452                 return templates;
453         }
454
455         for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
456
457                 if (g_strcasecmp (node->name, "Sheet") == 0) {
458                         template = gl_template_xml_parse_sheet (node);
459                         templates = g_list_append (templates, template);
460                 } else {
461                         if ( !xmlNodeIsText(node) ) {
462                                 if (g_strcasecmp (node->name,"comment") != 0) {
463                                         g_warning ("bad node =  \"%s\"",node->name);
464                                 }
465                         }
466                 }
467         }
468
469         xmlFreeDoc (doc);
470
471         gl_debug (DEBUG_TEMPLATE, "END");
472         return templates;
473 }
474
475 /*****************************************************************************/
476 /* Parse XML template Node.                                                  */
477 /*****************************************************************************/
478 glTemplate *
479 gl_template_xml_parse_sheet (xmlNodePtr sheet_node)
480 {
481         glTemplate *template;
482         xmlNodePtr node;
483
484         gl_debug (DEBUG_TEMPLATE, "START");
485
486         template = g_new0 (glTemplate, 1);
487
488         template->name = g_list_append (template->name,
489                                         xmlGetProp (sheet_node, "name"));
490         template->page_size = xmlGetProp (sheet_node, "size");
491         if ( strcmp (template->page_size,"US-Letter") == 0 ) {
492                 /* Compatibility with old pre-1.0 template files.*/
493                 template->page_size = "US Letter";
494         }
495         template->description = xmlGetProp (sheet_node, "description");
496
497         for (node = sheet_node->xmlChildrenNode; node != NULL;
498              node = node->next) {
499                 if (g_strcasecmp (node->name, "Label") == 0) {
500                         xml_parse_label (node, template);
501                 } else if (g_strcasecmp (node->name, "Alias") == 0) {
502                         xml_parse_alias (node, template);
503                 } else {
504                         if (g_strcasecmp (node->name, "text") != 0) {
505                                 g_warning ("bad node =  \"%s\"", node->name);
506                         }
507                 }
508         }
509
510         gl_debug (DEBUG_TEMPLATE, "END");
511
512         return template;
513 }
514
515 /*--------------------------------------------------------------------------*/
516 /* PRIVATE.  Parse XML Sheet->Label Node.                                   */
517 /*--------------------------------------------------------------------------*/
518 static void
519 xml_parse_label (xmlNodePtr label_node,
520                  glTemplate * template)
521 {
522         xmlNodePtr node;
523         gchar *style;
524
525         gl_debug (DEBUG_TEMPLATE, "START");
526
527         style = xmlGetProp (label_node, "style");
528         if (g_strcasecmp (style, "rectangle") == 0) {
529                 template->style = GL_TEMPLATE_STYLE_RECT;
530         } else if (g_strcasecmp (style, "round") == 0) {
531                 template->style = GL_TEMPLATE_STYLE_ROUND;
532         } else if (g_strcasecmp (style, "cd") == 0) {
533                 template->style = GL_TEMPLATE_STYLE_CD;
534         } else {
535                 g_warning ("Unknown label style in template");
536         }
537
538         if (template->style == GL_TEMPLATE_STYLE_RECT) {
539                 template->label_width =
540                     g_strtod (xmlGetProp (label_node, "width"), NULL);
541                 template->label_height =
542                     g_strtod (xmlGetProp (label_node, "height"), NULL);
543                 template->label_round =
544                     g_strtod (xmlGetProp (label_node, "round"), NULL);
545         } else if (template->style == GL_TEMPLATE_STYLE_ROUND) {
546                 template->label_radius =
547                     g_strtod (xmlGetProp (label_node, "radius"), NULL);
548                 template->label_width = 2.0 * template->label_radius;
549                 template->label_height = 2.0 * template->label_radius;
550         } else if (template->style == GL_TEMPLATE_STYLE_CD) {
551                 template->label_radius =
552                     g_strtod (xmlGetProp (label_node, "radius"), NULL);
553                 template->label_hole =
554                     g_strtod (xmlGetProp (label_node, "hole"), NULL);
555                 template->label_width = 2.0 * template->label_radius;
556                 template->label_height = 2.0 * template->label_radius;
557         }
558
559         for (node = label_node->xmlChildrenNode; node != NULL;
560              node = node->next) {
561                 if (g_strcasecmp (node->name, "Layout") == 0) {
562                         xml_parse_layout (node, template);
563                 } else if (g_strcasecmp (node->name, "Markup") == 0) {
564                         xml_parse_markup (node, template);
565                 } else if (g_strcasecmp (node->name, "text") != 0) {
566                         g_warning ("bad node =  \"%s\"", node->name);
567                 }
568         }
569
570         gl_debug (DEBUG_TEMPLATE, "END");
571 }
572
573 /*--------------------------------------------------------------------------*/
574 /* PRIVATE.  Parse XML Sheet->Label->Layout Node.                           */
575 /*--------------------------------------------------------------------------*/
576 static void
577 xml_parse_layout (xmlNodePtr layout_node,
578                   glTemplate * template)
579 {
580         xmlNodePtr node;
581
582         gl_debug (DEBUG_TEMPLATE, "START");
583
584         sscanf (xmlGetProp (layout_node, "nx"), "%d", &(template->nx));
585         sscanf (xmlGetProp (layout_node, "ny"), "%d", &(template->ny));
586         template->x0 = g_strtod (xmlGetProp (layout_node, "x0"), NULL);
587         template->y0 = g_strtod (xmlGetProp (layout_node, "y0"), NULL);
588         template->dx = g_strtod (xmlGetProp (layout_node, "dx"), NULL);
589         template->dy = g_strtod (xmlGetProp (layout_node, "dy"), NULL);
590
591         for (node = layout_node->xmlChildrenNode; node != NULL;
592              node = node->next) {
593                 if (g_strcasecmp (node->name, "text") != 0) {
594                         g_warning ("bad node =  \"%s\"", node->name);
595                 }
596         }
597
598         gl_debug (DEBUG_TEMPLATE, "END");
599 }
600
601 /*--------------------------------------------------------------------------*/
602 /* PRIVATE.  Parse XML Sheet->Label->Markup Node.                           */
603 /*--------------------------------------------------------------------------*/
604 static void
605 xml_parse_markup (xmlNodePtr markup_node,
606                   glTemplate * template)
607 {
608         gchar *type;
609         xmlNodePtr node;
610
611         gl_debug (DEBUG_TEMPLATE, "START");
612
613         type = xmlGetProp (markup_node, "type");
614         if (g_strcasecmp (type, "margin") == 0) {
615                 template->label_margin =
616                         g_strtod (xmlGetProp (markup_node, "size"), NULL);
617         }
618
619         for (node = markup_node->xmlChildrenNode; node != NULL;
620              node = node->next) {
621                 if (g_strcasecmp (node->name, "text") != 0) {
622                         g_warning ("bad node =  \"%s\"", node->name);
623                 }
624         }
625
626         gl_debug (DEBUG_TEMPLATE, "END");
627 }
628
629 /*--------------------------------------------------------------------------*/
630 /* PRIVATE.  Parse XML Sheet->Alias Node.                                   */
631 /*--------------------------------------------------------------------------*/
632 static void
633 xml_parse_alias (xmlNodePtr alias_node,
634                  glTemplate * template)
635 {
636         gl_debug (DEBUG_TEMPLATE, "START");
637
638         template->name = g_list_append (template->name,
639                                         xmlGetProp (alias_node, "name"));
640
641         gl_debug (DEBUG_TEMPLATE, "END");
642 }
643
644 /****************************************************************************/
645 /* Add XML Template Node                                                    */
646 /****************************************************************************/
647 void
648 gl_template_xml_add_sheet (glTemplate * template,
649                            xmlNodePtr root,
650                            xmlNsPtr ns)
651 {
652         xmlNodePtr node;
653         GList *p;
654
655         gl_debug (DEBUG_TEMPLATE, "START");
656
657         node = xmlNewChild (root, ns, "Sheet", NULL);
658
659         xmlSetProp (node, "name", template->name->data);
660         xmlSetProp (node, "size", template->page_size);
661         xmlSetProp (node, "description", template->description);
662
663         xml_add_label (template, node, ns);
664
665         for ( p=template->name->next; p != NULL; p=p->next ) {
666                 xml_add_alias( p->data, node, ns );
667         }
668
669         gl_debug (DEBUG_TEMPLATE, "END");
670 }
671
672 /*--------------------------------------------------------------------------*/
673 /* PRIVATE.  Add XML Sheet->Label Node.                                     */
674 /*--------------------------------------------------------------------------*/
675 static void
676 xml_add_label (glTemplate *template,
677                xmlNodePtr root,
678                xmlNsPtr ns)
679 {
680         xmlNodePtr node;
681         gchar *string;
682
683         gl_debug (DEBUG_TEMPLATE, "START");
684
685         node = xmlNewChild(root, ns, "Label", NULL);
686
687         xmlSetProp (node, "id", "0");
688
689         switch (template->style) {
690         case GL_TEMPLATE_STYLE_RECT:
691                 xmlSetProp (node, "style", "rectangle");
692                 string = g_strdup_printf ("%g", template->label_width);
693                 xmlSetProp (node, "width", string);
694                 g_free (string);
695                 string = g_strdup_printf ("%g", template->label_height);
696                 xmlSetProp (node, "height", string);
697                 g_free (string);
698                 string = g_strdup_printf ("%g", template->label_round);
699                 xmlSetProp (node, "round", string);
700                 g_free (string);
701                 break;
702         case GL_TEMPLATE_STYLE_ROUND:
703                 xmlSetProp (node, "style", "round");
704                 string = g_strdup_printf ("%g", template->label_radius);
705                 xmlSetProp (node, "radius", string);
706                 g_free (string);
707                 break;
708         case GL_TEMPLATE_STYLE_CD:
709                 xmlSetProp (node, "style", "cd");
710                 string = g_strdup_printf ("%g", template->label_radius);
711                 xmlSetProp (node, "radius", string);
712                 g_free (string);
713                 string = g_strdup_printf ("%g", template->label_hole);
714                 xmlSetProp (node, "hole", string);
715                 g_free (string);
716                 break;
717         default:
718                 g_warning ("Unknown label style");
719                 break;
720         }
721
722         xml_add_markup_margin (template, node, ns);
723         xml_add_layout (template, node, ns);
724
725         gl_debug (DEBUG_TEMPLATE, "END");
726 }
727
728 /*--------------------------------------------------------------------------*/
729 /* PRIVATE.  Add XML Sheet->Label->Layout Node.                             */
730 /*--------------------------------------------------------------------------*/
731 static void
732 xml_add_layout (glTemplate *template,
733                 xmlNodePtr root,
734                 xmlNsPtr ns)
735 {
736         xmlNodePtr node;
737         gchar *string;
738
739         gl_debug (DEBUG_TEMPLATE, "START");
740
741         node = xmlNewChild(root, ns, "Layout", NULL);
742         string = g_strdup_printf ("%d", template->nx);
743         xmlSetProp (node, "nx", string);
744         g_free (string);
745         string = g_strdup_printf ("%d", template->ny);
746         xmlSetProp (node, "ny", string);
747         g_free (string);
748         string = g_strdup_printf ("%g", template->x0);
749         xmlSetProp (node, "x0", string);
750         g_free (string);
751         string = g_strdup_printf ("%g", template->y0);
752         xmlSetProp (node, "y0", string);
753         g_free (string);
754         string = g_strdup_printf ("%g", template->dx);
755         xmlSetProp (node, "dx", string);
756         g_free (string);
757         string = g_strdup_printf ("%g", template->dy);
758         xmlSetProp (node, "dy", string);
759         g_free (string);
760
761         gl_debug (DEBUG_TEMPLATE, "END");
762 }
763
764 /*--------------------------------------------------------------------------*/
765 /* PRIVATE.  Add XML Sheet->Label->Markup Node.                             */
766 /*--------------------------------------------------------------------------*/
767 static void
768 xml_add_markup_margin (glTemplate *template,
769                        xmlNodePtr root,
770                        xmlNsPtr ns)
771 {
772         xmlNodePtr node;
773         gchar *string;
774
775         gl_debug (DEBUG_TEMPLATE, "START");
776
777         node = xmlNewChild(root, ns, "Markup", NULL);
778         xmlSetProp (node, "type", "margin");
779
780         string = g_strdup_printf ("%g", template->label_margin);
781         xmlSetProp (node, "size", string);
782         g_free (string);
783
784         gl_debug (DEBUG_TEMPLATE, "END");
785 }
786
787 /*--------------------------------------------------------------------------*/
788 /* PRIVATE.  Add XML Sheet->Alias Node.                                     */
789 /*--------------------------------------------------------------------------*/
790 static void
791 xml_add_alias (gchar *name,
792                xmlNodePtr root,
793                xmlNsPtr ns)
794 {
795         xmlNodePtr node;
796
797         gl_debug (DEBUG_TEMPLATE, "START");
798
799         node = xmlNewChild (root, ns, "Alias", NULL);
800         xmlSetProp (node, "name", name);
801
802         gl_debug (DEBUG_TEMPLATE, "END");
803 }
804