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