]> git.sur5r.net Git - glabels/blob - libglabels/template.c
Rename executables and key files to support parallel installation
[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_ellipse_new:
414  *   @id:      ID of frame.  (This should currently always be "0").
415  *   @w:       width of frame in points.
416  *   @h:       height of frame in points.
417  *   @r:       radius of rounded corners in points.  (Should be 0 for square corners.)
418  *   @x_waste: Amount of overprint to allow in the horizontal direction.
419  *   @y_waste: Amount of overprint to allow in the vertical direction.
420  *
421  * This function creates a new template frame for an elliptical label or card.
422  *
423  * Returns: Pointer to newly allocated #lglTemplateFrame structure.
424  *
425  */
426 lglTemplateFrame *
427 lgl_template_frame_ellipse_new  (const gchar         *id,
428                                  gdouble              w,
429                                  gdouble              h,
430                                  gdouble              waste)
431 {
432         lglTemplateFrame *frame;
433
434         frame = g_new0 (lglTemplateFrame, 1);
435
436         frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE;
437         frame->ellipse.id = g_strdup (id);
438
439         frame->ellipse.w = w;
440         frame->ellipse.h = h;
441         frame->ellipse.waste = waste;
442
443         return frame;
444 }
445
446
447 /**
448  * lgl_template_frame_round_new:
449  *   @id:      ID of frame.  (This should currently always be "0").
450  *   @r:       radius of label in points.
451  *   @waste:   Amount of overprint to allow.
452  *
453  * This function creates a new template frame for a round label.
454  *
455  * Returns: Pointer to newly allocated #lglTemplateFrame structure.
456  *
457  */
458 lglTemplateFrame *
459 lgl_template_frame_round_new (const gchar         *id,
460                               gdouble              r,
461                               gdouble              waste)
462 {
463         lglTemplateFrame *frame;
464
465         frame = g_new0 (lglTemplateFrame, 1);
466
467         frame->shape = LGL_TEMPLATE_FRAME_SHAPE_ROUND;
468         frame->round.id = g_strdup (id);
469
470         frame->round.r = r;
471         frame->round.waste = waste;
472
473         return frame;
474 }
475
476                                                                                
477 /**
478  * lgl_template_frame_cd_new:
479  *   @id:      ID of frame.  (This should currently always be "0").
480  *   @r1:      outer radius of label in points.
481  *   @r2:      radius of center hole in points.
482  *   @w:       clip width of frame in points for business card CDs.  Should be 0 for no clipping.
483  *   @h:       clip height of frame in points for business card CDs.  Should be 0 for no clipping.
484  *   @waste:   Amount of overprint to allow.
485  *
486  * This function creates a new template frame for a CD/DVD label.
487  *
488  * Returns: Pointer to newly allocated #lglTemplateFrame structure.
489  *
490  */
491 lglTemplateFrame *
492 lgl_template_frame_cd_new (const gchar         *id,
493                            gdouble              r1,
494                            gdouble              r2,
495                            gdouble              w,
496                            gdouble              h,
497                            gdouble              waste)
498 {
499         lglTemplateFrame *frame;
500
501         frame = g_new0 (lglTemplateFrame, 1);
502
503         frame->shape = LGL_TEMPLATE_FRAME_SHAPE_CD;
504         frame->cd.id = g_strdup (id);
505
506         frame->cd.r1 = r1;
507         frame->cd.r2 = r2;
508         frame->cd.w  = w;
509         frame->cd.h  = h;
510         frame->cd.waste = waste;
511
512         return frame;
513 }
514
515
516 /**
517  * lgl_template_frame_get_size:
518  * @frame: #lglTemplateFrame structure to query
519  * @w: pointer to location to receive width of frame
520  * @h: pointer to location to receive height of frame
521  *
522  * Get size (width and height) of given #lglTemplateFrame in points.
523  *
524  */
525 void
526 lgl_template_frame_get_size (const lglTemplateFrame *frame,
527                              gdouble                *w,
528                              gdouble                *h)
529 {
530         g_return_if_fail (frame);
531
532         switch (frame->shape) {
533         case LGL_TEMPLATE_FRAME_SHAPE_RECT:
534                 *w = frame->rect.w;
535                 *h = frame->rect.h;
536                 break;
537         case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
538                 *w = frame->ellipse.w;
539                 *h = frame->ellipse.h;
540                 break;
541         case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
542                 *w = 2.0 * frame->round.r;
543                 *h = 2.0 * frame->round.r;
544                 break;
545         case LGL_TEMPLATE_FRAME_SHAPE_CD:
546                 if (frame->cd.w == 0.0) {
547                         *w = 2.0 * frame->cd.r1;
548                 } else {
549                         *w = frame->cd.w;
550                 }
551                 if (frame->cd.h == 0.0) {
552                         *h = 2.0 * frame->cd.r1;
553                 } else {
554                         *h = frame->cd.h;
555                 }
556                 break;
557         default:
558                 *w = 0.0;
559                 *h = 0.0;
560                 break;
561         }
562 }
563
564
565 /**
566  * lgl_template_frame_get_n_labels:
567  * @frame: #lglTemplateFrame structure to query
568  *
569  * Get total number of labels per sheet corresponding to the given frame.
570  *
571  * Returns: number of labels per sheet.
572  *
573  */
574 gint
575 lgl_template_frame_get_n_labels (const lglTemplateFrame *frame)
576 {
577         gint               n_labels = 0;
578         GList             *p;
579         lglTemplateLayout *layout;
580
581         g_return_val_if_fail (frame, 0);
582
583         for ( p=frame->all.layouts; p != NULL; p=p->next ) {
584                 layout = (lglTemplateLayout *)p->data;
585
586                 n_labels += layout->nx * layout->ny;
587         }
588
589         return n_labels;
590 }
591
592
593 /**
594  * lgl_template_frame_get_origins:
595  * @frame: #lglTemplateFrame structure to query
596  *
597  * Get an array of label origins for the given frame.  These origins represent the
598  * upper left hand corner of each label on a page corresponding to the given frame.
599  * The origins will be ordered geometrically left to right and then top to bottom.
600  * The array should be freed using g_free().
601  *
602  * Returns: A newly allocated array of #lglTemplateOrigin structures.
603  *
604  */
605 lglTemplateOrigin *
606 lgl_template_frame_get_origins (const lglTemplateFrame *frame)
607 {
608         gint               i_label, n_labels, ix, iy;
609         lglTemplateOrigin *origins;
610         GList             *p;
611         lglTemplateLayout *layout;
612
613         g_return_val_if_fail (frame, NULL);
614
615         n_labels = lgl_template_frame_get_n_labels (frame);
616         origins = g_new0 (lglTemplateOrigin, n_labels);
617
618         i_label = 0;
619         for ( p=frame->all.layouts; p != NULL; p=p->next ) {
620                 layout = (lglTemplateLayout *)p->data;
621
622                 for (iy = 0; iy < layout->ny; iy++) {
623                         for (ix = 0; ix < layout->nx; ix++, i_label++) {
624                                 origins[i_label].x = ix*layout->dx + layout->x0;
625                                 origins[i_label].y = iy*layout->dy + layout->y0;
626                         }
627                 }
628         }
629
630         g_qsort_with_data (origins, n_labels, sizeof(lglTemplateOrigin),
631                            compare_origins, NULL);
632
633         return origins;
634 }
635
636
637 /**
638  * lgl_template_frame_add_layout:
639  *   @frame:  Pointer to template frame to add layout to.
640  *   @layout: Pointer to layout structure to add to frame.
641  *
642  * This function adds a layout structure to the given template frame.
643  *
644  */
645 void
646 lgl_template_frame_add_layout (lglTemplateFrame   *frame,
647                                lglTemplateLayout  *layout)
648 {
649         g_return_if_fail (frame);
650         g_return_if_fail (layout);
651
652         frame->all.layouts = g_list_append (frame->all.layouts, layout);
653 }
654  
655
656 /**
657  * lgl_template_frame_add_markup:
658  *   @frame:  Pointer to template frame to add markup to.
659  *   @markup: Pointer to markup structure to add to frame.
660  *
661  * This function adds a markup structure to the given template frame.
662  *
663  */
664 void
665 lgl_template_frame_add_markup (lglTemplateFrame   *frame,
666                                lglTemplateMarkup  *markup)
667 {
668         g_return_if_fail (frame);
669         g_return_if_fail (markup);
670
671         frame->all.markups = g_list_append (frame->all.markups, markup);
672 }
673  
674
675 /**
676  * lgl_template_layout_new:
677  *   @nx:  Number of labels across.
678  *   @ny:  Number of labels down.
679  *   @x0:  X coordinate of the top-left corner of the top-left label in the layout in points.
680  *   @y0:  Y coordinate of the top-left corner of the top-left label in the layout in points.
681  *   @dx:  Horizontal pitch in points.  This is the distance from left-edge to left-edge.
682  *   @dy:  Vertical pitch in points.  This is the distance from top-edge to top-edge.
683  *
684  * This function creates a new layout structure with the given parameters.
685  *
686  * Returns: a newly allocated #lglTemplateLayout structure.
687  *
688  */
689 lglTemplateLayout *
690 lgl_template_layout_new (gint    nx,
691                          gint    ny,
692                          gdouble x0,
693                          gdouble y0,
694                          gdouble dx,
695                          gdouble dy)
696 {
697         lglTemplateLayout *layout;
698
699         layout = g_new0 (lglTemplateLayout, 1);
700
701         layout->nx = nx;
702         layout->ny = ny;
703         layout->x0 = x0;
704         layout->y0 = y0;
705         layout->dx = dx;
706         layout->dy = dy;
707
708         return layout;
709 }
710
711
712 /**
713  * lgl_template_markup_margin_new:
714  *   @size: margin size in points.
715  *
716  * This function creates a new margin markup structure.
717  *
718  * Returns: a newly allocated #lglTemplateMarkup structure.
719  *
720  */
721 lglTemplateMarkup *
722 lgl_template_markup_margin_new (gdouble size)
723 {
724         lglTemplateMarkup *markup;
725
726         markup = g_new0 (lglTemplateMarkup, 1);
727
728         markup->type        = LGL_TEMPLATE_MARKUP_MARGIN;
729         markup->margin.size = size;
730
731         return markup;
732 }
733
734
735 /**
736  * lgl_template_markup_line_new:
737  *   @x1: x coordinate of first endpoint.
738  *   @y1: y coordinate of first endpoint.
739  *   @x2: x coordinate of second endpoint.
740  *   @y2: y coordinate of second endpoint.
741  *
742  * This function creates a new line markup structure.
743  *
744  * Returns: a newly allocated #lglTemplateMarkup structure.
745  *
746  */
747 lglTemplateMarkup *
748 lgl_template_markup_line_new (gdouble x1,
749                               gdouble y1,
750                               gdouble x2,
751                               gdouble y2)
752 {
753         lglTemplateMarkup *markup;
754
755         markup = g_new0 (lglTemplateMarkup, 1);
756
757         markup->type        = LGL_TEMPLATE_MARKUP_LINE;
758         markup->line.x1     = x1;
759         markup->line.y1     = y1;
760         markup->line.x2     = x2;
761         markup->line.y2     = y2;
762
763         return markup;
764 }
765
766
767 /**
768  * lgl_template_markup_circle_new:
769  *   @x0: x coordinate of center of circle.
770  *   @y0: y coordinate of center of circle.
771  *   @r:  radius of circle.
772  *
773  * This function creates a new circle markup structure.
774  *
775  * Returns: a newly allocated #lglTemplateMarkup structure.
776  *
777  */
778 lglTemplateMarkup *
779 lgl_template_markup_circle_new (gdouble x0,
780                                 gdouble y0,
781                                 gdouble r)
782 {
783         lglTemplateMarkup *markup;
784
785         markup = g_new0 (lglTemplateMarkup, 1);
786
787         markup->type        = LGL_TEMPLATE_MARKUP_CIRCLE;
788         markup->circle.x0   = x0;
789         markup->circle.y0   = y0;
790         markup->circle.r    = r;
791
792         return markup;
793 }
794
795
796 /**
797  * lgl_template_markup_rect_new:
798  *   @x1: x coordinate of top-left corner of rectangle.
799  *   @y1: y coordinate of top-left corner of rectangle.
800  *   @w:  width of rectangle.
801  *   @h:  height of rectangle.
802  *   @r:  radius of rounded corner.
803  *
804  * This function creates a new rectangle markup structure.
805  *
806  * Returns: a newly allocated #lglTemplateMarkup structure.
807  *
808  */
809 lglTemplateMarkup *
810 lgl_template_markup_rect_new (gdouble x1,
811                               gdouble y1,
812                               gdouble w,
813                               gdouble h,
814                               gdouble r)
815 {
816         lglTemplateMarkup *markup;
817
818         markup = g_new0 (lglTemplateMarkup, 1);
819
820         markup->type        = LGL_TEMPLATE_MARKUP_RECT;
821         markup->rect.x1     = x1;
822         markup->rect.y1     = y1;
823         markup->rect.w      = w;
824         markup->rect.h      = h;
825         markup->rect.r      = r;
826
827         return markup;
828 }
829
830
831 /**
832  * lgl_template_markup_ellipse_new:
833  *   @x1: x coordinate of top-left corner of ellipse.
834  *   @y1: y coordinate of top-left corner of ellipse.
835  *   @w:  width of ellipse.
836  *   @h:  height of ellipse.
837  *
838  * This function creates a new ellipse markup structure.
839  *
840  * Returns: a newly allocated #lglTemplateMarkup structure.
841  *
842  */
843 lglTemplateMarkup *
844 lgl_template_markup_ellipse_new (gdouble x1,
845                                  gdouble y1,
846                                  gdouble w,
847                                  gdouble h)
848 {
849         lglTemplateMarkup *markup;
850
851         markup = g_new0 (lglTemplateMarkup, 1);
852
853         markup->type        = LGL_TEMPLATE_MARKUP_ELLIPSE;
854         markup->ellipse.x1     = x1;
855         markup->ellipse.y1     = y1;
856         markup->ellipse.w      = w;
857         markup->ellipse.h      = h;
858
859         return markup;
860 }
861
862
863 /**
864  * lgl_template_dup:
865  *   @orig_template: Template to duplicate.
866  *
867  * This function duplicates a template structure.
868  *
869  * Returns:  a newly allocated #lglTemplate structure.
870  *
871  */
872 lglTemplate *
873 lgl_template_dup (const lglTemplate *orig_template)
874 {
875         lglTemplate         *template;
876         lglTemplateAlias    *alias;
877         GList               *p;
878         lglTemplateFrame    *frame;
879
880         g_return_val_if_fail (orig_template, NULL);
881
882         template = lgl_template_new (orig_template->brand,
883                                      orig_template->part,
884                                      orig_template->description,
885                                      orig_template->paper_id,
886                                      orig_template->page_width,
887                                      orig_template->page_height);
888
889         template->equiv_part  = g_strdup (orig_template->equiv_part);
890         template->product_url = g_strdup (orig_template->product_url);
891
892         for ( p=orig_template->aliases; p != NULL; p=p->next )
893         {
894                 alias = (lglTemplateAlias *)p->data;
895
896                 if ( !(UTF8_EQUAL (template->brand, alias->brand) &&
897                        UTF8_EQUAL (template->part, alias->part)) )
898                 {
899                         lgl_template_add_alias (template, lgl_template_alias_dup (alias));
900                 }
901
902         }
903
904         for ( p=orig_template->category_ids; p != NULL; p=p->next )
905         {
906                 lgl_template_add_category (template, p->data);
907         }
908
909         for ( p=orig_template->frames; p != NULL; p=p->next )
910         {
911                 frame = (lglTemplateFrame *)p->data;
912
913                 lgl_template_add_frame (template, lgl_template_frame_dup (frame));
914         }
915
916         return template;
917 }
918
919
920 /**
921  * lgl_template_free:
922  *   @template: Template to free.
923  *
924  * This function frees all memory associated with given template structure.
925  *
926  */
927 void
928 lgl_template_free (lglTemplate *template)
929 {
930         GList            *p;
931         lglTemplateFrame *frame;
932
933         if ( template != NULL ) {
934
935                 g_free (template->brand);
936                 template->brand = NULL;
937
938                 g_free (template->part);
939                 template->part = NULL;
940
941                 g_free (template->description);
942                 template->description = NULL;
943
944                 g_free (template->paper_id);
945                 template->paper_id = NULL;
946
947                 for ( p=template->aliases; p != NULL; p=p->next ) {
948
949                         lgl_template_alias_free (p->data);
950                         p->data = NULL;
951
952                 }
953                 g_list_free (template->aliases);
954                 template->aliases = NULL;
955
956                 for ( p=template->category_ids; p != NULL; p=p->next ) {
957
958                         g_free (p->data);
959                         p->data = NULL;
960
961                 }
962                 g_list_free (template->category_ids);
963                 template->category_ids = NULL;
964
965                 for ( p=template->frames; p != NULL; p=p->next ) {
966
967                         frame = (lglTemplateFrame *)p->data;
968
969                         lgl_template_frame_free (frame);
970                         p->data = NULL;
971                 }
972                 g_list_free (template->frames);
973                 template->frames = NULL;
974
975                 g_free (template);
976
977         }
978
979 }
980
981
982 /**
983  * lgl_template_alias_dup:
984  *   @orig_alias: Alias to duplicate.
985  *
986  * This function duplicates a template alias structure.
987  *
988  * Returns:  a newly allocated #lglTemplateAlias structure.
989  *
990  */
991 lglTemplateAlias *
992 lgl_template_alias_dup (const lglTemplateAlias *orig_alias)
993 {
994         g_return_val_if_fail (orig_alias, NULL);
995
996         return lgl_template_alias_new (orig_alias->brand, orig_alias->part);
997 }
998
999
1000 /**
1001  * lgl_template_alias_free:
1002  *   @alias: Alias to free.
1003  *
1004  * This function frees all memory associated with given template alias structure.
1005  *
1006  */
1007 void
1008 lgl_template_alias_free (lglTemplateAlias *alias)
1009 {
1010
1011         if ( alias != NULL )
1012         {
1013                 g_free (alias->brand);
1014                 alias->brand = NULL;
1015
1016                 g_free (alias->part);
1017                 alias->part = NULL;
1018
1019                 g_free (alias);
1020         }
1021 }
1022
1023
1024 /**
1025  * lgl_template_frame_dup:
1026  *   @orig_frame: Frame to duplicate.
1027  *
1028  * This function duplicates a template frame structure.
1029  *
1030  * Returns:  a newly allocated #lglTemplateFrame structure.
1031  *
1032  */
1033 lglTemplateFrame *
1034 lgl_template_frame_dup (const lglTemplateFrame *orig_frame)
1035 {
1036         lglTemplateFrame    *frame;
1037         GList               *p;
1038         lglTemplateLayout   *layout;
1039         lglTemplateMarkup   *markup;
1040
1041         g_return_val_if_fail (orig_frame, NULL);
1042
1043         switch (orig_frame->shape) {
1044
1045         case LGL_TEMPLATE_FRAME_SHAPE_RECT:
1046                 frame =
1047                         lgl_template_frame_rect_new (orig_frame->all.id,
1048                                                      orig_frame->rect.w,
1049                                                      orig_frame->rect.h,
1050                                                      orig_frame->rect.r,
1051                                                      orig_frame->rect.x_waste,
1052                                                      orig_frame->rect.y_waste);
1053                 break;
1054
1055         case LGL_TEMPLATE_FRAME_SHAPE_ELLIPSE:
1056                 frame =
1057                         lgl_template_frame_ellipse_new (orig_frame->all.id,
1058                                                         orig_frame->ellipse.w,
1059                                                         orig_frame->ellipse.h,
1060                                                         orig_frame->ellipse.waste);
1061                 break;
1062
1063         case LGL_TEMPLATE_FRAME_SHAPE_ROUND:
1064                 frame =
1065                         lgl_template_frame_round_new (orig_frame->all.id,
1066                                                       orig_frame->round.r,
1067                                                       orig_frame->round.waste);
1068                 break;
1069
1070         case LGL_TEMPLATE_FRAME_SHAPE_CD:
1071                 frame =
1072                         lgl_template_frame_cd_new (orig_frame->all.id,
1073                                                    orig_frame->cd.r1,
1074                                                    orig_frame->cd.r2,
1075                                                    orig_frame->cd.w,
1076                                                    orig_frame->cd.h,
1077                                                    orig_frame->cd.waste);
1078                 break;
1079
1080         default:
1081                 return NULL;
1082                 break;
1083         }
1084
1085         for ( p=orig_frame->all.layouts; p != NULL; p=p->next ) {
1086
1087                 layout = (lglTemplateLayout *)p->data;
1088
1089                 lgl_template_frame_add_layout (frame, lgl_template_layout_dup (layout));
1090         }
1091
1092         for ( p=orig_frame->all.markups; p != NULL; p=p->next ) {
1093
1094                 markup = (lglTemplateMarkup *)p->data;
1095
1096                 lgl_template_frame_add_markup (frame, lgl_template_markup_dup (markup));
1097         }
1098
1099         return frame;
1100 }
1101
1102
1103 /**
1104  * lgl_template_frame_free:
1105  *   @frame: Frame to free.
1106  *
1107  * This function frees all memory associated with given template frame structure.
1108  *
1109  */
1110 void
1111 lgl_template_frame_free (lglTemplateFrame *frame)
1112 {
1113         GList                *p;
1114         lglTemplateLayout    *layout;
1115         lglTemplateMarkup    *markup;
1116
1117         if ( frame != NULL ) {
1118
1119                 g_free (frame->all.id);
1120                 frame->all.id = NULL;
1121
1122                 for ( p=frame->all.layouts; p != NULL; p=p->next ) {
1123
1124                         layout = (lglTemplateLayout *)p->data;
1125
1126                         lgl_template_layout_free (layout);
1127                         p->data = NULL;
1128                 }
1129                 g_list_free (frame->all.layouts);
1130                 frame->all.layouts = NULL;
1131
1132                 for ( p=frame->all.markups; p != NULL; p=p->next ) {
1133
1134                         markup = (lglTemplateMarkup *)p->data;
1135
1136                         lgl_template_markup_free (markup);
1137                         p->data = NULL;
1138                 }
1139                 g_list_free (frame->all.markups);
1140                 frame->all.markups = NULL;
1141
1142                 g_free (frame);
1143
1144         }
1145
1146 }
1147
1148
1149 /**
1150  * lgl_template_layout_dup:
1151  *   @orig_layout: Layout to duplicate.
1152  *
1153  * This function duplicates a template layout structure.
1154  *
1155  * Returns:  a newly allocated #lglTemplateLayout structure.
1156  *
1157  */
1158 lglTemplateLayout *
1159 lgl_template_layout_dup (const lglTemplateLayout *orig_layout)
1160 {
1161         lglTemplateLayout *layout;
1162
1163         g_return_val_if_fail (orig_layout, NULL);
1164
1165         layout = g_new0 (lglTemplateLayout, 1);
1166
1167         /* copy contents */
1168         *layout = *orig_layout;
1169
1170         return layout;
1171 }
1172
1173
1174 /**
1175  * lgl_template_layout_free:
1176  *   @layout: Layout to free.
1177  *
1178  * This function frees all memory associated with given template layout structure.
1179  *
1180  */
1181 void
1182 lgl_template_layout_free (lglTemplateLayout *layout)
1183 {
1184         g_free (layout);
1185 }
1186
1187
1188 /**
1189  * lgl_template_markup_dup:
1190  *   @orig_markup: Markup to duplicate.
1191  *
1192  * This function duplicates a template markup structure.
1193  *
1194  * Returns:  a newly allocated #lglTemplateMarkup structure.
1195  *
1196  */
1197 lglTemplateMarkup *
1198 lgl_template_markup_dup (const lglTemplateMarkup *orig_markup)
1199 {
1200         lglTemplateMarkup *markup;
1201
1202         g_return_val_if_fail (orig_markup, NULL);
1203
1204         markup = g_new0 (lglTemplateMarkup, 1);
1205
1206         *markup = *orig_markup;
1207
1208         return markup;
1209 }
1210
1211
1212 /**
1213  * lgl_template_markup_free:
1214  *   @markup: Markup to free.
1215  *
1216  * This function frees all memory associated with given template markup structure.
1217  *
1218  */
1219 void
1220 lgl_template_markup_free (lglTemplateMarkup *markup)
1221 {
1222         g_free (markup);
1223 }
1224
1225
1226 static gint
1227 compare_origins (gconstpointer a,
1228                  gconstpointer b,
1229                  gpointer      user_data)
1230 {
1231         const lglTemplateOrigin *a_origin = a, *b_origin = b;
1232
1233         if ( a_origin->y < b_origin->y ) {
1234                 return -1;
1235         } else if ( a_origin->y > b_origin->y ) {
1236                 return +1;
1237         } else {
1238                 if ( a_origin->x < b_origin->x ) {
1239                         return -1;
1240                 } else if ( a_origin->x > b_origin->x ) {
1241                         return +1;
1242                 } else {
1243                         return 0; /* hopefully 2 labels won't have the same origin */
1244                 }
1245         }
1246 }
1247
1248
1249
1250 /*
1251  * Local Variables:       -- emacs
1252  * mode: C                -- emacs
1253  * c-basic-offset: 8      -- emacs
1254  * tab-width: 8           -- emacs
1255  * indent-tabs-mode: nil  -- emacs
1256  * End:                   -- emacs
1257  */