]> git.sur5r.net Git - glabels/blob - libglabels/lgl-db.c
Upload to unstable
[glabels] / libglabels / lgl-db.c
1 /*
2  *  lgl-db.c
3  *  Copyright (C) 2003-2010  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of libglabels.
6  *
7  *  libglabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  libglabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "lgl-db.h"
24
25 #include <glib/gi18n.h>
26 #include <glib.h>
27 #include <glib/gstdio.h>
28 #include <glib-object.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32
33 #include "libglabels-private.h"
34
35 #include "lgl-xml-paper.h"
36 #include "lgl-xml-category.h"
37 #include "lgl-xml-vendor.h"
38 #include "lgl-xml-template.h"
39
40 /*===========================================*/
41 /* Private macros and constants.             */
42 /*===========================================*/
43
44 /* Data system and user data directories.  (must free w/ g_free()) */
45 #define SYSTEM_CONFIG_DIR     g_build_filename (LIBGLABELS_CONFIG_DIR, "templates", NULL)
46 #define USER_CONFIG_DIR       g_build_filename (g_get_user_config_dir (), "libglabels", "templates" , NULL)
47 #define ALT_USER_CONFIG_DIR   g_build_filename (g_get_home_dir (), ".glabels", NULL)
48
49
50 /*===========================================*/
51 /* Private types                             */
52 /*===========================================*/
53
54 #define TYPE_LGL_DB_MODEL              (lgl_db_model_get_type ())
55 #define LGL_DB_MODEL(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_LGL_DB_MODEL, lglDbModel))
56 #define LGL_DB_MODEL_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_LGL_DB_MODEL, lglDbModelClass))
57 #define IS_LGL_DB_MODEL(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_LGL_DB_MODEL))
58 #define IS_LGL_DB_MODEL_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_LGL_DB_MODEL))
59 #define LGL_DB_MODEL_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS ((object), TYPE_LGL_DB_MODEL, lglDbModelClass))
60
61
62 typedef struct _lglDbModel          lglDbModel;
63 typedef struct _lglDbModelClass     lglDbModelClass;
64
65
66 struct _lglDbModel {
67         GObject     parent;
68
69         GList      *papers;
70         GList      *categories;
71         GList      *vendors;
72         GList      *templates;
73
74         GHashTable *template_cache;
75 };
76
77
78 struct _lglDbModelClass {
79         GObjectClass  parent_class;
80
81         /*
82          * Signals
83          */
84         void (*changed)     (lglDbModel *this,
85                              gpointer    user_data);
86
87 };
88
89
90 enum {
91         CHANGED,
92         LAST_SIGNAL
93 };
94
95
96 /*===========================================*/
97 /* Private globals                           */
98 /*===========================================*/
99
100 static guint signals[LAST_SIGNAL] = {0};
101
102 static lglDbModel *model = NULL;
103
104
105 /*===========================================*/
106 /* Local function prototypes                 */
107 /*===========================================*/
108
109 static void   lgl_db_model_finalize        (GObject     *object);
110
111 static void   add_to_template_cache        (lglTemplate *template);
112
113 static GList *read_papers                  (void);
114 static GList *read_paper_files_from_dir    (GList       *papers,
115                                             const gchar *dirname);
116
117 static GList *read_categories              (void);
118 static GList *read_category_files_from_dir (GList       *categories,
119                                             const gchar *dirname);
120
121 static GList *read_vendors                 (void);
122 static GList *read_vendor_files_from_dir   (GList       *vendors,
123                                             const gchar *dirname);
124
125 static void   read_templates               (void);
126 static void   read_template_files_from_dir (const gchar *dirname);
127
128 static lglTemplate *template_full_page     (const gchar *page_size);
129
130
131 /*****************************************************************************/
132 /* Object infrastructure.                                                    */
133 /*****************************************************************************/
134 G_DEFINE_TYPE (lglDbModel, lgl_db_model, G_TYPE_OBJECT);
135
136
137 /*****************************************************************************/
138 /* Class Init Function.                                                      */
139 /*****************************************************************************/
140 static void
141 lgl_db_model_class_init (lglDbModelClass *class)
142 {
143         GObjectClass  *gobject_class = (GObjectClass *) class;
144
145         lgl_db_model_parent_class = g_type_class_peek_parent (class);
146
147         gobject_class->finalize = lgl_db_model_finalize;
148
149         signals[CHANGED] =
150                 g_signal_new ("changed",
151                               G_OBJECT_CLASS_TYPE (gobject_class),
152                               G_SIGNAL_RUN_LAST,
153                               G_STRUCT_OFFSET (lglDbModelClass, changed),
154                               NULL, NULL,
155                               g_cclosure_marshal_VOID__VOID,
156                               G_TYPE_NONE,
157                               0);
158 }
159
160
161 /*****************************************************************************/
162 /* Object Instance Init Function.                                            */
163 /*****************************************************************************/
164 static void
165 lgl_db_model_init (lglDbModel *this)
166 {
167         this->template_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)lgl_template_free);
168 }
169
170
171 /*****************************************************************************/
172 /* Finalize Method.                                                          */
173 /*****************************************************************************/
174 static void
175 lgl_db_model_finalize (GObject *object)
176 {
177         lglDbModel    *this;
178         GList         *p;
179
180         g_return_if_fail (object && IS_LGL_DB_MODEL (object));
181         this = LGL_DB_MODEL (object);
182
183         g_hash_table_unref (this->template_cache);
184
185         for (p = this->papers; p != NULL; p = p->next)
186         {
187                 g_free (p->data);
188                 p->data = NULL;
189         }
190         g_list_free (this->papers);
191
192         for (p = this->categories; p != NULL; p = p->next)
193         {
194                 g_free (p->data);
195                 p->data = NULL;
196         }
197         g_list_free (this->categories);
198
199         for (p = this->vendors; p != NULL; p = p->next)
200         {
201                 g_free (p->data);
202                 p->data = NULL;
203         }
204         g_list_free (this->vendors);
205
206         for (p = this->templates; p != NULL; p = p->next)
207         {
208                 lgl_template_free ((lglTemplate *)p->data);
209                 p->data = NULL;
210         }
211         g_list_free (this->templates);
212
213         G_OBJECT_CLASS (lgl_db_model_parent_class)->finalize (object);
214 }
215
216
217 /*****************************************************************************/
218 /** New Object Generator.                                                    */
219 /*****************************************************************************/
220 lglDbModel *
221 lgl_db_model_new (void)
222 {
223         lglDbModel *this;
224
225         this = g_object_new (TYPE_LGL_DB_MODEL, NULL);
226
227         return this;
228 }
229
230
231 /*===========================================*/
232 /* Module initialization                     */
233 /*===========================================*/
234
235 /**
236  * lgl_db_init:
237  *
238  * Initialize all libglabels subsystems.  It is not necessary for an application to call
239  * lgl_db_init(), because libglabels will initialize on demand.  An application programmer may
240  * choose to call lgl_db_init() at startup to minimize the impact of the first libglabels call
241  * on GUI response time.
242  *
243  * This function initializes its paper definitions, category definitions, vendor definitions,
244  * and its template database. It will search both system and user template directories to locate
245  * this data.
246  */
247 void
248 lgl_db_init (void)
249 {
250         lglPaper    *paper_other;
251         lglCategory *category_user_defined;
252         lglTemplate *template;
253         GList       *page_sizes;
254         GList       *p;
255
256         model = lgl_db_model_new ();
257
258         /*
259          * Paper definitions
260          */
261         model->papers = read_papers ();
262
263         /* Create and append an "Other" entry. */
264         /* Translators: "Other" here means other page size.  Meaning a page size
265          * other than the standard ones that libglabels knows about such as
266          * "letter", "A4", etc. */
267         paper_other = lgl_paper_new ("Other", _("Other"), 0.0, 0.0, NULL);
268         model->papers = g_list_append (model->papers, paper_other);
269
270         /*
271          * Categories
272          */
273         model->categories = read_categories ();
274
275         /* Create and append a "User defined" entry. */
276         category_user_defined = lgl_category_new ("user-defined", _("User defined"));
277         model->categories = g_list_append (model->categories, category_user_defined);
278
279         /*
280          * Vendors
281          */
282         model->vendors = read_vendors ();
283
284         /*
285          * Templates
286          */
287         read_templates ();
288
289         /* Create and append generic full page templates. */
290         page_sizes = lgl_db_get_paper_id_list ();
291         for ( p=page_sizes; p != NULL; p=p->next )
292         {
293                 if ( !lgl_db_is_paper_id_other (p->data) )
294                 {
295                         template = template_full_page (p->data);
296                         _lgl_db_register_template_internal (template);
297                         lgl_template_free (template);
298                 }
299         }
300         lgl_db_free_paper_id_list (page_sizes);
301
302 }
303
304
305 /**
306  * lgl_db_notify_add:
307  * @func: Callback function to be called when database changes.
308  * @user_data: Passback user data to supply to callback function.
309  *
310  * Register a notification callback function to be called when the database changes.
311  *
312  * Returns: an ID for this notification registration.
313  */
314 gulong
315 lgl_db_notify_add (lglDbNotifyFunc func,
316                    gpointer        user_data)
317 {
318         if (!model)
319         {
320                 lgl_db_init ();
321         }
322
323         return g_signal_connect_swapped (G_OBJECT (model), "changed", G_CALLBACK (func), user_data);
324 }
325
326
327 /**
328  * lgl_db_notify_remove:
329  * @id: ID of notification registration to cancel (see lgl_db_notify_add()).
330  *
331  * Cancel a previous registration a notification callback function.
332  */
333 void
334 lgl_db_notify_remove  (gulong id)
335 {
336         g_signal_handler_disconnect (G_OBJECT (model), id);
337 }
338
339
340 /*===========================================*/
341 /* Paper db functions.                       */
342 /*===========================================*/
343
344 /**
345  * lgl_db_get_paper_id_list:
346  *
347  * Get a list of all paper ids known to libglabels.
348  *
349  * Returns: a list of paper ids.
350  *
351  */
352 GList *
353 lgl_db_get_paper_id_list (void)
354 {
355         GList           *ids = NULL;
356         GList           *p;
357         lglPaper        *paper;
358
359         if (!model)
360         {
361                 lgl_db_init ();
362         }
363
364         for ( p=model->papers; p != NULL; p=p->next )
365         {
366                 paper = (lglPaper *)p->data;
367                 ids = g_list_append (ids, g_strdup (paper->id));
368         }
369
370         return ids;
371 }
372
373
374 /**
375  * lgl_db_free_paper_id_list:
376  * @ids: List of id strings to be freed.
377  *
378  * Free up all storage associated with an id list obtained with
379  * lgl_db_get_paper_id_list().
380  *
381  */
382 void
383 lgl_db_free_paper_id_list (GList *ids)
384 {
385         GList *p;
386
387         for (p = ids; p != NULL; p = p->next)
388         {
389                 g_free (p->data);
390                 p->data = NULL;
391         }
392
393         g_list_free (ids);
394 }
395
396
397 /**
398  * lgl_db_get_paper_name_list:
399  *
400  * Get a list of all localized paper names known to libglabels.
401  *
402  * Returns: a list of localized paper names.
403  *
404  */
405 GList *
406 lgl_db_get_paper_name_list (void)
407 {
408         GList           *names = NULL;
409         GList           *p;
410         lglPaper        *paper;
411
412         if (!model)
413         {
414                 lgl_db_init ();
415         }
416
417         for ( p=model->papers; p != NULL; p=p->next )
418         {
419                 paper = (lglPaper *)p->data;
420                 names = g_list_append (names, g_strdup (paper->name));
421         }
422
423         return names;
424 }
425
426
427 /**
428  * lgl_db_free_paper_name_list:
429  * @names: List of localized paper name strings to be freed.
430  *
431  * Free up all storage associated with a name list obtained with
432  * lgl_db_get_paper_name_list().
433  *
434  */
435 void
436 lgl_db_free_paper_name_list (GList *names)
437 {
438         GList *p;
439
440         for (p = names; p != NULL; p = p->next)
441         {
442                 g_free (p->data);
443                 p->data = NULL;
444         }
445
446         g_list_free (names);
447 }
448
449
450 /**
451  * lgl_db_lookup_paper_from_name:
452  * @name: localized paper name string
453  *
454  * Lookup paper definition from localized paper name string.
455  *
456  * Returns: pointer to a newly allocated #lglPaper structure.
457  *
458  */
459 lglPaper *
460 lgl_db_lookup_paper_from_name (const gchar *name)
461 {
462         GList       *p;
463         lglPaper    *paper;
464
465         if (!model)
466         {
467                 lgl_db_init ();
468         }
469
470         if (name == NULL)
471         {
472                 /* If no name, return first paper as a default */
473                 return lgl_paper_dup ((lglPaper *) model->papers->data);
474         }
475
476         for (p = model->papers; p != NULL; p = p->next)
477         {
478                 paper = (lglPaper *) p->data;
479                 if (UTF8_EQUAL (paper->name, name))
480                 {
481                         return lgl_paper_dup (paper);
482                 }
483         }
484
485         return NULL;
486 }
487
488
489 /**
490  * lgl_db_lookup_paper_from_id:
491  * @id: paper id string
492  *
493  * Lookup paper definition from id string.
494  *
495  * Returns: pointer to a newly allocated #lglPaper structure.
496  *
497  */
498 lglPaper *
499 lgl_db_lookup_paper_from_id (const gchar *id)
500 {
501         GList       *p;
502         lglPaper    *paper;
503
504         if (!model)
505         {
506                 lgl_db_init ();
507         }
508
509         if (id == NULL)
510         {
511                 /* If no id, return first paper as a default */
512                 return lgl_paper_dup ((lglPaper *) model->papers->data);
513         }
514
515         for (p = model->papers; p != NULL; p = p->next)
516         {
517                 paper = (lglPaper *) p->data;
518                 if (ASCII_EQUAL (paper->id, id))
519                 {
520                         return lgl_paper_dup (paper);
521                 }
522         }
523
524         return NULL;
525 }
526
527
528 /**
529  * lgl_db_lookup_paper_id_from_name:
530  * @name: localized paper name stringp
531  *
532  * Lookup paper name string from localized paper name string.
533  *
534  * Returns: pointer to a newly allocated id string.
535  *
536  */
537 gchar *
538 lgl_db_lookup_paper_id_from_name (const gchar *name)
539 {
540         lglPaper *paper = NULL;
541         gchar    *id = NULL;
542
543         if (name != NULL)
544         {
545                 paper = lgl_db_lookup_paper_from_name (name);
546                 if ( paper != NULL )
547                 {
548                         id = g_strdup (paper->id);
549                         lgl_paper_free (paper);
550                         paper = NULL;
551                 }
552         }
553
554         return id;
555 }
556
557
558 /**
559  * lgl_db_lookup_paper_name_from_id:
560  * @id: paper id string
561  *
562  * Lookup localized paper name string from paper id string.
563  *
564  * Returns: pointer to a newly allocated localized paper name string.
565  *
566  */
567 gchar *
568 lgl_db_lookup_paper_name_from_id (const gchar         *id)
569 {
570         lglPaper *paper = NULL;
571         gchar    *name = NULL;
572
573         if (id != NULL)
574         {
575                 paper = lgl_db_lookup_paper_from_id (id);
576                 if ( paper != NULL )
577                 {
578                         name = g_strdup (paper->name);
579                         lgl_paper_free (paper);
580                         paper = NULL;
581                 }
582         }
583
584         return name;
585 }
586
587
588 /**
589  * lgl_db_is_paper_id_known:
590  * @id: paper id to test
591  *
592  * Determine if given paper id is known to libglabels.
593  *
594  * Returns: TRUE if id is known, otherwise FALSE.
595  *
596  */
597 gboolean
598 lgl_db_is_paper_id_known (const gchar *id)
599 {
600         GList       *p;
601         lglPaper    *paper;
602
603         if (!model)
604         {
605                 lgl_db_init ();
606         }
607
608         if (id == NULL)
609         {
610                 return FALSE;
611         }
612
613         for (p = model->papers; p != NULL; p = p->next)
614         {
615                 paper = (lglPaper *) p->data;
616                 if (ASCII_EQUAL (paper->id, id))
617                 {
618                         return TRUE;
619                 }
620         }
621
622         return FALSE;
623 }
624
625
626 /**
627  * lgl_db_is_paper_id_other:
628  * @id: paper id to test
629  *
630  * Determine if given paper id is the special id "Other."
631  *
632  * Returns: TRUE if id is "Other", otherwise FALSE.
633  *
634  */
635 gboolean
636 lgl_db_is_paper_id_other (const gchar *id)
637 {
638         if (id == NULL)
639         {
640                 return FALSE;
641         }
642
643         return (ASCII_EQUAL (id, "Other"));
644 }
645
646
647 static GList *
648 read_papers (void)
649 {
650         gchar *data_dir;
651         GList *papers = NULL;
652
653         data_dir = SYSTEM_CONFIG_DIR;
654         papers = read_paper_files_from_dir (papers, data_dir);
655         g_free (data_dir);
656
657         data_dir = USER_CONFIG_DIR;
658         papers = read_paper_files_from_dir (papers, data_dir);
659         g_free (data_dir);
660
661         if (papers == NULL)
662         {
663                 g_critical (_("Unable to locate paper size definitions.  Libglabels may not be installed correctly!"));
664         }
665
666         return papers;
667 }
668
669
670 static GList *
671 read_paper_files_from_dir (GList       *papers,
672                            const gchar *dirname)
673 {
674         GDir        *dp;
675         const gchar *filename, *extension;
676         gchar       *full_filename = NULL;
677         GError      *gerror = NULL;
678         GList       *new_papers = NULL;
679
680         if (dirname == NULL)
681         {
682                 return papers;
683         }
684
685         if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
686         {
687                 return papers;
688         }
689
690         dp = g_dir_open (dirname, 0, &gerror);
691         if (gerror != NULL)
692         {
693                 g_message ("cannot open data directory: %s", gerror->message );
694                 return papers;
695         }
696
697         while ((filename = g_dir_read_name (dp)) != NULL)
698         {
699
700                 extension = strrchr (filename, '.');
701
702                 if (extension != NULL)
703                 {
704
705                         if ( ASCII_EQUAL (filename, "paper-sizes.xml") )
706                         {
707
708                                 full_filename =
709                                     g_build_filename (dirname, filename, NULL);
710                                 new_papers =
711                                     lgl_xml_paper_read_papers_from_file (full_filename);
712                                 g_free (full_filename);
713
714                                 papers = g_list_concat (papers, new_papers);
715                                 new_papers = NULL;
716
717                         }
718
719                 }
720
721         }
722
723         g_dir_close (dp);
724
725         return papers;
726 }
727
728
729 /**
730  * lgl_db_print_known_papers:
731  *
732  * For debugging purposes: print a list of all paper definitions known to
733  * libglabels.
734  *
735  */
736 void
737 lgl_db_print_known_papers (void)
738 {
739         GList       *p;
740         lglPaper    *paper;
741
742         if (!model)
743         {
744                 lgl_db_init ();
745         }
746
747         g_print ("%s():\n", __FUNCTION__);
748         for (p = model->papers; p != NULL; p = p->next)
749         {
750                 paper = (lglPaper *) p->data;
751
752                 g_print ("PAPER id=\"%s\", name=\"%s\", width=%gpts, height=%gpts\n",
753                          paper->id, paper->name, paper->width, paper->height);
754         }
755         g_print ("\n");
756
757 }
758
759
760 /*===========================================*/
761 /* Category db functions.                    */
762 /*===========================================*/
763
764 /**
765  * lgl_db_get_category_id_list:
766  *
767  * Get a list of all category ids known to libglabels.
768  *
769  * Returns: a list of category ids.
770  *
771  */
772 GList *
773 lgl_db_get_category_id_list (void)
774 {
775         GList           *ids = NULL;
776         GList           *p;
777         lglCategory     *category;
778
779         if (!model)
780         {
781                 lgl_db_init ();
782         }
783
784         for ( p=model->categories; p != NULL; p=p->next )
785         {
786                 category = (lglCategory *)p->data;
787                 ids = g_list_append (ids, g_strdup (category->id));
788         }
789
790         return ids;
791 }
792
793
794 /**
795  * lgl_db_free_category_id_list:
796  * @ids: List of id strings to be freed.
797  *
798  * Free up all storage associated with an id list obtained with
799  * lgl_db_get_category_id_list().
800  *
801  */
802 void
803 lgl_db_free_category_id_list (GList *ids)
804 {
805         GList *p;
806
807         for (p = ids; p != NULL; p = p->next)
808         {
809                 g_free (p->data);
810                 p->data = NULL;
811         }
812
813         g_list_free (ids);
814 }
815
816
817 /**
818  * lgl_db_get_category_name_list:
819  *
820  * Get a list of all localized category names known to libglabels.
821  *
822  * Returns: a list of localized category names.
823  *
824  */
825 GList *
826 lgl_db_get_category_name_list (void)
827 {
828         GList           *names = NULL;
829         GList           *p;
830         lglCategory     *category;
831
832         if (!model)
833         {
834                 lgl_db_init ();
835         }
836
837         for ( p=model->categories; p != NULL; p=p->next )
838         {
839                 category = (lglCategory *)p->data;
840                 names = g_list_append (names, g_strdup (category->name));
841         }
842
843         return names;
844 }
845
846
847 /**
848  * lgl_db_free_category_name_list:
849  * @names: List of localized category name strings to be freed.
850  *
851  * Free up all storage associated with a name list obtained with
852  * lgl_db_get_category_name_list().
853  *
854  */
855 void
856 lgl_db_free_category_name_list (GList *names)
857 {
858         GList *p;
859
860         for (p = names; p != NULL; p = p->next)
861         {
862                 g_free (p->data);
863                 p->data = NULL;
864         }
865
866         g_list_free (names);
867 }
868
869
870 /**
871  * lgl_db_lookup_category_from_name:
872  * @name: localized category name string
873  *
874  * Lookup category definition from localized category name string.
875  *
876  * Returns: pointer to a newly allocated #lglCategory structure.
877  *
878  */
879 lglCategory *
880 lgl_db_lookup_category_from_name (const gchar *name)
881 {
882         GList       *p;
883         lglCategory *category;
884
885         if (!model)
886         {
887                 lgl_db_init ();
888         }
889
890         if (name == NULL)
891         {
892                 /* If no name, return first category as a default */
893                 return lgl_category_dup ((lglCategory *) model->categories->data);
894         }
895
896         for (p = model->categories; p != NULL; p = p->next)
897         {
898                 category = (lglCategory *) p->data;
899                 if (UTF8_EQUAL (category->name, name))
900                 {
901                         return lgl_category_dup (category);
902                 }
903         }
904
905         return NULL;
906 }
907
908
909 /**
910  * lgl_db_lookup_category_from_id:
911  * @id: category id string
912  *
913  * Lookup category definition from id string.
914  *
915  * Returns: pointer to a newly allocated #lglCategory structure.
916  *
917  */
918 lglCategory *
919 lgl_db_lookup_category_from_id (const gchar *id)
920 {
921         GList       *p;
922         lglCategory *category;
923
924         if (!model)
925         {
926                 lgl_db_init ();
927         }
928
929         if (id == NULL)
930         {
931                 /* If no id, return first category as a default */
932                 return lgl_category_dup ((lglCategory *) model->categories->data);
933         }
934
935         for (p = model->categories; p != NULL; p = p->next)
936         {
937                 category = (lglCategory *) p->data;
938                 if (ASCII_EQUAL (category->id, id))
939                 {
940                         return lgl_category_dup (category);
941                 }
942         }
943
944         return NULL;
945 }
946
947
948 /**
949  * lgl_db_lookup_category_id_from_name:
950  * @name: localized category name stringp
951  *
952  * Lookup category name string from localized category name string.
953  *
954  * Returns: pointer to a newly allocated id string.
955  *
956  */
957 gchar *
958 lgl_db_lookup_category_id_from_name (const gchar *name)
959 {
960         lglCategory *category = NULL;
961         gchar       *id = NULL;
962
963         if (name != NULL)
964         {
965                 category = lgl_db_lookup_category_from_name (name);
966                 if ( category != NULL )
967                 {
968                         id = g_strdup (category->id);
969                         lgl_category_free (category);
970                         category = NULL;
971                 }
972         }
973
974         return id;
975 }
976
977
978 /**
979  * lgl_db_lookup_category_name_from_id:
980  * @id: category id string
981  *
982  * Lookup localized category name string from category id string.
983  *
984  * Returns: pointer to a newly allocated localized category name string.
985  *
986  */
987 gchar *
988 lgl_db_lookup_category_name_from_id (const gchar         *id)
989 {
990         lglCategory *category = NULL;
991         gchar       *name = NULL;
992
993         if (id != NULL)
994         {
995                 category = lgl_db_lookup_category_from_id (id);
996                 if ( category != NULL )
997                 {
998                         name = g_strdup (category->name);
999                         lgl_category_free (category);
1000                         category = NULL;
1001                 }
1002         }
1003
1004         return name;
1005 }
1006
1007
1008 /**
1009  * lgl_db_is_category_id_known:
1010  * @id: category id to test
1011  *
1012  * Determine if given category id is known to libglabels.
1013  *
1014  * Returns: TRUE if id is known, otherwise FALSE.
1015  *
1016  */
1017 gboolean
1018 lgl_db_is_category_id_known (const gchar *id)
1019 {
1020         GList       *p;
1021         lglCategory *category;
1022
1023         if (!model)
1024         {
1025                 lgl_db_init ();
1026         }
1027
1028         if (id == NULL)
1029         {
1030                 return FALSE;
1031         }
1032
1033         for (p = model->categories; p != NULL; p = p->next)
1034         {
1035                 category = (lglCategory *) p->data;
1036                 if (ASCII_EQUAL (category->id, id))
1037                 {
1038                         return TRUE;
1039                 }
1040         }
1041
1042         return FALSE;
1043 }
1044
1045
1046 static GList *
1047 read_categories (void)
1048 {
1049         gchar *data_dir;
1050         GList *categories = NULL;
1051
1052         data_dir = SYSTEM_CONFIG_DIR;
1053         categories = read_category_files_from_dir (categories, data_dir);
1054         g_free (data_dir);
1055
1056         data_dir = USER_CONFIG_DIR;
1057         categories = read_category_files_from_dir (categories, data_dir);
1058         g_free (data_dir);
1059
1060         if (categories == NULL)
1061         {
1062                 g_critical (_("Unable to locate category definitions.  Libglabels may not be installed correctly!"));
1063         }
1064
1065         return categories;
1066 }
1067
1068
1069 static GList *
1070 read_category_files_from_dir (GList       *categories,
1071                               const gchar *dirname)
1072 {
1073         GDir        *dp;
1074         const gchar *filename, *extension;
1075         gchar       *full_filename = NULL;
1076         GError      *gerror = NULL;
1077         GList       *new_categories = NULL;
1078
1079         if (dirname == NULL)
1080         {
1081                 return categories;
1082         }
1083
1084         if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
1085         {
1086                 return categories;
1087         }
1088
1089         dp = g_dir_open (dirname, 0, &gerror);
1090         if (gerror != NULL)
1091         {
1092                 g_message ("cannot open data directory: %s", gerror->message );
1093                 return categories;
1094         }
1095
1096         while ((filename = g_dir_read_name (dp)) != NULL)
1097         {
1098
1099                 extension = strrchr (filename, '.');
1100
1101                 if (extension != NULL)
1102                 {
1103
1104                         if ( ASCII_EQUAL (filename, "categories.xml") )
1105                         {
1106
1107                                 full_filename =
1108                                     g_build_filename (dirname, filename, NULL);
1109                                 new_categories =
1110                                     lgl_xml_category_read_categories_from_file (full_filename);
1111                                 g_free (full_filename);
1112
1113                                 categories = g_list_concat (categories, new_categories);
1114                                 new_categories = NULL;
1115
1116                         }
1117
1118                 }
1119
1120         }
1121
1122         g_dir_close (dp);
1123
1124         return categories;
1125 }
1126
1127
1128 /**
1129  * lgl_db_print_known_categories:
1130  *
1131  * For debugging purposes: print a list of all category definitions known to
1132  * libglabels.
1133  *
1134  */
1135 void
1136 lgl_db_print_known_categories (void)
1137 {
1138         GList       *p;
1139         lglCategory *category;
1140
1141         if (!model)
1142         {
1143                 lgl_db_init ();
1144         }
1145
1146         g_print ("%s():\n", __FUNCTION__);
1147         for (p = model->categories; p != NULL; p = p->next)
1148         {
1149                 category = (lglCategory *) p->data;
1150
1151                 g_print ("CATEGORY id=\"%s\", name=\"%s\"\n", category->id, category->name);
1152         }
1153         g_print ("\n");
1154
1155 }
1156
1157
1158 /*===========================================*/
1159 /* Vendor db functions.                       */
1160 /*===========================================*/
1161
1162 /**
1163  * lgl_db_get_vendor_name_list:
1164  *
1165  * Get a list of all localized vendor names known to libglabels.
1166  *
1167  * Returns: a list of localized vendor names.
1168  *
1169  */
1170 GList *
1171 lgl_db_get_vendor_name_list (void)
1172 {
1173         GList           *names = NULL;
1174         GList           *p;
1175         lglVendor       *vendor;
1176
1177         if (!model)
1178         {
1179                 lgl_db_init ();
1180         }
1181
1182         for ( p=model->vendors; p != NULL; p=p->next )
1183         {
1184                 vendor = (lglVendor *)p->data;
1185                 names = g_list_append (names, g_strdup (vendor->name));
1186         }
1187
1188         return names;
1189 }
1190
1191
1192 /**
1193  * lgl_db_free_vendor_name_list:
1194  * @names: List of localized vendor name strings to be freed.
1195  *
1196  * Free up all storage associated with a name list obtained with
1197  * lgl_db_get_vendor_name_list().
1198  *
1199  */
1200 void
1201 lgl_db_free_vendor_name_list (GList *names)
1202 {
1203         GList *p;
1204
1205         for (p = names; p != NULL; p = p->next)
1206         {
1207                 g_free (p->data);
1208                 p->data = NULL;
1209         }
1210
1211         g_list_free (names);
1212 }
1213
1214
1215 /**
1216  * lgl_db_lookup_vendor_from_name:
1217  * @name: localized vendor name string
1218  *
1219  * Lookup vendor definition from localized vendor name string.
1220  *
1221  * Returns: pointer to a newly allocated #lglVendor structure.
1222  *
1223  */
1224 lglVendor *
1225 lgl_db_lookup_vendor_from_name (const gchar *name)
1226 {
1227         GList       *p;
1228         lglVendor   *vendor;
1229
1230         if (!model)
1231         {
1232                 lgl_db_init ();
1233         }
1234
1235         if (name == NULL)
1236         {
1237                 /* If no name, return first vendor as a default */
1238                 return lgl_vendor_dup ((lglVendor *) model->vendors->data);
1239         }
1240
1241         for (p = model->vendors; p != NULL; p = p->next)
1242         {
1243                 vendor = (lglVendor *) p->data;
1244                 if (UTF8_EQUAL (vendor->name, name))
1245                 {
1246                         return lgl_vendor_dup (vendor);
1247                 }
1248         }
1249
1250         return NULL;
1251 }
1252
1253
1254 /**
1255  * lgl_db_is_vendor_name_known:
1256  * @name: vendor name to test
1257  *
1258  * Determine if given vendor id is known to libglabels.
1259  *
1260  * Returns: TRUE if id is known, otherwise FALSE.
1261  *
1262  */
1263 gboolean
1264 lgl_db_is_vendor_name_known (const gchar *name)
1265 {
1266         GList       *p;
1267         lglVendor   *vendor;
1268
1269         if (!model)
1270         {
1271                 lgl_db_init ();
1272         }
1273
1274         if (name == NULL)
1275         {
1276                 return FALSE;
1277         }
1278
1279         for (p = model->vendors; p != NULL; p = p->next)
1280         {
1281                 vendor = (lglVendor *) p->data;
1282                 if (UTF8_EQUAL (vendor->name, name))
1283                 {
1284                         return TRUE;
1285                 }
1286         }
1287
1288         return FALSE;
1289 }
1290
1291
1292 static GList *
1293 read_vendors (void)
1294 {
1295         gchar *data_dir;
1296         GList *vendors = NULL;
1297
1298         data_dir = SYSTEM_CONFIG_DIR;
1299         vendors = read_vendor_files_from_dir (vendors, data_dir);
1300         g_free (data_dir);
1301
1302         data_dir = USER_CONFIG_DIR;
1303         vendors = read_vendor_files_from_dir (vendors, data_dir);
1304         g_free (data_dir);
1305
1306         return vendors;
1307 }
1308
1309
1310 static GList *
1311 read_vendor_files_from_dir (GList      *vendors,
1312                            const gchar *dirname)
1313 {
1314         GDir        *dp;
1315         const gchar *filename, *extension;
1316         gchar       *full_filename = NULL;
1317         GError      *gerror = NULL;
1318         GList       *new_vendors = NULL;
1319
1320         if (dirname == NULL)
1321         {
1322                 return vendors;
1323         }
1324
1325         if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
1326         {
1327                 return vendors;
1328         }
1329
1330         dp = g_dir_open (dirname, 0, &gerror);
1331         if (gerror != NULL)
1332         {
1333                 g_message ("cannot open data directory: %s", gerror->message );
1334                 return vendors;
1335         }
1336
1337         while ((filename = g_dir_read_name (dp)) != NULL)
1338         {
1339
1340                 extension = strrchr (filename, '.');
1341
1342                 if (extension != NULL)
1343                 {
1344
1345                         if ( ASCII_EQUAL (filename, "vendors.xml") )
1346                         {
1347
1348                                 full_filename =
1349                                     g_build_filename (dirname, filename, NULL);
1350                                 new_vendors =
1351                                     lgl_xml_vendor_read_vendors_from_file (full_filename);
1352                                 g_free (full_filename);
1353
1354                                 vendors = g_list_concat (vendors, new_vendors);
1355                                 new_vendors = NULL;
1356
1357                         }
1358
1359                 }
1360
1361         }
1362
1363         g_dir_close (dp);
1364
1365         return vendors;
1366 }
1367
1368
1369 /**
1370  * lgl_db_print_known_vendors:
1371  *
1372  * For debugging purposes: print a list of all vendor definitions known to
1373  * libglabels.
1374  *
1375  */
1376 void
1377 lgl_db_print_known_vendors (void)
1378 {
1379         GList       *p;
1380         lglVendor   *vendor;
1381
1382         if (!model)
1383         {
1384                 lgl_db_init ();
1385         }
1386
1387         g_print ("%s():\n", __FUNCTION__);
1388         for (p = model->vendors; p != NULL; p = p->next)
1389         {
1390                 vendor = (lglVendor *) p->data;
1391
1392                 g_print ("VENDOR name=\"%s\", url=\"%s\"\n",
1393                          vendor->name, vendor->url);
1394         }
1395         g_print ("\n");
1396
1397 }
1398
1399
1400 /*===========================================*/
1401 /* Brand db functions.                       */
1402 /*===========================================*/
1403
1404 /**
1405  * lgl_db_get_brand_list:
1406  * @paper_id: If non NULL, limit results to given page size.
1407  * @category_id: If non NULL, limit results to given template category.
1408  *
1409  * Get a list of all valid brands of templates in the template database.
1410  * Results can be filtered by page size and/or template category.  A list of valid page
1411  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
1412  * categories can be obtained using lgl_db_get_category_id_list().
1413  *
1414  * Returns: a list of brands
1415  */
1416 GList *
1417 lgl_db_get_brand_list (const gchar *paper_id,
1418                        const gchar *category_id)
1419 {
1420         GList            *p_tmplt;
1421         lglTemplate      *template;
1422         GList            *brands = NULL;
1423
1424         if (!model)
1425         {
1426                 lgl_db_init ();
1427         }
1428
1429         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1430         {
1431                 template = (lglTemplate *) p_tmplt->data;
1432                 if (lgl_template_does_page_size_match (template, paper_id) &&
1433                     lgl_template_does_category_match (template, category_id))
1434                 {
1435
1436                         if ( !g_list_find_custom (brands, template->brand,
1437                                                   (GCompareFunc)lgl_str_utf8_casecmp) )
1438                         {
1439                                 brands = g_list_insert_sorted (brands,
1440                                                                g_strdup (template->brand),
1441                                                                (GCompareFunc)lgl_str_utf8_casecmp);
1442                         }
1443                 }
1444         }
1445
1446         return brands;
1447 }
1448
1449
1450 /**
1451  * lgl_db_free_brand_list:
1452  * @brands: List of template brand strings to be freed.
1453  *
1454  * Free up all storage associated with a list of template names obtained with
1455  * lgl_db_get_brand_list().
1456  *
1457  */
1458 void
1459 lgl_db_free_brand_list (GList *brands)
1460 {
1461         GList *p_brand;
1462
1463         for (p_brand = brands; p_brand != NULL; p_brand = p_brand->next)
1464         {
1465                 g_free (p_brand->data);
1466                 p_brand->data = NULL;
1467         }
1468
1469         g_list_free (brands);
1470 }
1471
1472
1473 /*===========================================*/
1474 /* Template db functions.                    */
1475 /*===========================================*/
1476
1477 void
1478 _lgl_db_register_template_internal (const lglTemplate   *template)
1479 {
1480         lglTemplate *template_copy;
1481
1482         if (!lgl_db_does_template_exist (template->brand, template->part))
1483         {
1484                 template_copy = lgl_template_dup (template);
1485                 model->templates = g_list_append (model->templates, template_copy);
1486                 add_to_template_cache (template_copy);
1487         }
1488         else
1489         {
1490                 g_message ("Duplicate template: %s %s.", template->brand, template->part);
1491         }
1492 }
1493
1494
1495 /**
1496  * lgl_db_register_template:
1497  * @template:  Pointer to a template structure to add to database.
1498  *
1499  * Register a template.  This function adds a template to the template database.
1500  * The template will be stored in an individual XML file in the user template directory.
1501  *
1502  * Returns: Status of registration attempt (#lglDbRegStatus)
1503  */
1504 lglDbRegStatus
1505 lgl_db_register_template (const lglTemplate *template)
1506 {
1507         lglTemplate *template_copy;
1508         gchar       *dir, *filename, *abs_filename;
1509         gint         bytes_written;
1510
1511         if (!model)
1512         {
1513                 lgl_db_init ();
1514         }
1515
1516         if (lgl_db_does_template_exist (template->brand, template->part))
1517         {
1518                 return LGL_DB_REG_BRAND_PART_EXISTS;
1519         }
1520
1521         if (lgl_db_is_paper_id_known (template->paper_id))
1522         {
1523                 dir = USER_CONFIG_DIR;
1524                 g_mkdir_with_parents (dir, 0775); /* Try to make sure directory exists. */
1525                 filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
1526                 abs_filename = g_build_filename (dir, filename, NULL);
1527                 bytes_written = lgl_xml_template_write_template_to_file (template, abs_filename);
1528                 g_free (dir);
1529                 g_free (filename);
1530                 g_free (abs_filename);
1531
1532                 if (bytes_written > 0)
1533                 {
1534                         template_copy = lgl_template_dup (template);
1535                         lgl_template_add_category (template_copy, "user-defined");
1536                         model->templates = g_list_append (model->templates, template_copy);
1537                         add_to_template_cache (template_copy);
1538                         g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
1539                         return LGL_DB_REG_OK;
1540                 }
1541                 else
1542                 {
1543                         return LGL_DB_REG_FILE_WRITE_ERROR;
1544                 }
1545         }
1546         else
1547         {
1548                 g_message ("Cannot register new template with unknown page size.");
1549                 return LGL_DB_REG_BAD_PAPER_ID;
1550         }
1551
1552 }
1553
1554
1555 /**
1556  * lgl_db_delete_template_by_name:
1557  * @name:  Name of template to be deleted.
1558  *
1559  * Delete a user defined template.  This function deletes a template from
1560  * the template database. The individual XML file in the user template
1561  * directory will also be removed.
1562  *
1563  * Returns: Status of registration attempt (#lglDbDeleteStatus)
1564  */
1565 lglDbDeleteStatus
1566 lgl_db_delete_template_by_name (const gchar *name)
1567 {
1568         lglTemplate *template, *template1;
1569         gchar       *dir, *filename, *abs_filename;
1570         GList       *p;
1571
1572         if (!model)
1573         {
1574                 lgl_db_init ();
1575         }
1576
1577         if (!lgl_db_does_template_name_exist (name))
1578         {
1579                 return LGL_DB_DELETE_DOES_NOT_EXIST;
1580         }
1581
1582         template = lgl_db_lookup_template_from_name (name);
1583         if ( lgl_template_does_category_match (template, "user-defined") )
1584         {
1585                 dir = USER_CONFIG_DIR;
1586                 filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
1587                 abs_filename = g_build_filename (dir, filename, NULL);
1588
1589                 if (!g_file_test (abs_filename, G_FILE_TEST_EXISTS))
1590                 {
1591                         g_message ("File \"%s\" does not exist.  Cannot delete template.", abs_filename);
1592                         return LGL_DB_DELETE_DOES_NOT_EXIST;
1593                 }
1594
1595                 g_unlink (abs_filename);
1596
1597                 g_free (dir);
1598                 g_free (filename);
1599                 g_free (abs_filename);
1600
1601                 for ( p=model->templates; p != NULL; p=p->next )
1602                 {
1603                         template1 = (lglTemplate *)p->data;
1604
1605                         if ( lgl_template_do_templates_match (template, template1) )
1606                         {
1607                                 model->templates = g_list_delete_link (model->templates, p);
1608                                 g_hash_table_remove (model->template_cache, name);
1609                                 break;
1610                         }
1611                 }
1612
1613                 lgl_template_free (template);
1614
1615                 g_signal_emit (G_OBJECT (model), signals[CHANGED], 0);
1616                 return LGL_DB_DELETE_OK;
1617         }
1618         else
1619         {
1620                 return LGL_DB_DELETE_NOT_USER_DEFINED;
1621         }
1622
1623 }
1624
1625
1626 /**
1627  * lgl_db_delete_template_by_brand_part:
1628  * @brand:  Brand name or vendor of template to be deleted.
1629  * @part:   Part name or number of template to be deleted.
1630  *
1631  * Delete a user defined template.  This function deletes a template from
1632  * the template database. The individual XML file in the user template
1633  * directory will also be removed.
1634  *
1635  * Returns: Status of registration attempt (#lglDbDeleteStatus)
1636  */
1637 lglDbDeleteStatus
1638 lgl_db_delete_template_by_brand_part (const gchar  *brand,
1639                                       const gchar  *part)
1640 {
1641         gchar             *name;
1642         lglDbDeleteStatus  status;
1643
1644         name = g_strdup_printf ("%s %s", brand, part);
1645
1646         status = lgl_db_delete_template_by_name (name);
1647
1648         g_free (name);
1649
1650         return status;
1651 }
1652
1653
1654 /**
1655  * lgl_db_does_template_exist:
1656  * @brand: Brand name.
1657  * @part:  Part name/number.
1658  *
1659  * This function tests whether a template with the given brand and part name/number exists.
1660  *
1661  * Returns:  TRUE if such a template exists in the database.
1662  */
1663 gboolean
1664 lgl_db_does_template_exist (const gchar *brand,
1665                             const gchar *part)
1666 {
1667         GList            *p_tmplt;
1668         lglTemplate      *template;
1669
1670         if (!model)
1671         {
1672                 lgl_db_init ();
1673         }
1674
1675         if ((brand == NULL) || (part == NULL))
1676         {
1677                 return FALSE;
1678         }
1679
1680         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1681         {
1682                 template = (lglTemplate *) p_tmplt->data;
1683
1684                 if ( UTF8_EQUAL (brand, template->brand) &&
1685                      UTF8_EQUAL (part, template->part) )
1686                 {
1687                         return TRUE;
1688                 }
1689         }
1690
1691         return FALSE;
1692 }
1693
1694
1695 /**
1696  * lgl_db_does_template_name_exist:
1697  * @name: name string
1698  *
1699  * This function test whether a template with the given name exists.
1700  *
1701  * Returns: TRUE if such a template exists in the database.
1702  *
1703  */
1704 gboolean
1705 lgl_db_does_template_name_exist (const gchar *name)
1706 {
1707         GList            *p_tmplt;
1708         lglTemplate      *template;
1709         gchar            *candidate_name;
1710
1711         if (!model)
1712         {
1713                 lgl_db_init ();
1714         }
1715
1716         if (name == NULL)
1717         {
1718                 return FALSE;
1719         }
1720
1721         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1722         {
1723                 template = (lglTemplate *) p_tmplt->data;
1724                 candidate_name = g_strdup_printf ("%s %s", template->brand, template->part);
1725
1726                 if ( UTF8_EQUAL (candidate_name, name) )
1727                 {
1728                         g_free (candidate_name);
1729                         return TRUE;
1730                 }
1731                 g_free (candidate_name);
1732         }
1733
1734         return FALSE;
1735 }
1736
1737
1738 /**
1739  * lgl_db_get_template_name_list_all:
1740  * @brand:     If non NULL, limit results to given brand
1741  * @paper_id: If non NULL, limit results to given page size.
1742  * @category_id: If non NULL, limit results to given template category.
1743  *
1744  * Get a list of all valid names of templates in the template database.
1745  * Results can be filtered by page size and/or template category.  A list of valid page
1746  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
1747  * categories can be obtained using lgl_db_get_category_id_list().
1748  *
1749  * Returns: a list of template names.
1750  */
1751 GList *
1752 lgl_db_get_template_name_list_all (const gchar *brand,
1753                                    const gchar *paper_id,
1754                                    const gchar *category_id)
1755 {
1756         GList            *p_tmplt;
1757         lglTemplate      *template;
1758         gchar            *name;
1759         GList            *names = NULL;
1760
1761         if (!model)
1762         {
1763                 lgl_db_init ();
1764         }
1765
1766         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1767         {
1768                 template = (lglTemplate *) p_tmplt->data;
1769                 if (lgl_template_does_brand_match (template, brand) &&
1770                     lgl_template_does_page_size_match (template, paper_id) &&
1771                     lgl_template_does_category_match (template, category_id))
1772                 {
1773                         name = g_strdup_printf ("%s %s", template->brand, template->part);
1774                         names = g_list_insert_sorted (names, name, (GCompareFunc)lgl_str_part_name_cmp);
1775                 }
1776         }
1777
1778         return names;
1779 }
1780
1781
1782 /**
1783  * lgl_db_get_similar_template_name_list:
1784  * @name:     Name of template under test.
1785  *
1786  * Get a list of all valid names of templates in the template database that
1787  * have the same size and layout characteristics as the given template.
1788  *
1789  * Returns: a list of template names.
1790  */
1791 GList *
1792 lgl_db_get_similar_template_name_list (const gchar  *name)
1793 {
1794         GList            *p_tmplt;
1795         lglTemplate      *template1;
1796         lglTemplate      *template2;
1797         gchar            *name2;
1798         GList            *names = NULL;
1799
1800         if (!model)
1801         {
1802                 lgl_db_init ();
1803         }
1804
1805         if ( !name )
1806         {
1807                 return NULL;
1808         }
1809
1810         template1 = lgl_db_lookup_template_from_name (name);
1811         if ( !template1 )
1812         {
1813                 return NULL;
1814         }
1815
1816         for (p_tmplt = model->templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1817         {
1818                 template2 = (lglTemplate *) p_tmplt->data;
1819
1820                 if ( lgl_template_are_templates_identical (template1, template2) )
1821                 {
1822
1823                         name2 = g_strdup_printf ("%s %s", template2->brand, template2->part);
1824                         if ( !UTF8_EQUAL (name2, name) )
1825                         {
1826                                 names = g_list_insert_sorted (names, name2,
1827                                                               (GCompareFunc)lgl_str_part_name_cmp);
1828                         }
1829
1830                 }
1831         }
1832
1833         return names;
1834 }
1835
1836
1837 /**
1838  * lgl_db_free_template_name_list:
1839  * @names: List of template name strings to be freed.
1840  *
1841  * Free up all storage associated with a list of template names obtained with
1842  * lgl_db_get_template_name_list_all().
1843  *
1844  */
1845 void
1846 lgl_db_free_template_name_list (GList *names)
1847 {
1848         GList *p_name;
1849
1850         for (p_name = names; p_name != NULL; p_name = p_name->next)
1851         {
1852                 g_free (p_name->data);
1853                 p_name->data = NULL;
1854         }
1855
1856         g_list_free (names);
1857 }
1858
1859
1860 /**
1861  * lgl_db_lookup_template_from_name:
1862  * @name: name string
1863  *
1864  * Lookup template in template database from name string.
1865  *
1866  * Returns: pointer to a newly allocated #lglTemplate structure.
1867  *
1868  */
1869 lglTemplate *
1870 lgl_db_lookup_template_from_name (const gchar *name)
1871 {
1872         lglTemplate      *template;
1873         lglTemplate      *new_template;
1874
1875         if (!model)
1876         {
1877                 lgl_db_init ();
1878         }
1879
1880         if (name == NULL)
1881         {
1882                 /* If no name, return first template as a default */
1883                 return lgl_template_dup ((lglTemplate *) model->templates->data);
1884         }
1885
1886         template = g_hash_table_lookup (model->template_cache, name);
1887
1888         if (template)
1889         {
1890                 new_template = lgl_template_dup (template);
1891                 return new_template;
1892         }
1893
1894         /* No matching template has been found so return the first template */
1895         return lgl_template_dup ((lglTemplate *) model->templates->data);
1896 }
1897
1898
1899 /**
1900  * lgl_db_lookup_template_from_brand_part:
1901  * @brand: brand name string
1902  * @part:  part name string
1903  *
1904  * Lookup template in template database from brand and part strings.
1905  *
1906  * Returns: pointer to a newly allocated #lglTemplate structure.
1907  *
1908  */
1909 lglTemplate *
1910 lgl_db_lookup_template_from_brand_part(const gchar *brand,
1911                                        const gchar *part)
1912 {
1913         gchar            *name;
1914         lglTemplate      *template;
1915         lglTemplate      *new_template;
1916
1917         if (!model)
1918         {
1919                 lgl_db_init ();
1920         }
1921
1922         if ((brand == NULL) || (part == NULL))
1923         {
1924                 /* If no name, return first template as a default */
1925                 return lgl_template_dup ((lglTemplate *) model->templates->data);
1926         }
1927
1928         name = g_strdup_printf ("%s %s", brand, part);
1929         template = g_hash_table_lookup (model->template_cache, name);
1930
1931         if (template)
1932         {
1933                 new_template = lgl_template_dup (template);
1934                 return new_template;
1935         }
1936
1937         /* No matching template has been found so return the first template */
1938         g_free (name);
1939         return lgl_template_dup ((lglTemplate *) model->templates->data);
1940 }
1941
1942
1943 static void
1944 add_to_template_cache (lglTemplate *template)
1945 {
1946         gchar            *name;
1947
1948         name = g_strdup_printf ("%s %s", template->brand, template->part);
1949
1950         g_hash_table_insert (model->template_cache, name, template);
1951 }
1952
1953
1954 void
1955 read_templates (void)
1956 {
1957         gchar       *data_dir;
1958         GList       *p;
1959         lglTemplate *template;
1960
1961         /*
1962          * User defined templates.  Add to user-defined category.
1963          */
1964         data_dir = USER_CONFIG_DIR;
1965         read_template_files_from_dir (data_dir);
1966         g_free (data_dir);
1967         for ( p=model->templates; p != NULL; p=p->next )
1968         {
1969                 template = (lglTemplate *)p->data;
1970                 lgl_template_add_category (template, "user-defined");
1971         }
1972
1973         /*
1974          * Alternate user defined templates.  (Used for manually created templates).
1975          */
1976         data_dir = ALT_USER_CONFIG_DIR;
1977         read_template_files_from_dir (data_dir);
1978         g_free (data_dir);
1979
1980         /*
1981          * System templates.
1982          */
1983         data_dir = SYSTEM_CONFIG_DIR;
1984         read_template_files_from_dir (data_dir);
1985         g_free (data_dir);
1986
1987         if (model->templates == NULL)
1988         {
1989                 g_critical (_("Unable to locate any template files.  Libglabels may not be installed correctly!"));
1990         }
1991 }
1992
1993
1994 void
1995 read_template_files_from_dir (const gchar *dirname)
1996 {
1997         GDir        *dp;
1998         const gchar *filename, *extension, *extension2;
1999         gchar       *full_filename = NULL;
2000         GError      *gerror = NULL;
2001
2002         if (dirname == NULL)
2003                 return;
2004
2005         if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
2006         {
2007                 return;
2008         }
2009
2010         dp = g_dir_open (dirname, 0, &gerror);
2011         if (gerror != NULL)
2012         {
2013                 g_message ("cannot open data directory: %s", gerror->message );
2014                 return;
2015         }
2016
2017         while ((filename = g_dir_read_name (dp)) != NULL)
2018         {
2019
2020                 extension = strrchr (filename, '.');
2021                 extension2 = strrchr (filename, '-');
2022
2023                 if ( (extension && ASCII_EQUAL (extension, ".template")) ||
2024                      (extension2 && ASCII_EQUAL (extension2, "-templates.xml")) )
2025                 {
2026
2027                         full_filename = g_build_filename (dirname, filename, NULL);
2028                         lgl_xml_template_read_templates_from_file (full_filename);
2029                         g_free (full_filename);
2030                 }
2031
2032         }
2033
2034         g_dir_close (dp);
2035 }
2036
2037
2038 static lglTemplate *
2039 template_full_page (const gchar *paper_id)
2040 {
2041         lglPaper              *paper = NULL;
2042         lglTemplate           *template = NULL;
2043         lglTemplateFrame      *frame = NULL;
2044         gchar                 *part;
2045         gchar                 *desc;
2046
2047         g_return_val_if_fail (paper_id, NULL);
2048
2049         paper = lgl_db_lookup_paper_from_id (paper_id);
2050         if ( paper == NULL )
2051         {
2052                 return NULL;
2053         }
2054
2055         part = g_strdup_printf ("%s-Full-Page", paper->id);
2056         desc = g_strdup_printf (_("%s full page label"), paper->name);
2057
2058         template = lgl_template_new ("Generic", part, desc,
2059                                      paper_id, paper->width, paper->height);
2060
2061
2062         frame = lgl_template_frame_rect_new ("0",
2063                                              paper->width,
2064                                              paper->height,
2065                                              0.0,
2066                                              0.0,
2067                                              0.0);
2068         lgl_template_add_frame (template, frame);
2069
2070         lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0., 0., 0., 0.));
2071
2072         lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (9.0));
2073
2074         g_free (desc);
2075         desc = NULL;
2076         lgl_paper_free (paper);
2077         paper = NULL;
2078
2079         return template;
2080 }
2081
2082
2083 /**
2084  * lgl_db_print_known_templates:
2085  *
2086  * Print all known templates (for debugging purposes).
2087  *
2088  */
2089 void
2090 lgl_db_print_known_templates (void)
2091 {
2092         GList       *p;
2093         lglTemplate *template;
2094
2095         if (!model)
2096         {
2097                 lgl_db_init ();
2098         }
2099
2100         g_print ("%s():\n", __FUNCTION__);
2101         for (p=model->templates; p!=NULL; p=p->next)
2102         {
2103                 template = (lglTemplate *)p->data;
2104
2105                 g_print("TEMPLATE brand=\"%s\", part=\"%s\", description=\"%s\"\n",
2106                         template->brand, template->part, template->description);
2107
2108         }
2109         g_print ("\n");
2110
2111 }
2112
2113
2114
2115
2116 /*
2117  * Local Variables:       -- emacs
2118  * mode: C                -- emacs
2119  * c-basic-offset: 8      -- emacs
2120  * tab-width: 8           -- emacs
2121  * indent-tabs-mode: nil  -- emacs
2122  * End:                   -- emacs
2123  */