2 * (GLABELS) Label and Business Card Creation program for GNOME
4 * template.c: template module
6 * Copyright (C) 2001-2002 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
26 #include <sys/types.h>
36 #ifdef PACKAGE_DATA_DIR
37 #define GL_DATA_DIR (PACKAGE_DATA_DIR G_DIR_SEPARATOR_S "glabels")
39 #define GL_DATA_DIR gnome_datadir_file("glabels")
42 /*===========================================*/
44 /*===========================================*/
46 /*===========================================*/
48 /*===========================================*/
50 static GList *templates = NULL;
52 /*===========================================*/
53 /* Local function prototypes */
54 /*===========================================*/
55 static GList *read_templates (void);
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);
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_alias (xmlNodePtr alias_node, glTemplate * template);
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_alias (gchar *name, xmlNodePtr root, xmlNsPtr ns);
71 /*****************************************************************************/
72 /* Initialize module. */
73 /*****************************************************************************/
75 gl_template_init (void)
77 templates = read_templates ();
80 /*****************************************************************************/
81 /* Get a list of valid template names for given page size */
82 /*****************************************************************************/
84 gl_template_get_name_list (const gchar * page_size)
86 GList *p_tmplt, *p_name;
91 for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next) {
92 template = (glTemplate *) p_tmplt->data;
93 if (g_strcasecmp (page_size, template->page_size) == 0) {
94 for (p_name = template->name; p_name != NULL;
95 p_name = p_name->next) {
96 str = g_strdup_printf("%s: %s",
97 (gchar *) p_name->data,
98 template->description);
99 names = g_list_insert_sorted (names, str,
100 (GCompareFunc)g_strcasecmp);
108 /*****************************************************************************/
109 /* Free a list of template names. */
110 /*****************************************************************************/
112 gl_template_free_name_list (GList ** names)
116 for (p_name = *names; p_name != NULL; p_name = p_name->next) {
117 g_free (p_name->data);
121 g_list_free (*names);
125 /*****************************************************************************/
126 /* Return a template structure from a name. */
127 /*****************************************************************************/
129 gl_template_from_name (const gchar * name)
131 GList *p_tmplt, *p_name;
132 glTemplate *template;
136 /* If no name, return first template as a default */
137 return (glTemplate *) templates->data;
140 split_name = g_strsplit (name, ":", 2);
142 for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next) {
143 template = (glTemplate *) p_tmplt->data;
144 for (p_name = template->name; p_name != NULL;
145 p_name = p_name->next) {
146 if (g_strcasecmp (p_name->data, split_name[0]) == 0) {
147 g_strfreev (split_name);
148 return gl_template_copy(template);
153 g_strfreev (split_name);
158 /*****************************************************************************/
159 /* Copy a template. */
160 /*****************************************************************************/
161 glTemplate *gl_template_copy (const glTemplate *orig_template)
163 glTemplate *template;
166 template = g_new0 (glTemplate,1);
168 /* Shallow copy first */
169 *template = *orig_template;
171 /* Now the deep stuff */
172 template->name = NULL;
173 for ( p=orig_template->name; p != NULL; p=p->next ) {
174 template->name = g_list_append (template->name,
177 template->description = g_strdup (orig_template->description);
178 template->page_size = g_strdup (orig_template->page_size);
183 /*****************************************************************************/
184 /* Free up a template. */
185 /*****************************************************************************/
186 void gl_template_free (glTemplate **template)
190 for ( p=(*template)->name; p != NULL; p=p->next ) {
194 g_list_free ((*template)->name);
195 (*template)->name = NULL;
197 g_free ((*template)->description);
198 (*template)->description = NULL;
200 g_free ((*template)->page_size);
201 (*template)->page_size = NULL;
207 /*--------------------------------------------------------------------------*/
208 /* PRIVATE. Read templates from various files. */
209 /*--------------------------------------------------------------------------*/
211 read_templates (void)
213 gchar *home_data_dir = get_home_data_dir ();
214 GList *templates = NULL;
218 templates = read_template_files_from_dir (templates, GL_DATA_DIR);
219 templates = read_template_files_from_dir (templates, home_data_dir);
221 g_free (home_data_dir);
223 if (templates == NULL) {
224 WARN (_("No template files found!"));
230 /*--------------------------------------------------------------------------*/
231 /* PRIVATE. get '~/.glabels' directory path. */
232 /*--------------------------------------------------------------------------*/
234 get_home_data_dir (void)
236 gchar *dir = gnome_util_prepend_user_home (".glabels");
238 /* Try to create ~/.glabels directory. If it exists, no problem. */
244 /*--------------------------------------------------------------------------*/
245 /* PRIVATE. Read all template files from given directory. Append to list. */
246 /*--------------------------------------------------------------------------*/
248 read_template_files_from_dir (GList * templates,
249 const gchar * dirname)
252 struct dirent *d_entry;
253 gchar *filename, *extension;
254 gchar *full_filename = NULL;
259 dp = opendir (dirname);
263 while ((d_entry = readdir (dp)) != NULL) {
265 filename = d_entry->d_name;
266 extension = strrchr (filename, '.');
268 if (extension != NULL) {
270 if (strcasecmp (extension, ".template") == 0) {
273 g_concat_dir_and_file (dirname, filename);
275 read_templates_from_file (templates,
277 g_free (full_filename);
290 /*--------------------------------------------------------------------------*/
291 /* PRIVATE. Read templates from template file. */
292 /*--------------------------------------------------------------------------*/
294 read_templates_from_file (GList * templates,
295 gchar * xml_filename)
298 xmlNodePtr root, node;
299 glTemplate *template;
301 doc = xmlParseFile (xml_filename);
303 WARN ("\"%s\" is not a glabels template file (not XML)",
308 root = xmlDocGetRootElement (doc);
309 if (!root || !root->name) {
310 WARN ("\"%s\" is not a glabels template file (no root node)",
315 if (g_strcasecmp (root->name, "glabels-templates") != 0) {
316 WARN ("\"%s\" is not a glabels template file (wrong root node)",
322 for (node = root->xmlChildrenNode; node != NULL; node = node->next) {
324 if (g_strcasecmp (node->name, "Sheet") == 0) {
325 template = g_new0 (glTemplate, 1);
326 gl_template_xml_parse_sheet (template, node);
327 templates = g_list_append (templates, template);
329 if (g_strcasecmp (node->name, "text") != 0) {
330 WARN ("bad node = \"%s\"", node->name);
340 /*****************************************************************************/
341 /* Parse XML template Node. */
342 /*****************************************************************************/
344 gl_template_xml_parse_sheet (glTemplate * template,
345 xmlNodePtr sheet_node)
349 template->name = g_list_append (template->name,
350 xmlGetProp (sheet_node, "name"));
351 template->page_size = xmlGetProp (sheet_node, "size");
352 template->description = xmlGetProp (sheet_node, "description");
354 for (node = sheet_node->xmlChildrenNode; node != NULL;
356 if (g_strcasecmp (node->name, "Label") == 0) {
357 xml_parse_label (node, template);
358 } else if (g_strcasecmp (node->name, "Alias") == 0) {
359 xml_parse_alias (node, template);
361 if (g_strcasecmp (node->name, "text") != 0) {
362 WARN ("bad node = \"%s\"", node->name);
369 /*--------------------------------------------------------------------------*/
370 /* PRIVATE. Parse XML Sheet->Label Node. */
371 /*--------------------------------------------------------------------------*/
373 xml_parse_label (xmlNodePtr label_node,
374 glTemplate * template)
379 style = xmlGetProp (label_node, "style");
380 if (g_strcasecmp (style, "rectangle") == 0) {
381 template->style = GL_TEMPLATE_STYLE_RECT;
382 } else if (g_strcasecmp (style, "round") == 0) {
383 template->style = GL_TEMPLATE_STYLE_ROUND;
384 } else if (g_strcasecmp (style, "cd") == 0) {
385 template->style = GL_TEMPLATE_STYLE_CD;
387 WARN ("Unknown label style in template");
390 if (template->style == GL_TEMPLATE_STYLE_RECT) {
391 template->label_width =
392 g_strtod (xmlGetProp (label_node, "width"), NULL);
393 template->label_height =
394 g_strtod (xmlGetProp (label_node, "height"), NULL);
395 template->label_round =
396 g_strtod (xmlGetProp (label_node, "round"), NULL);
397 } else if (template->style == GL_TEMPLATE_STYLE_ROUND) {
398 template->label_radius =
399 g_strtod (xmlGetProp (label_node, "radius"), NULL);
400 template->label_width = 2.0 * template->label_radius;
401 template->label_height = 2.0 * template->label_radius;
402 } else if (template->style == GL_TEMPLATE_STYLE_CD) {
403 template->label_radius =
404 g_strtod (xmlGetProp (label_node, "radius"), NULL);
405 template->label_hole =
406 g_strtod (xmlGetProp (label_node, "hole"), NULL);
407 template->label_width = 2.0 * template->label_radius;
408 template->label_height = 2.0 * template->label_radius;
411 template->label_margin =
412 g_strtod (xmlGetProp (label_node, "margin"), NULL);
414 for (node = label_node->xmlChildrenNode; node != NULL;
416 if (g_strcasecmp (node->name, "Layout") == 0) {
417 xml_parse_layout (node, template);
419 if (g_strcasecmp (node->name, "text") != 0) {
420 WARN ("bad node = \"%s\"", node->name);
427 /*--------------------------------------------------------------------------*/
428 /* PRIVATE. Parse XML Sheet->Label->Layout Node. */
429 /*--------------------------------------------------------------------------*/
431 xml_parse_layout (xmlNodePtr layout_node,
432 glTemplate * template)
436 sscanf (xmlGetProp (layout_node, "nx"), "%d", &(template->nx));
437 sscanf (xmlGetProp (layout_node, "ny"), "%d", &(template->ny));
438 template->x0 = g_strtod (xmlGetProp (layout_node, "x0"), NULL);
439 template->y0 = g_strtod (xmlGetProp (layout_node, "y0"), NULL);
440 template->dx = g_strtod (xmlGetProp (layout_node, "dx"), NULL);
441 template->dy = g_strtod (xmlGetProp (layout_node, "dy"), NULL);
443 for (node = layout_node->xmlChildrenNode; node != NULL;
445 if (g_strcasecmp (node->name, "text") != 0) {
446 WARN ("bad node = \"%s\"", node->name);
452 /*--------------------------------------------------------------------------*/
453 /* PRIVATE. Parse XML Sheet->Alias Node. */
454 /*--------------------------------------------------------------------------*/
456 xml_parse_alias (xmlNodePtr alias_node,
457 glTemplate * template)
459 template->name = g_list_append (template->name,
460 xmlGetProp (alias_node, "name"));
463 /****************************************************************************/
464 /* Add XML Template Node */
465 /****************************************************************************/
467 gl_template_xml_add_sheet (glTemplate * template,
474 node = xmlNewChild (root, ns, "Sheet", NULL);
476 xmlSetProp (node, "name", template->name->data);
477 xmlSetProp (node, "size", template->page_size);
478 xmlSetProp (node, "description", template->description);
480 xml_add_label (template, node, ns);
482 for ( p=template->name->next; p != NULL; p=p->next ) {
483 xml_add_alias( p->data, node, ns );
487 /*--------------------------------------------------------------------------*/
488 /* PRIVATE. Add XML Sheet->Label Node. */
489 /*--------------------------------------------------------------------------*/
491 xml_add_label (glTemplate *template,
498 node = xmlNewChild(root, ns, "Label", NULL);
499 string = g_strdup_printf ("%g", template->label_margin);
500 xmlSetProp (node, "margin", string);
502 switch (template->style) {
503 case GL_TEMPLATE_STYLE_RECT:
504 xmlSetProp (node, "style", "rectangle");
505 string = g_strdup_printf ("%g", template->label_width);
506 xmlSetProp (node, "width", string);
508 string = g_strdup_printf ("%g", template->label_height);
509 xmlSetProp (node, "height", string);
511 string = g_strdup_printf ("%g", template->label_round);
512 xmlSetProp (node, "round", string);
515 case GL_TEMPLATE_STYLE_ROUND:
516 xmlSetProp (node, "style", "round");
517 string = g_strdup_printf ("%g", template->label_radius);
518 xmlSetProp (node, "radius", string);
521 case GL_TEMPLATE_STYLE_CD:
522 xmlSetProp (node, "style", "cd");
523 string = g_strdup_printf ("%g", template->label_radius);
524 xmlSetProp (node, "radius", string);
526 string = g_strdup_printf ("%g", template->label_hole);
527 xmlSetProp (node, "hole", string);
531 WARN ("Unknown label style");
535 xml_add_layout (template, node, ns);
539 /*--------------------------------------------------------------------------*/
540 /* PRIVATE. Add XML Sheet->Label->Layout Node. */
541 /*--------------------------------------------------------------------------*/
543 xml_add_layout (glTemplate *template,
550 node = xmlNewChild(root, ns, "Layout", NULL);
551 string = g_strdup_printf ("%d", template->nx);
552 xmlSetProp (node, "nx", string);
554 string = g_strdup_printf ("%d", template->ny);
555 xmlSetProp (node, "ny", string);
557 string = g_strdup_printf ("%g", template->x0);
558 xmlSetProp (node, "x0", string);
560 string = g_strdup_printf ("%g", template->y0);
561 xmlSetProp (node, "y0", string);
563 string = g_strdup_printf ("%g", template->dx);
564 xmlSetProp (node, "dx", string);
566 string = g_strdup_printf ("%g", template->dy);
567 xmlSetProp (node, "dy", string);
571 /*--------------------------------------------------------------------------*/
572 /* PRIVATE. Add XML Sheet->Alias Node. */
573 /*--------------------------------------------------------------------------*/
575 xml_add_alias (gchar *name,
581 node = xmlNewChild (root, ns, "Alias", NULL);
582 xmlSetProp (node, "name", name);