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