]> git.sur5r.net Git - glabels/blob - libglabels/template.c
Libglabels mods to support reorganization of template database
[glabels] / libglabels / template.c
1 /*
2  *  template.c
3  *  Copyright (C) 2001-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of libglabels.
6  *
7  *  libglabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  libglabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include "template.h"
24
25 #include <glib/gi18n.h>
26 #include <glib.h>
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30
31 #include "libglabels-private.h"
32
33 #include "db.h"
34 #include "paper.h"
35
36 /*===========================================*/
37 /* Private types                             */
38 /*===========================================*/
39
40
41 /*===========================================*/
42 /* Private globals                           */
43 /*===========================================*/
44
45
46 /*===========================================*/
47 /* Local function prototypes                 */
48 /*===========================================*/
49
50 static gint         compare_origins              (gconstpointer           a,
51                                                   gconstpointer           b,
52                                                   gpointer                user_data);
53
54 /*===========================================*/
55 /* Functions.                                */
56 /*===========================================*/
57
58 /**
59  * lgl_template_new:
60  *   @brand:        Template brand
61  *   @part:         Template part name/number
62  *   @description:  Template descriptions
63  *   @paper_id:     Page size id
64  *   @page_width:   Page width in points, set to zero unless paper_id="Other"
65  *   @page_height:  Page height in points, set to zero unless paper_id="Other"
66  *
67  * Create a new template structure, with the given top-level attributes.  The
68  * created template will have no initial aliases, categories, or frames
69  * associated with it.  See lgl_template_add_alias(), lgl_template_add_category(),
70  * and lgl_template_add_frame() to add these.
71  *
72  * Returns: pointer to a newly allocated #lglTemplate structure.
73  *
74  */
75 lglTemplate *
76 lgl_template_new (const gchar         *brand,
77                   const gchar         *part,
78                   const gchar         *description,
79                   const gchar         *paper_id,
80                   gdouble              page_width,
81                   gdouble              page_height)
82 {
83         lglTemplate      *template;
84         lglTemplateAlias *alias;
85
86         template = g_new0 (lglTemplate,1);
87
88         template->brand       = g_strdup (brand);
89         template->part        = g_strdup (part);
90         template->description = g_strdup (description);
91         template->paper_id    = g_strdup (paper_id);
92         template->page_width  = page_width;
93         template->page_height = page_height;
94
95         /* Always include primary name in alias list. */
96         template->aliases = NULL;
97         alias = lgl_template_alias_new (brand, part);
98         lgl_template_add_alias (template, alias);
99
100         return template;
101 }
102
103
104 /**
105  * lgl_template_new_from_equiv:
106  *   @brand:        Template brand
107  *   @part:         Template part name/number
108  *   @equiv_part:   Name of equivalent part to base template on
109  *
110  * Create a new template structure based on an existing template.  The
111  * created template will be a duplicate of the original template, except with
112  * the new part name/number.
113  *
114  * Returns: pointer to a newly allocated #lglTemplate structure.
115  *
116  */
117 lglTemplate *
118 lgl_template_new_from_equiv (const gchar          *brand,
119                              const gchar          *part,
120                              const gchar          *equiv_part)
121 {
122         lglTemplate      *template;
123         GList            *p_alias;
124         lglTemplateAlias *alias;
125
126         template = lgl_db_lookup_template_from_brand_part (brand, equiv_part);
127         if (template)
128         {
129                 g_free (template->part);
130                 g_free (template->equiv_part);
131
132                 template->part       = g_strdup (part);
133                 template->equiv_part = g_strdup (equiv_part);
134
135                 for ( p_alias = template->aliases; p_alias != NULL; p_alias = p_alias->next )
136                 {
137                         alias = (lglTemplateAlias *)p_alias->data;
138                         lgl_template_alias_free (alias);
139                 }
140                 g_list_free (template->aliases);
141                 template->aliases = NULL;
142
143                 alias = lgl_template_alias_new (brand, part);
144                 lgl_template_add_alias (template, alias);
145         }
146         else
147         {
148                 g_message (_("Equivalent part (\"%s\") for \"%s\", not previously defined."),
149                            equiv_part, part);
150         }
151
152         return template;
153 }
154
155
156 /**
157  * lgl_template_get_name:
158  *   @template:  Pointer to template structure to test
159  *
160  * This function returns the name of the given template.  The name is the concetenation
161  * of the brand and part name/number.
162  *
163  * Returns:  A pointer to a newly allocated name string.  Should be freed with g_free().
164  *
165  */
166 gchar *
167 lgl_template_get_name (const lglTemplate  *template)
168 {
169         g_return_val_if_fail (template, NULL);
170
171         return g_strdup_printf ("%s %s", template->brand, template->part);
172 }
173
174
175 /**
176  * lgl_template_do_templates_match:
177  *   @template1:  Pointer to 1st template structure to test
178  *   @template2:  Pointer to 2nd template structure to test
179  *
180  * This function tests if the given templates match.  This is a simple test that only tests
181  * the brand and part name/number. It does not test if they are actually identical.
182  *
183  * Returns:  TRUE if the two template matche.
184  *
185  */
186 gboolean
187 lgl_template_do_templates_match (const lglTemplate  *template1,
188                                  const lglTemplate  *template2)
189 {
190         g_return_val_if_fail (template1, FALSE);
191         g_return_val_if_fail (template2, FALSE);
192
193         return (UTF8_EQUAL (template1->brand, template2->brand) &&
194                 UTF8_EQUAL (template1->part, template2->part));
195 }
196
197
198 /**
199  * lgl_template_does_brand_match:
200  *   @template:  Pointer to template structure to test
201  *   @brand:     Brand string
202  *
203  * This function tests if the brand of the template matches the given brand.
204  *
205  * Returns:  TRUE if the template matches the given brand.
206  *
207  */
208 gboolean
209 lgl_template_does_brand_match (const lglTemplate  *template,
210                                const gchar        *brand)
211 {
212         g_return_val_if_fail (template, FALSE);
213
214         /* NULL matches everything. */
215         if (brand == NULL)
216         {
217                 return TRUE;
218         }
219
220         return UTF8_EQUAL (template->brand, brand);
221 }
222
223
224 /**
225  * lgl_template_does_page_size_match:
226  *   @template:  Pointer to template structure to test
227  *   @paper_id:  Page size ID string
228  *
229  * This function tests if the page size of the template matches the given ID.
230  *
231  * Returns:  TRUE if the template matches the given page size ID.
232  *
233  */
234 gboolean
235 lgl_template_does_page_size_match (const lglTemplate  *template,
236                                    const gchar        *paper_id)
237 {
238         g_return_val_if_fail (template, FALSE);
239
240         /* NULL matches everything. */
241         if (paper_id == NULL)
242         {
243                 return TRUE;
244         }
245
246         return ASCII_EQUAL(paper_id, template->paper_id);
247 }
248
249
250 /**
251  * lgl_template_does_category_match:
252  *   @template:     Pointer to template structure to test
253  *   @category_id:  Category ID string
254  *
255  * This function tests if the given template belongs to the given category ID.
256  *
257  * Returns:  TRUE if the template matches the given category ID.
258  *
259  */
260 gboolean
261 lgl_template_does_category_match  (const lglTemplate  *template,
262                                    const gchar        *category_id)
263 {
264         GList *p;
265
266         g_return_val_if_fail (template, FALSE);
267
268         /* NULL matches everything. */
269         if (category_id == NULL)
270         {
271                 return TRUE;
272         }
273
274         for ( p=template->category_ids; p != NULL; p=p->next )
275         {
276                 if (ASCII_EQUAL(category_id, p->data))
277                 {
278                         return TRUE;
279                 }
280         }
281
282         return FALSE;
283 }
284
285
286 /**
287  * lgl_template_alias_new:
288  *   @brand:        Alias brand
289  *   @part:         Alias part name/number
290  *
291  * Create a new template alias structure, with the given brand and part number.
292  *
293  * Returns: pointer to a newly allocated #lglTemplateAlias structure.
294  *
295  */
296 lglTemplateAlias *
297 lgl_template_alias_new (const gchar         *brand,
298                         const gchar         *part)
299 {
300         lglTemplateAlias *alias;
301
302         alias = g_new0 (lglTemplateAlias,1);
303
304         alias->brand       = g_strdup (brand);
305         alias->part        = g_strdup (part);
306
307         return alias;
308 }
309
310
311 /**
312  * lgl_template_add_alias:
313  *   @template:  Pointer to template structure
314  *   @alias:     Alias string
315  *
316  * This function adds the given alias to a templates list of aliases.
317  *
318  */
319 void
320 lgl_template_add_alias (lglTemplate         *template,
321                         lglTemplateAlias    *alias)
322 {
323         g_return_if_fail (template);
324         g_return_if_fail (alias);
325
326         template->aliases = g_list_append (template->aliases, alias);
327 }
328  
329
330 /**
331  * lgl_template_add_frame:
332  *   @template:  Pointer to template structure
333  *   @frame:     Pointer to frame structure
334  *
335  * This function adds the given frame structure to the template.  Once added,
336  * the frame structure belongs to the given template; do not attempt to free
337  * it.
338  *
339  * Note: Currently glabels only supports a single frame per template.
340  *
341  */
342 void
343 lgl_template_add_frame (lglTemplate      *template,
344                         lglTemplateFrame *frame)
345 {
346         g_return_if_fail (template);
347         g_return_if_fail (frame);
348
349         template->frames = g_list_append (template->frames, frame);
350 }
351
352  
353 /**
354  * lgl_template_add_category:
355  *   @template:     Pointer to template structure
356  *   @category_id:  Category ID string
357  *
358  * This function adds the given category ID to a templates category list.
359  *
360  */
361 void
362 lgl_template_add_category (lglTemplate         *template,
363                            const gchar         *category_id)
364 {
365         g_return_if_fail (template);
366         g_return_if_fail (category_id);
367
368         template->category_ids = g_list_append (template->category_ids,
369                                                 g_strdup (category_id));
370 }
371
372  
373 /**
374  * lgl_template_frame_rect_new:
375  *   @id:      ID of frame.  (This should currently always be "0").
376  *   @w:       width of frame in points.
377  *   @h:       height of frame in points.
378  *   @r:       radius of rounded corners in points.  (Should be 0 for square corners.)
379  *   @x_waste: Amount of overprint to allow in the horizontal direction.
380  *   @y_waste: Amount of overprint to allow in the vertical direction.
381  *
382  * This function creates a new template frame for a rectangular label or card.
383  *
384  * Returns: Pointer to newly allocated #lglTemplateFrame structure.
385  *
386  */
387 lglTemplateFrame *
388 lgl_template_frame_rect_new  (const gchar         *id,
389                               gdouble              w,
390                               gdouble              h,
391                               gdouble              r,
392                               gdouble              x_waste,
393                               gdouble              y_waste)
394 {
395         lglTemplateFrame *frame;
396
397         frame = g_new0 (lglTemplateFrame, 1);
398
399         frame->shape = LGL_TEMPLATE_FRAME_SHAPE_RECT;
400         frame->rect.id = g_strdup (id);
401
402         frame->rect.w = w;
403         frame->rect.h = h;
404         frame->rect.r = r;
405         frame->rect.x_waste = x_waste;
406         frame->rect.y_waste = y_waste;
407
408         return frame;
409 }
410
411
412 /**
413  * lgl_template_frame_round_new:
414  *   @id:      ID of frame.  (This should currently always be "0").
415  *   @r:       radius of label in points.
416  *   @waste:   Amount of overprint to allow.
417  *
418  * This function creates a new template frame for a round label.
419  *
420  * Returns: Pointer to newly allocated #lglTemplateFrame structure.
421  *
422  */
423 lglTemplateFrame *
424 lgl_template_frame_round_new (const gchar         *id,
425                               gdouble              r,
426                               gdouble              waste)
427 {
428         lglTemplateFrame *frame;
429
430         frame = g_new0 (lglTemplateFrame, 1);
431
432         frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ROUND;
433         frame->round.id = g_strdup (id);
434
435         frame->round.r = r;
436         frame->round.waste = waste;
437
438         return frame;
439 }
440
441                                                                                
442 /**
443  * lgl_template_frame_cd_new:
444  *   @id:      ID of frame.  (This should currently always be "0").
445  *   @r1:      outer radius of label in points.
446  *   @r2:      radius of center hole in points.
447  *   @w:       clip width of frame in points for business card CDs.  Should be 0 for no clipping.
448  *   @h:       clip height of frame in points for business card CDs.  Should be 0 for no clipping.
449  *   @waste:   Amount of overprint to allow.
450  *
451  * This function creates a new template frame for a CD/DVD label.
452  *
453  * Returns: Pointer to newly allocated #lglTemplateFrame structure.
454  *
455  */
456 lglTemplateFrame *
457 lgl_template_frame_cd_new (const gchar         *id,
458                            gdouble              r1,
459                            gdouble              r2,
460                            gdouble              w,
461                            gdouble              h,
462                            gdouble              waste)
463 {
464         lglTemplateFrame *frame;
465
466         frame = g_new0 (lglTemplateFrame, 1);
467
468         frame->shape = LGL_TEMPLATE_FRAME_SHAPE_CD;
469         frame->cd.id = g_strdup (id);
470
471         frame->cd.r1 = r1;
472         frame->cd.r2 = r2;
473         frame->cd.w  = w;
474         frame->cd.h  = h;
475         frame->cd.waste = waste;
476
477         return frame;
478 }
479
480
481 /**
482  * lgl_template_frame_get_size:
483  * @frame: #lglTemplateFrame structure to query
484  * @w: pointer to location to receive width of frame
485  * @h: pointer to location to receive height of frame
486  *
487  * Get size (width and height) of given #lglTemplateFrame in points.
488  *
489  */
490 void
491 lgl_template_frame_get_size (const lglTemplateFrame *frame,
492                              gdouble                *w,
493                              gdouble                *h)
494 {
495         g_return_if_fail (frame);
496
497         switch (frame->shape) {
498         case LGL_TEMPLATE_FRAME_SHAPE_RECT:
499                 *w = frame->rect.w;
500                 *h = frame->rect.h;
501                 break;
502         case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
503                 *w = 2.0 * frame->round.r;
504                 *h = 2.0 * frame->round.r;
505                 break;
506         case LGL_TEMPLATE_FRAME_SHAPE_CD:
507                 if (frame->cd.w == 0.0) {
508                         *w = 2.0 * frame->cd.r1;
509                 } else {
510                         *w = frame->cd.w;
511                 }
512                 if (frame->cd.h == 0.0) {
513                         *h = 2.0 * frame->cd.r1;
514                 } else {
515                         *h = frame->cd.h;
516                 }
517                 break;
518         default:
519                 *w = 0.0;
520                 *h = 0.0;
521                 break;
522         }
523 }
524
525
526 /**
527  * lgl_template_frame_get_n_labels:
528  * @frame: #lglTemplateFrame structure to query
529  *
530  * Get total number of labels per sheet corresponding to the given frame.
531  *
532  * Returns: number of labels per sheet.
533  *
534  */
535 gint
536 lgl_template_frame_get_n_labels (const lglTemplateFrame *frame)
537 {
538         gint               n_labels = 0;
539         GList             *p;
540         lglTemplateLayout *layout;
541
542         g_return_val_if_fail (frame, 0);
543
544         for ( p=frame->all.layouts; p != NULL; p=p->next ) {
545                 layout = (lglTemplateLayout *)p->data;
546
547                 n_labels += layout->nx * layout->ny;
548         }
549
550         return n_labels;
551 }
552
553
554 /**
555  * lgl_template_frame_get_origins:
556  * @frame: #lglTemplateFrame structure to query
557  *
558  * Get an array of label origins for the given frame.  These origins represent the
559  * upper left hand corner of each label on a page corresponding to the given frame.
560  * The origins will be ordered geometrically left to right and then top to bottom.
561  * The array should be freed using g_free().
562  *
563  * Returns: A newly allocated array of #lglTemplateOrigin structures.
564  *
565  */
566 lglTemplateOrigin *
567 lgl_template_frame_get_origins (const lglTemplateFrame *frame)
568 {
569         gint               i_label, n_labels, ix, iy;
570         lglTemplateOrigin *origins;
571         GList             *p;
572         lglTemplateLayout *layout;
573
574         g_return_val_if_fail (frame, NULL);
575
576         n_labels = lgl_template_frame_get_n_labels (frame);
577         origins = g_new0 (lglTemplateOrigin, n_labels);
578
579         i_label = 0;
580         for ( p=frame->all.layouts; p != NULL; p=p->next ) {
581                 layout = (lglTemplateLayout *)p->data;
582
583                 for (iy = 0; iy < layout->ny; iy++) {
584                         for (ix = 0; ix < layout->nx; ix++, i_label++) {
585                                 origins[i_label].x = ix*layout->dx + layout->x0;
586                                 origins[i_label].y = iy*layout->dy + layout->y0;
587                         }
588                 }
589         }
590
591         g_qsort_with_data (origins, n_labels, sizeof(lglTemplateOrigin),
592                            compare_origins, NULL);
593
594         return origins;
595 }
596
597
598 /**
599  * lgl_template_frame_add_layout:
600  *   @frame:  Pointer to template frame to add layout to.
601  *   @layout: Pointer to layout structure to add to frame.
602  *
603  * This function adds a layout structure to the given template frame.
604  *
605  */
606 void
607 lgl_template_frame_add_layout (lglTemplateFrame   *frame,
608                                lglTemplateLayout  *layout)
609 {
610         g_return_if_fail (frame);
611         g_return_if_fail (layout);
612
613         frame->all.layouts = g_list_append (frame->all.layouts, layout);
614 }
615  
616
617 /**
618  * lgl_template_frame_add_markup:
619  *   @frame:  Pointer to template frame to add markup to.
620  *   @markup: Pointer to markup structure to add to frame.
621  *
622  * This function adds a markup structure to the given template frame.
623  *
624  */
625 void
626 lgl_template_frame_add_markup (lglTemplateFrame   *frame,
627                                lglTemplateMarkup  *markup)
628 {
629         g_return_if_fail (frame);
630         g_return_if_fail (markup);
631
632         frame->all.markups = g_list_append (frame->all.markups, markup);
633 }
634  
635
636 /**
637  * lgl_template_layout_new:
638  *   @nx:  Number of labels across.
639  *   @ny:  Number of labels down.
640  *   @x0:  X coordinate of the top-left corner of the top-left label in the layout in points.
641  *   @y0:  Y coordinate of the top-left corner of the top-left label in the layout in points.
642  *   @dx:  Horizontal pitch in points.  This is the distance from left-edge to left-edge.
643  *   @dy:  Vertical pitch in points.  This is the distance from top-edge to top-edge.
644  *
645  * This function creates a new layout structure with the given parameters.
646  *
647  * Returns: a newly allocated #lglTemplateLayout structure.
648  *
649  */
650 lglTemplateLayout *
651 lgl_template_layout_new (gint    nx,
652                          gint    ny,
653                          gdouble x0,
654                          gdouble y0,
655                          gdouble dx,
656                          gdouble dy)
657 {
658         lglTemplateLayout *layout;
659
660         layout = g_new0 (lglTemplateLayout, 1);
661
662         layout->nx = nx;
663         layout->ny = ny;
664         layout->x0 = x0;
665         layout->y0 = y0;
666         layout->dx = dx;
667         layout->dy = dy;
668
669         return layout;
670 }
671
672
673 /**
674  * lgl_template_markup_margin_new:
675  *   @size: margin size in points.
676  *
677  * This function creates a new margin markup structure.
678  *
679  * Returns: a newly allocated #lglTemplateMarkup structure.
680  *
681  */
682 lglTemplateMarkup *
683 lgl_template_markup_margin_new (gdouble size)
684 {
685         lglTemplateMarkup *markup;
686
687         markup = g_new0 (lglTemplateMarkup, 1);
688
689         markup->type        = LGL_TEMPLATE_MARKUP_MARGIN;
690         markup->margin.size = size;
691
692         return markup;
693 }
694
695
696 /**
697  * lgl_template_markup_line_new:
698  *   @x1: x coordinate of first endpoint.
699  *   @y1: y coordinate of first endpoint.
700  *   @x2: x coordinate of second endpoint.
701  *   @y2: y coordinate of second endpoint.
702  *
703  * This function creates a new line markup structure.
704  *
705  * Returns: a newly allocated #lglTemplateMarkup structure.
706  *
707  */
708 lglTemplateMarkup *
709 lgl_template_markup_line_new (gdouble x1,
710                               gdouble y1,
711                               gdouble x2,
712                               gdouble y2)
713 {
714         lglTemplateMarkup *markup;
715
716         markup = g_new0 (lglTemplateMarkup, 1);
717
718         markup->type        = LGL_TEMPLATE_MARKUP_LINE;
719         markup->line.x1     = x1;
720         markup->line.y1     = y1;
721         markup->line.x2     = x2;
722         markup->line.y2     = y2;
723
724         return markup;
725 }
726
727
728 /**
729  * lgl_template_markup_circle_new:
730  *   @x0: x coordinate of center of circle.
731  *   @y0: y coordinate of center of circle.
732  *   @r:  radius of circle.
733  *
734  * This function creates a new circle markup structure.
735  *
736  * Returns: a newly allocated #lglTemplateMarkup structure.
737  *
738  */
739 lglTemplateMarkup *
740 lgl_template_markup_circle_new (gdouble x0,
741                                 gdouble y0,
742                                 gdouble r)
743 {
744         lglTemplateMarkup *markup;
745
746         markup = g_new0 (lglTemplateMarkup, 1);
747
748         markup->type        = LGL_TEMPLATE_MARKUP_CIRCLE;
749         markup->circle.x0   = x0;
750         markup->circle.y0   = y0;
751         markup->circle.r    = r;
752
753         return markup;
754 }
755
756
757 /**
758  * lgl_template_markup_rect_new:
759  *   @x1: x coordinate of top-left corner of rectangle.
760  *   @y1: y coordinate of top-left corner of rectangle.
761  *   @w:  width of rectangle.
762  *   @h:  height of rectangle.
763  *   @r:  radius of rounded corner.
764  *
765  * This function creates a new rectangle markup structure.
766  *
767  * Returns: a newly allocated #lglTemplateMarkup structure.
768  *
769  */
770 lglTemplateMarkup *
771 lgl_template_markup_rect_new (gdouble x1,
772                               gdouble y1,
773                               gdouble w,
774                               gdouble h,
775                               gdouble r)
776 {
777         lglTemplateMarkup *markup;
778
779         markup = g_new0 (lglTemplateMarkup, 1);
780
781         markup->type        = LGL_TEMPLATE_MARKUP_RECT;
782         markup->rect.x1     = x1;
783         markup->rect.y1     = y1;
784         markup->rect.w      = w;
785         markup->rect.h      = h;
786         markup->rect.r      = r;
787
788         return markup;
789 }
790
791
792 /**
793  * lgl_template_dup:
794  *   @orig_template: Template to duplicate.
795  *
796  * This function duplicates a template structure.
797  *
798  * Returns:  a newly allocated #lglTemplate structure.
799  *
800  */
801 lglTemplate *
802 lgl_template_dup (const lglTemplate *orig_template)
803 {
804         lglTemplate         *template;
805         lglTemplateAlias    *alias;
806         GList               *p;
807         lglTemplateFrame    *frame;
808
809         g_return_val_if_fail (orig_template, NULL);
810
811         template = lgl_template_new (orig_template->brand,
812                                      orig_template->part,
813                                      orig_template->description,
814                                      orig_template->paper_id,
815                                      orig_template->page_width,
816                                      orig_template->page_height);
817
818         template->equiv_part  = g_strdup (orig_template->equiv_part);
819         template->product_url = g_strdup (orig_template->product_url);
820
821         for ( p=orig_template->aliases; p != NULL; p=p->next )
822         {
823                 alias = (lglTemplateAlias *)p->data;
824
825                 if ( !(UTF8_EQUAL (template->brand, alias->brand) &&
826                        UTF8_EQUAL (template->part, alias->part)) )
827                 {
828                         lgl_template_add_alias (template, lgl_template_alias_dup (alias));
829                 }
830
831         }
832
833         for ( p=orig_template->category_ids; p != NULL; p=p->next )
834         {
835                 lgl_template_add_category (template, p->data);
836         }
837
838         for ( p=orig_template->frames; p != NULL; p=p->next )
839         {
840                 frame = (lglTemplateFrame *)p->data;
841
842                 lgl_template_add_frame (template, lgl_template_frame_dup (frame));
843         }
844
845         return template;
846 }
847
848
849 /**
850  * lgl_template_free:
851  *   @template: Template to free.
852  *
853  * This function frees all memory associated with given template structure.
854  *
855  */
856 void
857 lgl_template_free (lglTemplate *template)
858 {
859         GList            *p;
860         lglTemplateFrame *frame;
861
862         if ( template != NULL ) {
863
864                 g_free (template->brand);
865                 template->brand = NULL;
866
867                 g_free (template->part);
868                 template->part = NULL;
869
870                 g_free (template->description);
871                 template->description = NULL;
872
873                 g_free (template->paper_id);
874                 template->paper_id = NULL;
875
876                 for ( p=template->aliases; p != NULL; p=p->next ) {
877
878                         lgl_template_alias_free (p->data);
879                         p->data = NULL;
880
881                 }
882                 g_list_free (template->aliases);
883                 template->aliases = NULL;
884
885                 for ( p=template->category_ids; p != NULL; p=p->next ) {
886
887                         g_free (p->data);
888                         p->data = NULL;
889
890                 }
891                 g_list_free (template->category_ids);
892                 template->category_ids = NULL;
893
894                 for ( p=template->frames; p != NULL; p=p->next ) {
895
896                         frame = (lglTemplateFrame *)p->data;
897
898                         lgl_template_frame_free (frame);
899                         p->data = NULL;
900                 }
901                 g_list_free (template->frames);
902                 template->frames = NULL;
903
904                 g_free (template);
905
906         }
907
908 }
909
910
911 /**
912  * lgl_template_alias_dup:
913  *   @orig_alias: Alias to duplicate.
914  *
915  * This function duplicates a template alias structure.
916  *
917  * Returns:  a newly allocated #lglTemplateAlias structure.
918  *
919  */
920 lglTemplateAlias *
921 lgl_template_alias_dup (const lglTemplateAlias *orig_alias)
922 {
923         g_return_val_if_fail (orig_alias, NULL);
924
925         return lgl_template_alias_new (orig_alias->brand, orig_alias->part);
926 }
927
928
929 /**
930  * lgl_template_alias_free:
931  *   @alias: Alias to free.
932  *
933  * This function frees all memory associated with given template alias structure.
934  *
935  */
936 void
937 lgl_template_alias_free (lglTemplateAlias *alias)
938 {
939
940         if ( alias != NULL )
941         {
942                 g_free (alias->brand);
943                 alias->brand = NULL;
944
945                 g_free (alias->part);
946                 alias->part = NULL;
947
948                 g_free (alias);
949         }
950 }
951
952
953 /**
954  * lgl_template_frame_dup:
955  *   @orig_frame: Frame to duplicate.
956  *
957  * This function duplicates a template frame structure.
958  *
959  * Returns:  a newly allocated #lglTemplateFrame structure.
960  *
961  */
962 lglTemplateFrame *
963 lgl_template_frame_dup (const lglTemplateFrame *orig_frame)
964 {
965         lglTemplateFrame    *frame;
966         GList               *p;
967         lglTemplateLayout   *layout;
968         lglTemplateMarkup   *markup;
969
970         g_return_val_if_fail (orig_frame, NULL);
971
972         switch (orig_frame->shape) {
973
974         case LGL_TEMPLATE_FRAME_SHAPE_RECT:
975                 frame =
976                         lgl_template_frame_rect_new (orig_frame->all.id,
977                                                      orig_frame->rect.w,
978                                                      orig_frame->rect.h,
979                                                      orig_frame->rect.r,
980                                                      orig_frame->rect.x_waste,
981                                                      orig_frame->rect.y_waste);
982                 break;
983
984         case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
985                 frame =
986                         lgl_template_frame_round_new (orig_frame->all.id,
987                                                       orig_frame->round.r,
988                                                       orig_frame->round.waste);
989                 break;
990
991         case LGL_TEMPLATE_FRAME_SHAPE_CD:
992                 frame =
993                         lgl_template_frame_cd_new (orig_frame->all.id,
994                                                    orig_frame->cd.r1,
995                                                    orig_frame->cd.r2,
996                                                    orig_frame->cd.w,
997                                                    orig_frame->cd.h,
998                                                    orig_frame->cd.waste);
999                 break;
1000
1001         default:
1002                 return NULL;
1003                 break;
1004         }
1005
1006         for ( p=orig_frame->all.layouts; p != NULL; p=p->next ) {
1007
1008                 layout = (lglTemplateLayout *)p->data;
1009
1010                 lgl_template_frame_add_layout (frame, lgl_template_layout_dup (layout));
1011         }
1012
1013         for ( p=orig_frame->all.markups; p != NULL; p=p->next ) {
1014
1015                 markup = (lglTemplateMarkup *)p->data;
1016
1017                 lgl_template_frame_add_markup (frame, lgl_template_markup_dup (markup));
1018         }
1019
1020         return frame;
1021 }
1022
1023
1024 /**
1025  * lgl_template_frame_free:
1026  *   @frame: Frame to free.
1027  *
1028  * This function frees all memory associated with given template frame structure.
1029  *
1030  */
1031 void
1032 lgl_template_frame_free (lglTemplateFrame *frame)
1033 {
1034         GList                *p;
1035         lglTemplateLayout    *layout;
1036         lglTemplateMarkup    *markup;
1037
1038         if ( frame != NULL ) {
1039
1040                 g_free (frame->all.id);
1041                 frame->all.id = NULL;
1042
1043                 for ( p=frame->all.layouts; p != NULL; p=p->next ) {
1044
1045                         layout = (lglTemplateLayout *)p->data;
1046
1047                         lgl_template_layout_free (layout);
1048                         p->data = NULL;
1049                 }
1050                 g_list_free (frame->all.layouts);
1051                 frame->all.layouts = NULL;
1052
1053                 for ( p=frame->all.markups; p != NULL; p=p->next ) {
1054
1055                         markup = (lglTemplateMarkup *)p->data;
1056
1057                         lgl_template_markup_free (markup);
1058                         p->data = NULL;
1059                 }
1060                 g_list_free (frame->all.markups);
1061                 frame->all.markups = NULL;
1062
1063                 g_free (frame);
1064
1065         }
1066
1067 }
1068
1069
1070 /**
1071  * lgl_template_layout_dup:
1072  *   @orig_layout: Layout to duplicate.
1073  *
1074  * This function duplicates a template layout structure.
1075  *
1076  * Returns:  a newly allocated #lglTemplateLayout structure.
1077  *
1078  */
1079 lglTemplateLayout *
1080 lgl_template_layout_dup (const lglTemplateLayout *orig_layout)
1081 {
1082         lglTemplateLayout *layout;
1083
1084         g_return_val_if_fail (orig_layout, NULL);
1085
1086         layout = g_new0 (lglTemplateLayout, 1);
1087
1088         /* copy contents */
1089         *layout = *orig_layout;
1090
1091         return layout;
1092 }
1093
1094
1095 /**
1096  * lgl_template_layout_free:
1097  *   @layout: Layout to free.
1098  *
1099  * This function frees all memory associated with given template layout structure.
1100  *
1101  */
1102 void
1103 lgl_template_layout_free (lglTemplateLayout *layout)
1104 {
1105         g_free (layout);
1106 }
1107
1108
1109 /**
1110  * lgl_template_markup_dup:
1111  *   @orig_markup: Markup to duplicate.
1112  *
1113  * This function duplicates a template markup structure.
1114  *
1115  * Returns:  a newly allocated #lglTemplateMarkup structure.
1116  *
1117  */
1118 lglTemplateMarkup *
1119 lgl_template_markup_dup (const lglTemplateMarkup *orig_markup)
1120 {
1121         lglTemplateMarkup *markup;
1122
1123         g_return_val_if_fail (orig_markup, NULL);
1124
1125         markup = g_new0 (lglTemplateMarkup, 1);
1126
1127         *markup = *orig_markup;
1128
1129         return markup;
1130 }
1131
1132
1133 /**
1134  * lgl_template_markup_free:
1135  *   @markup: Markup to free.
1136  *
1137  * This function frees all memory associated with given template markup structure.
1138  *
1139  */
1140 void
1141 lgl_template_markup_free (lglTemplateMarkup *markup)
1142 {
1143         g_free (markup);
1144 }
1145
1146
1147 static gint
1148 compare_origins (gconstpointer a,
1149                  gconstpointer b,
1150                  gpointer      user_data)
1151 {
1152         const lglTemplateOrigin *a_origin = a, *b_origin = b;
1153
1154         if ( a_origin->y < b_origin->y ) {
1155                 return -1;
1156         } else if ( a_origin->y > b_origin->y ) {
1157                 return +1;
1158         } else {
1159                 if ( a_origin->x < b_origin->x ) {
1160                         return -1;
1161                 } else if ( a_origin->x > b_origin->x ) {
1162                         return +1;
1163                 } else {
1164                         return 0; /* hopefully 2 labels won't have the same origin */
1165                 }
1166         }
1167 }
1168
1169
1170
1171 /*
1172  * Local Variables:       -- emacs
1173  * mode: C                -- emacs
1174  * c-basic-offset: 8      -- emacs
1175  * tab-width: 8           -- emacs
1176  * indent-tabs-mode: nil  -- emacs
1177  * End:                   -- emacs
1178  */