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