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