]> git.sur5r.net Git - glabels/blob - libglabels/db.c
Imported Upstream version 2.2.8
[glabels] / libglabels / db.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (LIBGLABELS) Template library for GLABELS
5  *
6  *  db.c:  template db module
7  *
8  *  Copyright (C) 2003-2007  Jim Evins <evins@snaught.com>.
9  *
10  *  This file is part of the LIBGLABELS library.
11  *
12  *  This library is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Library General Public
14  *  License as published by the Free Software Foundation; either
15  *  version 2 of the License, or (at your option) any later version.
16  *
17  *  This library is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  *  Library General Public License for more details.
21  *
22  *  You should have received a copy of the GNU Library General Public
23  *  License along with this library; if not, write to the Free
24  *  Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  *  MA 02111-1307, USA
26  */
27 #include <config.h>
28
29 #include "db.h"
30
31 #include <glib/gi18n.h>
32 #include <glib/gmem.h>
33 #include <glib/gstrfuncs.h>
34 #include <glib/gdir.h>
35 #include <glib/gmessages.h>
36 #include <glib/ghash.h>
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40
41 #include "libglabels-private.h"
42
43 #include "xml-paper.h"
44 #include "xml-category.h"
45 #include "xml-template.h"
46
47
48 /*===========================================*/
49 /* Private types                             */
50 /*===========================================*/
51
52 /*===========================================*/
53 /* Private globals                           */
54 /*===========================================*/
55
56 static GList *papers     = NULL;
57 static GList *categories = NULL;
58 static GList *templates  = NULL;
59
60 static GHashTable *template_cache = NULL;
61
62 /*===========================================*/
63 /* Local function prototypes                 */
64 /*===========================================*/
65
66 static void   init_template_cache          (void);
67 static void   add_to_template_cache        (lglTemplate *template);
68
69 static GList *read_papers                  (void);
70 static GList *read_paper_files_from_dir    (GList       *papers,
71                                             const gchar *dirname);
72
73 static GList *read_categories              (void);
74 static GList *read_category_files_from_dir (GList       *categories,
75                                             const gchar *dirname);
76
77 static GList *read_templates               (void);
78 static GList *read_template_files_from_dir (GList       *templates,
79                                             const gchar *dirname);
80
81 static lglTemplate *template_full_page     (const gchar *page_size);
82
83
84
85 /*===========================================*/
86 /* Module initialization                     */
87 /*===========================================*/
88
89 /**
90  * lgl_db_init:
91  *
92  * Initialize all libglabels subsystems.  It is not necessary for an application to call
93  * lgl_db_init(), because libglabels will initialize on demand.  An application programmer may
94  * choose to call lgl_db_init() at startup to minimize the impact of the first libglabels call
95  * on GUI response time.
96  *
97  * This function initializes its paper definitions, category definitions, and its template
98  * database.. It will search both system and user template directories to locate
99  * this data.
100  */
101 void
102 lgl_db_init (void)
103 {
104         lglPaper    *paper_other;
105         lglCategory *category_user_defined;
106         GList       *page_sizes;
107         GList       *p;
108
109         /*
110          * Paper definitions
111          */
112         if (!papers)
113         {
114
115                 papers = read_papers ();
116
117                 /* Create and append an "Other" entry. */
118                 paper_other = lgl_paper_new ("Other", _("Other"), 0.0, 0.0, NULL);
119                 papers = g_list_append (papers, paper_other);
120
121         }
122
123         /*
124          * Categories
125          */
126         if (!categories)
127         {
128                 categories = read_categories ();
129
130                 /* Create and append a "User defined" entry. */
131                 category_user_defined = lgl_category_new ("user-defined", _("User defined"));
132                 categories = g_list_append (categories, category_user_defined);
133         }
134
135         /*
136          * Templates
137          */
138         if (!templates)
139         {
140
141                 templates = read_templates ();
142
143                 /* Create and append generic full page templates. */
144                 page_sizes = lgl_db_get_paper_id_list ();
145                 for ( p=page_sizes; p != NULL; p=p->next )
146                 {
147                         if ( !lgl_db_is_paper_id_other (p->data) )
148                         {
149                                 templates = g_list_append (templates,
150                                                            template_full_page (p->data));
151                         }
152                 }
153                 lgl_db_free_paper_id_list (page_sizes);
154
155                 init_template_cache ();
156         }
157 }
158
159
160
161 /*===========================================*/
162 /* Paper db functions.                       */
163 /*===========================================*/
164
165 /**
166  * lgl_db_get_paper_id_list:
167  *
168  * Get a list of all paper ids known to libglabels.
169  *
170  * Returns: a list of paper ids.
171  *
172  */
173 GList *
174 lgl_db_get_paper_id_list (void)
175 {
176         GList           *ids = NULL;
177         GList           *p;
178         lglPaper        *paper;
179
180         if (!papers)
181         {
182                 lgl_db_init ();
183         }
184
185         for ( p=papers; p != NULL; p=p->next )
186         {
187                 paper = (lglPaper *)p->data;
188                 ids = g_list_append (ids, g_strdup (paper->id));
189         }
190
191         return ids;
192 }
193
194
195 /**
196  * lgl_db_free_paper_id_list:
197  * @ids: List of id strings to be freed.
198  *
199  * Free up all storage associated with an id list obtained with
200  * lgl_db_get_paper_id_list().
201  *
202  */
203 void
204 lgl_db_free_paper_id_list (GList *ids)
205 {
206         GList *p;
207
208         for (p = ids; p != NULL; p = p->next)
209         {
210                 g_free (p->data);
211                 p->data = NULL;
212         }
213
214         g_list_free (ids);
215 }
216
217
218 /**
219  * lgl_db_get_paper_name_list:
220  *
221  * Get a list of all localized paper names known to libglabels.
222  *
223  * Returns: a list of localized paper names.
224  *
225  */
226 GList *
227 lgl_db_get_paper_name_list (void)
228 {
229         GList           *names = NULL;
230         GList           *p;
231         lglPaper        *paper;
232
233         if (!papers)
234         {
235                 lgl_db_init ();
236         }
237
238         for ( p=papers; p != NULL; p=p->next )
239         {
240                 paper = (lglPaper *)p->data;
241                 names = g_list_append (names, g_strdup (paper->name));
242         }
243
244         return names;
245 }
246
247
248 /**
249  * lgl_db_free_paper_name_list:
250  * @names: List of localized paper name strings to be freed.
251  *
252  * Free up all storage associated with a name list obtained with
253  * lgl_db_get_paper_name_list().
254  *
255  */
256 void
257 lgl_db_free_paper_name_list (GList *names)
258 {
259         GList *p;
260
261         for (p = names; p != NULL; p = p->next)
262         {
263                 g_free (p->data);
264                 p->data = NULL;
265         }
266
267         g_list_free (names);
268 }
269
270
271 /**
272  * lgl_db_lookup_paper_from_name:
273  * @name: localized paper name string
274  *
275  * Lookup paper definition from localized paper name string.
276  *
277  * Returns: pointer to a newly allocated #lglPaper structure.
278  *
279  */
280 lglPaper *
281 lgl_db_lookup_paper_from_name (const gchar *name)
282 {
283         GList       *p;
284         lglPaper    *paper;
285
286         if (!papers)
287         {
288                 lgl_db_init ();
289         }
290
291         if (name == NULL)
292         {
293                 /* If no name, return first paper as a default */
294                 return lgl_paper_dup ((lglPaper *) papers->data);
295         }
296
297         for (p = papers; p != NULL; p = p->next)
298         {
299                 paper = (lglPaper *) p->data;
300                 if (UTF8_EQUAL (paper->name, name))
301                 {
302                         return lgl_paper_dup (paper);
303                 }
304         }
305
306         return NULL;
307 }
308
309
310 /**
311  * lgl_db_lookup_paper_from_id:
312  * @id: paper id string
313  *
314  * Lookup paper definition from id string.
315  *
316  * Returns: pointer to a newly allocated #lglPaper structure.
317  *
318  */
319 lglPaper *
320 lgl_db_lookup_paper_from_id (const gchar *id)
321 {
322         GList       *p;
323         lglPaper    *paper;
324
325         if (!papers)
326         {
327                 lgl_db_init ();
328         }
329
330         if (id == NULL)
331         {
332                 /* If no id, return first paper as a default */
333                 return lgl_paper_dup ((lglPaper *) papers->data);
334         }
335
336         for (p = papers; p != NULL; p = p->next)
337         {
338                 paper = (lglPaper *) p->data;
339                 if (ASCII_EQUAL (paper->id, id))
340                 {
341                         return lgl_paper_dup (paper);
342                 }
343         }
344
345         return NULL;
346 }
347
348
349 /**
350  * lgl_db_lookup_paper_id_from_name:
351  * @name: localized paper name stringp
352  *
353  * Lookup paper name string from localized paper name string.
354  *
355  * Returns: pointer to a newly allocated id string.
356  *
357  */
358 gchar *
359 lgl_db_lookup_paper_id_from_name (const gchar *name)
360 {
361         lglPaper *paper = NULL;
362         gchar    *id = NULL;
363
364         if (name != NULL)
365         {
366                 paper = lgl_db_lookup_paper_from_name (name);
367                 if ( paper != NULL )
368                 {
369                         id = g_strdup (paper->id);
370                         lgl_paper_free (paper);
371                         paper = NULL;
372                 }
373         }
374
375         return id;
376 }
377
378
379 /**
380  * lgl_db_lookup_paper_name_from_id:
381  * @id: paper id string
382  *
383  * Lookup localized paper name string from paper id string.
384  *
385  * Returns: pointer to a newly allocated localized paper name string.
386  *
387  */
388 gchar *
389 lgl_db_lookup_paper_name_from_id (const gchar         *id)
390 {
391         lglPaper *paper = NULL;
392         gchar    *name = NULL;
393
394         if (id != NULL)
395         {
396                 paper = lgl_db_lookup_paper_from_id (id);
397                 if ( paper != NULL )
398                 {
399                         name = g_strdup (paper->name);
400                         lgl_paper_free (paper);
401                         paper = NULL;
402                 }
403         }
404
405         return name;
406 }
407
408
409 /**
410  * lgl_db_is_paper_id_known:
411  * @id: paper id to test
412  *
413  * Determine if given paper id is known to libglabels.
414  *
415  * Returns: TRUE if id is known, otherwise FALSE.
416  *
417  */
418 gboolean
419 lgl_db_is_paper_id_known (const gchar *id)
420 {
421         GList       *p;
422         lglPaper    *paper;
423
424         if (!papers)
425         {
426                 lgl_db_init ();
427         }
428
429         if (id == NULL)
430         {
431                 return FALSE;
432         }
433
434         for (p = papers; p != NULL; p = p->next)
435         {
436                 paper = (lglPaper *) p->data;
437                 if (ASCII_EQUAL (paper->id, id))
438                 {
439                         return TRUE;
440                 }
441         }
442
443         return FALSE;
444 }
445
446 /**
447  * lgl_db_is_paper_id_other:
448  * @id: paper id to test
449  *
450  * Determine if given paper id is the special id "Other."
451  *
452  * Returns: TRUE if id is "Other", otherwise FALSE.
453  *
454  */
455 gboolean
456 lgl_db_is_paper_id_other (const gchar *id)
457 {
458         if (id == NULL)
459         {
460                 return FALSE;
461         }
462
463         return (ASCII_EQUAL (id, "Other"));
464 }
465
466
467 static GList *
468 read_papers (void)
469 {
470         gchar *data_dir;
471         GList *papers = NULL;
472
473         data_dir = LGL_SYSTEM_DATA_DIR;
474         papers = read_paper_files_from_dir (papers, data_dir);
475         g_free (data_dir);
476
477         data_dir = LGL_USER_DATA_DIR;
478         papers = read_paper_files_from_dir (papers, data_dir);
479         g_free (data_dir);
480
481         if (papers == NULL) {
482                 g_critical (_("Unable to locate paper size definitions.  Libglabels may not be installed correctly!"));
483         }
484
485         return papers;
486 }
487
488
489 static GList *
490 read_paper_files_from_dir (GList       *papers,
491                            const gchar *dirname)
492 {
493         GDir        *dp;
494         const gchar *filename, *extension;
495         gchar       *full_filename = NULL;
496         GError      *gerror = NULL;
497         GList       *new_papers = NULL;
498
499         if (dirname == NULL) {
500                 return papers;
501         }
502
503         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
504                 return papers;
505         }
506
507         dp = g_dir_open (dirname, 0, &gerror);
508         if (gerror != NULL) {
509                 g_message ("cannot open data directory: %s", gerror->message );
510                 return papers;
511         }
512
513         while ((filename = g_dir_read_name (dp)) != NULL) {
514
515                 extension = strrchr (filename, '.');
516
517                 if (extension != NULL) {
518
519                         if ( ASCII_EQUAL (extension, ".paper") ||
520                              ASCII_EQUAL (filename, "paper-sizes.xml") )
521                         {
522
523                                 full_filename =
524                                     g_build_filename (dirname, filename, NULL);
525                                 new_papers =
526                                     lgl_xml_paper_read_papers_from_file (full_filename);
527                                 g_free (full_filename);
528
529                                 papers = g_list_concat (papers, new_papers);
530                                 new_papers = NULL;
531
532                         }
533
534                 }
535
536         }
537
538         g_dir_close (dp);
539
540         return papers;
541 }
542
543
544 /**
545  * lgl_db_print_known_papers:
546  *
547  * For debugging purposes: print a list of all paper definitions known to
548  * libglabels.
549  *
550  */
551 void
552 lgl_db_print_known_papers (void)
553 {
554         GList       *p;
555         lglPaper    *paper;
556
557         if (!papers) {
558                 lgl_db_init ();
559         }
560
561         g_print ("%s():\n", __FUNCTION__);
562         for (p = papers; p != NULL; p = p->next) {
563                 paper = (lglPaper *) p->data;
564
565                 g_print ("PAPER id=\"%s\", name=\"%s\", width=%gpts, height=%gpts\n",
566                          paper->id, paper->name, paper->width, paper->height);
567
568         }
569         g_print ("\n");
570
571 }
572
573
574 /*===========================================*/
575 /* Category db functions.                    */
576 /*===========================================*/
577
578 /**
579  * lgl_db_get_category_id_list:
580  *
581  * Get a list of all category ids known to libglabels.
582  *
583  * Returns: a list of category ids.
584  *
585  */
586 GList *
587 lgl_db_get_category_id_list (void)
588 {
589         GList           *ids = NULL;
590         GList           *p;
591         lglCategory     *category;
592
593         if (!categories)
594         {
595                 lgl_db_init ();
596         }
597
598         for ( p=categories; p != NULL; p=p->next )
599         {
600                 category = (lglCategory *)p->data;
601                 ids = g_list_append (ids, g_strdup (category->id));
602         }
603
604         return ids;
605 }
606
607
608 /**
609  * lgl_db_free_category_id_list:
610  * @ids: List of id strings to be freed.
611  *
612  * Free up all storage associated with an id list obtained with
613  * lgl_db_get_category_id_list().
614  *
615  */
616 void
617 lgl_db_free_category_id_list (GList *ids)
618 {
619         GList *p;
620
621         for (p = ids; p != NULL; p = p->next)
622         {
623                 g_free (p->data);
624                 p->data = NULL;
625         }
626
627         g_list_free (ids);
628 }
629
630
631 /**
632  * lgl_db_get_category_name_list:
633  *
634  * Get a list of all localized category names known to libglabels.
635  *
636  * Returns: a list of localized category names.
637  *
638  */
639 GList *
640 lgl_db_get_category_name_list (void)
641 {
642         GList           *names = NULL;
643         GList           *p;
644         lglCategory     *category;
645
646         if (!categories)
647         {
648                 lgl_db_init ();
649         }
650
651         for ( p=categories; p != NULL; p=p->next )
652         {
653                 category = (lglCategory *)p->data;
654                 names = g_list_append (names, g_strdup (category->name));
655         }
656
657         return names;
658 }
659
660
661 /**
662  * lgl_db_free_category_name_list:
663  * @names: List of localized category name strings to be freed.
664  *
665  * Free up all storage associated with a name list obtained with
666  * lgl_db_get_category_name_list().
667  *
668  */
669 void
670 lgl_db_free_category_name_list (GList *names)
671 {
672         GList *p;
673
674         for (p = names; p != NULL; p = p->next)
675         {
676                 g_free (p->data);
677                 p->data = NULL;
678         }
679
680         g_list_free (names);
681 }
682
683
684 /**
685  * lgl_db_lookup_category_from_name:
686  * @name: localized category name string
687  *
688  * Lookup category definition from localized category name string.
689  *
690  * Returns: pointer to a newly allocated #lglCategory structure.
691  *
692  */
693 lglCategory *
694 lgl_db_lookup_category_from_name (const gchar *name)
695 {
696         GList       *p;
697         lglCategory *category;
698
699         if (!categories)
700         {
701                 lgl_db_init ();
702         }
703
704         if (name == NULL)
705         {
706                 /* If no name, return first category as a default */
707                 return lgl_category_dup ((lglCategory *) categories->data);
708         }
709
710         for (p = categories; p != NULL; p = p->next)
711         {
712                 category = (lglCategory *) p->data;
713                 if (UTF8_EQUAL (category->name, name))
714                 {
715                         return lgl_category_dup (category);
716                 }
717         }
718
719         return NULL;
720 }
721
722
723 /**
724  * lgl_db_lookup_category_from_id:
725  * @id: category id string
726  *
727  * Lookup category definition from id string.
728  *
729  * Returns: pointer to a newly allocated #lglCategory structure.
730  *
731  */
732 lglCategory *
733 lgl_db_lookup_category_from_id (const gchar *id)
734 {
735         GList       *p;
736         lglCategory *category;
737
738         if (!categories)
739         {
740                 lgl_db_init ();
741         }
742
743         if (id == NULL)
744         {
745                 /* If no id, return first category as a default */
746                 return lgl_category_dup ((lglCategory *) categories->data);
747         }
748
749         for (p = categories; p != NULL; p = p->next)
750         {
751                 category = (lglCategory *) p->data;
752                 if (ASCII_EQUAL (category->id, id))
753                 {
754                         return lgl_category_dup (category);
755                 }
756         }
757
758         return NULL;
759 }
760
761
762 /**
763  * lgl_db_lookup_category_id_from_name:
764  * @name: localized category name stringp
765  *
766  * Lookup category name string from localized category name string.
767  *
768  * Returns: pointer to a newly allocated id string.
769  *
770  */
771 gchar *
772 lgl_db_lookup_category_id_from_name (const gchar *name)
773 {
774         lglCategory *category = NULL;
775         gchar       *id = NULL;
776
777         if (name != NULL)
778         {
779                 category = lgl_db_lookup_category_from_name (name);
780                 if ( category != NULL )
781                 {
782                         id = g_strdup (category->id);
783                         lgl_category_free (category);
784                         category = NULL;
785                 }
786         }
787
788         return id;
789 }
790
791
792 /**
793  * lgl_db_lookup_category_name_from_id:
794  * @id: category id string
795  *
796  * Lookup localized category name string from category id string.
797  *
798  * Returns: pointer to a newly allocated localized category name string.
799  *
800  */
801 gchar *
802 lgl_db_lookup_category_name_from_id (const gchar         *id)
803 {
804         lglCategory *category = NULL;
805         gchar       *name = NULL;
806
807         if (id != NULL)
808         {
809                 category = lgl_db_lookup_category_from_id (id);
810                 if ( category != NULL )
811                 {
812                         name = g_strdup (category->name);
813                         lgl_category_free (category);
814                         category = NULL;
815                 }
816         }
817
818         return name;
819 }
820
821
822 /**
823  * lgl_db_is_category_id_known:
824  * @id: category id to test
825  *
826  * Determine if given category id is known to libglabels.
827  *
828  * Returns: TRUE if id is known, otherwise FALSE.
829  *
830  */
831 gboolean
832 lgl_db_is_category_id_known (const gchar *id)
833 {
834         GList       *p;
835         lglCategory *category;
836
837         if (!categories)
838         {
839                 lgl_db_init ();
840         }
841
842         if (id == NULL)
843         {
844                 return FALSE;
845         }
846
847         for (p = categories; p != NULL; p = p->next)
848         {
849                 category = (lglCategory *) p->data;
850                 if (ASCII_EQUAL (category->id, id))
851                 {
852                         return TRUE;
853                 }
854         }
855
856         return FALSE;
857 }
858
859
860 static GList *
861 read_categories (void)
862 {
863         gchar *data_dir;
864         GList *categories = NULL;
865
866         data_dir = LGL_SYSTEM_DATA_DIR;
867         categories = read_category_files_from_dir (categories, data_dir);
868         g_free (data_dir);
869
870         data_dir = LGL_USER_DATA_DIR;
871         categories = read_category_files_from_dir (categories, data_dir);
872         g_free (data_dir);
873
874         if (categories == NULL) {
875                 g_critical (_("Unable to locate category definitions.  Libglabels may not be installed correctly!"));
876         }
877
878         return categories;
879 }
880
881
882 static GList *
883 read_category_files_from_dir (GList       *categories,
884                               const gchar *dirname)
885 {
886         GDir        *dp;
887         const gchar *filename, *extension;
888         gchar       *full_filename = NULL;
889         GError      *gerror = NULL;
890         GList       *new_categories = NULL;
891
892         if (dirname == NULL) {
893                 return categories;
894         }
895
896         if (!g_file_test (dirname, G_FILE_TEST_EXISTS)) {
897                 return categories;
898         }
899
900         dp = g_dir_open (dirname, 0, &gerror);
901         if (gerror != NULL) {
902                 g_message ("cannot open data directory: %s", gerror->message );
903                 return categories;
904         }
905
906         while ((filename = g_dir_read_name (dp)) != NULL) {
907
908                 extension = strrchr (filename, '.');
909
910                 if (extension != NULL) {
911
912                         if ( ASCII_EQUAL (extension, ".category") ||
913                              ASCII_EQUAL (filename, "categories.xml") )
914                         {
915
916                                 full_filename =
917                                     g_build_filename (dirname, filename, NULL);
918                                 new_categories =
919                                     lgl_xml_category_read_categories_from_file (full_filename);
920                                 g_free (full_filename);
921
922                                 categories = g_list_concat (categories, new_categories);
923                                 new_categories = NULL;
924
925                         }
926
927                 }
928
929         }
930
931         g_dir_close (dp);
932
933         return categories;
934 }
935
936
937 /**
938  * lgl_db_print_known_categories:
939  *
940  * For debugging purposes: print a list of all category definitions known to
941  * libglabels.
942  *
943  */
944 void
945 lgl_db_print_known_categories (void)
946 {
947         GList       *p;
948         lglCategory *category;
949
950         if (!categories) {
951                 lgl_db_init ();
952         }
953
954         g_print ("%s():\n", __FUNCTION__);
955         for (p = categories; p != NULL; p = p->next) {
956                 category = (lglCategory *) p->data;
957
958                 g_print ("CATEGORY id=\"%s\", name=\"%s\"\n", category->id, category->name);
959
960         }
961         g_print ("\n");
962
963 }
964
965
966
967 /*===========================================*/
968 /* Brand db functions.                       */
969 /*===========================================*/
970
971 /**
972  * lgl_db_get_brand_list:
973  * @paper_id: If non NULL, limit results to given page size.
974  * @category_id: If non NULL, limit results to given template category.
975  *
976  * Get a list of all valid brands of templates in the template database.
977  * Results can be filtered by page size and/or template category.  A list of valid page
978  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
979  * categories can be obtained using lgl_db_get_category_id_list().
980  *
981  * Returns: a list of brands
982  */
983 GList *
984 lgl_db_get_brand_list (const gchar *paper_id,
985                        const gchar *category_id)
986 {
987         GList            *p_tmplt, *p_alias;
988         lglTemplate      *template;
989         lglTemplateAlias *alias;
990         GList            *brands = NULL;
991
992         if (!templates)
993         {
994                 lgl_db_init ();
995         }
996
997         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
998         {
999                 template = (lglTemplate *) p_tmplt->data;
1000                 if (lgl_template_does_page_size_match (template, paper_id) &&
1001                     lgl_template_does_category_match (template, category_id))
1002                 {
1003                         for (p_alias = template->aliases; p_alias != NULL;
1004                              p_alias = p_alias->next)
1005                         {
1006                                 alias = (lglTemplateAlias *)p_alias->data;
1007
1008                                 if ( !g_list_find_custom (brands, alias->brand,
1009                                                           (GCompareFunc)lgl_str_utf8_casecmp) )
1010                                 {
1011                                         brands = g_list_insert_sorted (brands,
1012                                                                        g_strdup (alias->brand),
1013                                                                        (GCompareFunc)lgl_str_utf8_casecmp);
1014                                 }
1015                         }
1016                 }
1017         }
1018
1019         return brands;
1020 }
1021
1022
1023 /**
1024  * lgl_db_free_brand_list:
1025  * @brands: List of template brand strings to be freed.
1026  *
1027  * Free up all storage associated with a list of template names obtained with
1028  * lgl_db_get_brand_list().
1029  *
1030  */
1031 void
1032 lgl_db_free_brand_list (GList *brands)
1033 {
1034         GList *p_brand;
1035
1036         for (p_brand = brands; p_brand != NULL; p_brand = p_brand->next)
1037         {
1038                 g_free (p_brand->data);
1039                 p_brand->data = NULL;
1040         }
1041
1042         g_list_free (brands);
1043 }
1044
1045
1046
1047 /*===========================================*/
1048 /* Template db functions.                    */
1049 /*===========================================*/
1050
1051 /**
1052  * lgl_db_register_template:
1053  * @template:  Pointer to a template structure to add to database.
1054  *
1055  * Register a template.  This function adds a template to the template database.
1056  * The template will be stored in an individual XML file in the user template directory.
1057  *
1058  * Returns: Status of registration attempt (#lglDbRegStatus)
1059  */
1060 lglDbRegStatus
1061 lgl_db_register_template (const lglTemplate *template)
1062 {
1063         lglTemplate *template_copy;
1064         gchar       *dir, *filename, *abs_filename;
1065         gint         bytes_written;
1066
1067         if (!templates)
1068         {
1069                 lgl_db_init ();
1070         }
1071
1072         if (lgl_db_does_template_exist (template->brand, template->part))
1073         {
1074                 return LGL_DB_REG_BRAND_PART_EXISTS;
1075         }
1076
1077         if (lgl_db_is_paper_id_known (template->paper_id))
1078         {
1079                 dir = LGL_USER_DATA_DIR;
1080                 mkdir (dir, 0775); /* Try to make sure directory exists. */
1081                 filename = g_strdup_printf ("%s_%s.template", template->brand, template->part);
1082                 abs_filename = g_build_filename (dir, filename, NULL);
1083                 bytes_written = lgl_xml_template_write_template_to_file (template, abs_filename);
1084                 g_free (dir);
1085                 g_free (filename);
1086                 g_free (abs_filename);
1087
1088                 if (bytes_written > 0)
1089                 {
1090                         template_copy = lgl_template_dup (template);
1091                         lgl_template_add_category (template_copy, "user-defined");
1092                         templates = g_list_append (templates, template_copy);
1093                         add_to_template_cache (template_copy);
1094                         return LGL_DB_REG_OK;
1095                 }
1096                 else
1097                 {
1098                         return LGL_DB_REG_FILE_WRITE_ERROR;
1099                 }
1100         }
1101         else
1102         {
1103                 g_message ("Cannot register new template with unknown page size.");
1104                 return LGL_DB_REG_BAD_PAPER_ID;
1105         }
1106
1107 }
1108
1109
1110 /**
1111  * lgl_db_does_template_exist:
1112  * @brand: Brand name.
1113  * @part:  Part name/number.
1114  *
1115  * This function tests whether a template with the given brand and part name/number exists.
1116  *
1117  * Returns:  TRUE if such a template exists in the database.
1118  */
1119 gboolean
1120 lgl_db_does_template_exist (const gchar *brand,
1121                             const gchar *part)
1122 {
1123         GList            *p_tmplt, *p_alias;
1124         lglTemplate      *template;
1125         lglTemplateAlias *alias;
1126
1127         if (!templates)
1128         {
1129                 lgl_db_init ();
1130         }
1131
1132         if ((brand == NULL) || (part == NULL))
1133         {
1134                 return FALSE;
1135         }
1136
1137         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1138         {
1139                 template = (lglTemplate *) p_tmplt->data;
1140                 for (p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next)
1141                 {
1142                         alias = (lglTemplateAlias *)p_alias->data;
1143
1144                         if ( UTF8_EQUAL (brand, alias->brand) &&
1145                              UTF8_EQUAL (part, alias->part) )
1146                         {
1147                                 return TRUE;
1148                         }
1149                 }
1150         }
1151
1152         return FALSE;
1153 }
1154
1155
1156 /**
1157  * lgl_db_does_template_name_exist:
1158  * @name: name string
1159  *
1160  * This function test whether a template with the given name exists.
1161  *
1162  * Returns: TRUE if such a template exists in the database.
1163  *
1164  */
1165 gboolean
1166 lgl_db_does_template_name_exist (const gchar *name)
1167 {
1168         GList            *p_tmplt, *p_alias;
1169         lglTemplate      *template;
1170         lglTemplateAlias *alias;
1171         gchar            *candidate_name;
1172
1173         if (!templates)
1174         {
1175                 lgl_db_init ();
1176         }
1177
1178         if (name == NULL)
1179         {
1180                 return FALSE;
1181         }
1182
1183         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1184         {
1185                 template = (lglTemplate *) p_tmplt->data;
1186                 for (p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next)
1187                 {
1188                         alias = (lglTemplateAlias *)p_alias->data;
1189                         candidate_name = g_strdup_printf ("%s %s", alias->brand, alias->part);
1190
1191                         if ( UTF8_EQUAL (candidate_name, name) ) {
1192                                 g_free (candidate_name);
1193                                 return TRUE;
1194                         }
1195                         g_free (candidate_name);
1196                 }
1197         }
1198
1199         return FALSE;
1200 }
1201
1202
1203 /**
1204  * lgl_db_get_template_name_list_unique:
1205  * @brand:     If non NULL, limit results to given brand
1206  * @paper_id: If non NULL, limit results to given page size.
1207  * @category_id: If non NULL, limit results to given template category.
1208  *
1209  * Get a list of valid names of unique templates in the template database.  Results
1210  * can be filtered by page size and/or template category.  A list of valid page sizes
1211  * can be obtained using lgl_db_get_paper_id_list().  A list of valid template categories
1212  * can be obtained using lgl_db_get_category_id_list().
1213  *
1214  * This function differs from lgl_db_get_template_name_list_all(), because it does not
1215  * return multiple names for the same template.
1216  *
1217  * Returns: a list of template names.
1218  */
1219 GList *
1220 lgl_db_get_template_name_list_unique (const gchar *brand,
1221                                       const gchar *paper_id,
1222                                       const gchar *category_id)
1223 {
1224         GList       *p_tmplt;
1225         lglTemplate *template;
1226         gchar       *name;
1227         GList       *names = NULL;
1228
1229         if (!templates)
1230         {
1231                 lgl_db_init ();
1232         }
1233
1234         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1235         {
1236                 template = (lglTemplate *) p_tmplt->data;
1237
1238                 if (lgl_template_does_brand_match (template, brand) &&
1239                     lgl_template_does_page_size_match (template, paper_id) &&
1240                     lgl_template_does_category_match (template, category_id))
1241                 {
1242                         name = g_strdup_printf ("%s %s", template->brand, template->part);
1243                         names = g_list_insert_sorted (names, name,
1244                                                       (GCompareFunc)g_utf8_collate);
1245                 }
1246         }
1247
1248         return names;
1249 }
1250
1251
1252 /**
1253  * lgl_db_get_template_name_list_all:
1254  * @brand:     If non NULL, limit results to given brand
1255  * @paper_id: If non NULL, limit results to given page size.
1256  * @category_id: If non NULL, limit results to given template category.
1257  *
1258  * Get a list of all valid names and aliases of templates in the template database.
1259  * Results can be filtered by page size and/or template category.  A list of valid page
1260  * sizes can be obtained using lgl_db_get_paper_id_list().  A list of valid template
1261  * categories can be obtained using lgl_db_get_category_id_list().
1262  *
1263  * This function differs from lgl_db_get_template_name_list_unique(), because it will
1264  * return multiple names for the same template.
1265  *
1266  * Returns: a list of template names and aliases.
1267  */
1268 GList *
1269 lgl_db_get_template_name_list_all (const gchar *brand,
1270                                    const gchar *paper_id,
1271                                    const gchar *category_id)
1272 {
1273         GList            *p_tmplt, *p_alias;
1274         lglTemplate      *template;
1275         lglTemplateAlias *alias;
1276         gchar            *name;
1277         GList            *names = NULL;
1278
1279         if (!templates)
1280         {
1281                 lgl_db_init ();
1282         }
1283
1284         for (p_tmplt = templates; p_tmplt != NULL; p_tmplt = p_tmplt->next)
1285         {
1286                 template = (lglTemplate *) p_tmplt->data;
1287                 if (lgl_template_does_page_size_match (template, paper_id) &&
1288                     lgl_template_does_category_match (template, category_id))
1289                 {
1290                         for (p_alias = template->aliases; p_alias != NULL;
1291                              p_alias = p_alias->next)
1292                         {
1293                                 alias = (lglTemplateAlias *)p_alias->data;
1294
1295                                 if ( !brand || UTF8_EQUAL( alias->brand, brand) )
1296                                 {
1297                                         name = g_strdup_printf ("%s %s", alias->brand, alias->part);
1298                                         names = g_list_insert_sorted (names, name,
1299                                                                       (GCompareFunc)g_utf8_collate);
1300                                 }
1301                         }
1302                 }
1303         }
1304
1305         return names;
1306 }
1307
1308
1309 /**
1310  * lgl_db_free_template_name_list:
1311  * @names: List of template name strings to be freed.
1312  *
1313  * Free up all storage associated with a list of template names obtained with
1314  * lgl_db_get_template_name_list_all() or lgl_db_get_template_name_list_unique().
1315  *
1316  */
1317 void
1318 lgl_db_free_template_name_list (GList *names)
1319 {
1320         GList *p_name;
1321
1322         for (p_name = names; p_name != NULL; p_name = p_name->next)
1323         {
1324                 g_free (p_name->data);
1325                 p_name->data = NULL;
1326         }
1327
1328         g_list_free (names);
1329 }
1330
1331
1332 /**
1333  * lgl_db_lookup_template_from_name:
1334  * @name: name string
1335  *
1336  * Lookup template in template database from name string.
1337  *
1338  * Returns: pointer to a newly allocated #lglTemplate structure.
1339  *
1340  */
1341 lglTemplate *
1342 lgl_db_lookup_template_from_name (const gchar *name)
1343 {
1344         GList            *p_alias;
1345         lglTemplate      *template;
1346         lglTemplateAlias *alias;
1347         gchar            *candidate_name;
1348         lglTemplate      *new_template;
1349
1350         if (!templates)
1351         {
1352                 lgl_db_init ();
1353         }
1354
1355         if (name == NULL)
1356         {
1357                 /* If no name, return first template as a default */
1358                 return lgl_template_dup ((lglTemplate *) templates->data);
1359         }
1360
1361         template = g_hash_table_lookup (template_cache, name);
1362
1363         if (template)
1364         {
1365                 for (p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next)
1366                 {
1367                         alias = (lglTemplateAlias *)p_alias->data;
1368                         candidate_name = g_strdup_printf ("%s %s", alias->brand, alias->part);
1369
1370                         if ( UTF8_EQUAL (candidate_name, name) )
1371                         {
1372                                 g_free (candidate_name);
1373                                 new_template = lgl_template_dup (template);
1374                                 g_free (new_template->brand);
1375                                 new_template->brand = g_strdup (alias->brand);
1376                                 g_free (new_template->part);
1377                                 new_template->part = g_strdup (alias->part);
1378                                 return new_template;
1379                         }
1380
1381                         g_free (candidate_name);
1382                 }
1383         }
1384
1385         /* No matching template has been found so return the first template */
1386         return lgl_template_dup ((lglTemplate *) templates->data);
1387 }
1388
1389
1390 static void
1391 init_template_cache (void)
1392 {
1393         GList            *p_tmplt, *p_alias;
1394         lglTemplate      *template;
1395         lglTemplateAlias *alias;
1396         gchar            *name;
1397
1398         template_cache = g_hash_table_new (g_str_hash, g_str_equal);
1399
1400         for ( p_tmplt=templates; p_tmplt != NULL; p_tmplt=p_tmplt->next )
1401         {
1402                 template = (lglTemplate *) p_tmplt->data;
1403
1404                 for ( p_alias=template->aliases; p_alias != NULL; p_alias=p_alias->next )
1405                 {
1406                         alias = (lglTemplateAlias *)p_alias->data;
1407                         name = g_strdup_printf ("%s %s", alias->brand, alias->part);
1408
1409                         g_hash_table_insert (template_cache, name, template);
1410                 }
1411         }
1412 }
1413
1414
1415 static void
1416 add_to_template_cache (lglTemplate *template)
1417 {
1418         GList            *p_alias;
1419         lglTemplateAlias *alias;
1420         gchar            *name;
1421
1422         for ( p_alias=template->aliases; p_alias != NULL; p_alias=p_alias->next )
1423         {
1424                 alias = (lglTemplateAlias *)p_alias->data;
1425                 name = g_strdup_printf ("%s %s", alias->brand, alias->part);
1426
1427                 g_hash_table_insert (template_cache, name, template);
1428         }
1429 }
1430
1431
1432 static GList *
1433 read_templates (void)
1434 {
1435         gchar       *data_dir;
1436         GList       *templates = NULL;
1437         GList       *p;
1438         lglTemplate *template;
1439
1440         /*
1441          * User defined templates.  Add to user-defined category.
1442          */
1443         data_dir = LGL_USER_DATA_DIR;
1444         templates = read_template_files_from_dir (templates, data_dir);
1445         g_free (data_dir);
1446         for ( p=templates; p != NULL; p=p->next )
1447         {
1448                 template = (lglTemplate *)p->data;
1449                 lgl_template_add_category (template, "user-defined");
1450         }
1451
1452         /*
1453          * System templates.
1454          */
1455         data_dir = LGL_SYSTEM_DATA_DIR;
1456         templates = read_template_files_from_dir (templates, data_dir);
1457         g_free (data_dir);
1458
1459         if (templates == NULL)
1460         {
1461                 g_critical (_("Unable to locate any template files.  Libglabels may not be installed correctly!"));
1462         }
1463
1464         return templates;
1465 }
1466
1467
1468 static GList *
1469 read_template_files_from_dir (GList       *templates,
1470                               const gchar *dirname)
1471 {
1472         GDir        *dp;
1473         const gchar *filename, *extension, *extension2;
1474         gchar       *full_filename = NULL;
1475         GError      *gerror = NULL;
1476         GList       *new_templates = NULL;
1477
1478         if (dirname == NULL)
1479                 return templates;
1480
1481         if (!g_file_test (dirname, G_FILE_TEST_EXISTS))
1482         {
1483                 return templates;
1484         }
1485
1486         dp = g_dir_open (dirname, 0, &gerror);
1487         if (gerror != NULL)
1488         {
1489                 g_message ("cannot open data directory: %s", gerror->message );
1490                 return templates;
1491         }
1492
1493         while ((filename = g_dir_read_name (dp)) != NULL)
1494         {
1495
1496                 extension = strrchr (filename, '.');
1497                 extension2 = strrchr (filename, '-');
1498
1499                 if ( (extension && ASCII_EQUAL (extension, ".template")) ||
1500                      (extension2 && ASCII_EQUAL (extension2, "-templates.xml")) )
1501                 {
1502
1503                         full_filename = g_build_filename (dirname, filename, NULL);
1504                         new_templates =
1505                                 lgl_xml_template_read_templates_from_file (full_filename);
1506                         g_free (full_filename);
1507
1508                         templates = g_list_concat (templates, new_templates);
1509                         new_templates = NULL;
1510                 }
1511
1512         }
1513
1514         g_dir_close (dp);
1515
1516         return templates;
1517 }
1518
1519
1520 static lglTemplate *
1521 template_full_page (const gchar *paper_id)
1522 {
1523         lglPaper              *paper = NULL;
1524         lglTemplate           *template = NULL;
1525         lglTemplateFrame      *frame = NULL;
1526         gchar                 *part;
1527         gchar                 *desc;
1528
1529         g_return_val_if_fail (paper_id, NULL);
1530
1531         paper = lgl_db_lookup_paper_from_id (paper_id);
1532         if ( paper == NULL )
1533         {
1534                 return NULL;
1535         }
1536
1537         part = g_strdup_printf ("%s-Full-Page", paper->id);
1538         desc = g_strdup_printf (_("Generic %s full page template"), paper->name);
1539
1540         template = lgl_template_new ("Generic", part, desc,
1541                                      paper_id, paper->width, paper->height);
1542
1543
1544         frame = lgl_template_frame_rect_new ("0",
1545                                              paper->width,
1546                                              paper->height,
1547                                              0.0,
1548                                              0.0,
1549                                              0.0);
1550         lgl_template_add_frame (template, frame);
1551
1552         lgl_template_frame_add_layout (frame, lgl_template_layout_new (1, 1, 0., 0., 0., 0.));
1553
1554         lgl_template_frame_add_markup (frame, lgl_template_markup_margin_new (9.0));
1555
1556         g_free (desc);
1557         desc = NULL;
1558         lgl_paper_free (paper);
1559         paper = NULL;
1560
1561         return template;
1562 }
1563
1564
1565 /**
1566  * lgl_db_print_known_templates:
1567  *
1568  * Print all known templates (for debugging purposes).
1569  *
1570  */
1571 void
1572 lgl_db_print_known_templates (void)
1573 {
1574         GList       *p;
1575         lglTemplate *template;
1576
1577         g_print ("%s():\n", __FUNCTION__);
1578         for (p=templates; p!=NULL; p=p->next)
1579         {
1580                 template = (lglTemplate *)p->data;
1581
1582                 g_print("TEMPLATE brand=\"%s\", part=\"%s\", description=\"%s\"\n",
1583                         template->brand, template->part, template->description);
1584
1585         }
1586         g_print ("\n");
1587
1588 }
1589
1590 /**
1591  * lgl_db_print_aliases:
1592  *   @template: template
1593  *
1594  * Print all aliases of a template (for debugging purposes).
1595  *
1596  */
1597 void
1598 lgl_db_print_aliases (const lglTemplate *template)
1599 {
1600         GList            *p;
1601         lglTemplateAlias *alias;
1602
1603         g_print ("%s():\n", __FUNCTION__);
1604         for (p=template->aliases; p!=NULL; p=p->next)
1605         {
1606                 alias = (lglTemplateAlias *)p->data;
1607                 
1608                 g_print("Alias: brand=\"%s\", part=\"%s\"\n", alias->brand, alias->part);
1609
1610         }
1611         g_print ("\n");
1612
1613 }
1614
1615