]> git.sur5r.net Git - glabels/blob - src/bc.c
Imported Upstream version 2.2.8
[glabels] / src / bc.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2
3 /*
4  *  (GLABELS) Label and Business Card Creation program for GNOME
5  *
6  *  bc.c:  GLabels barcode module
7  *
8  *  Copyright (C) 2001-2003  Jim Evins <evins@snaught.com>.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
23  */
24 #include <config.h>
25
26 #include "bc.h"
27
28 #include <glib/gi18n.h>
29 #include <glib/gmem.h>
30 #include <glib/gstrfuncs.h>
31 #include <glib/gmessages.h>
32
33 #include "bc-postnet.h"
34 #include "bc-gnubarcode.h"
35 #include "bc-iec16022.h"
36
37 #include "debug.h"
38
39 /*========================================================*/
40 /* Private macros and constants.                          */
41 /*========================================================*/
42
43 /*========================================================*/
44 /* Private types.                                         */
45 /*========================================================*/
46
47 typedef struct {
48         gchar            *id;
49         gchar            *name;
50         glBarcodeNewFunc  new;
51         gboolean          can_text;
52         gboolean          text_optional;
53         gboolean          can_checksum;
54         gboolean          checksum_optional;
55         gchar            *default_digits;
56         gboolean          can_freeform;
57         guint             prefered_n;
58 } Backend;
59
60
61 /*========================================================*/
62 /* Private globals.                                       */
63 /*========================================================*/
64
65 static const Backend backends[] = {
66
67         { "POSTNET", N_("POSTNET (any)"), gl_barcode_postnet_new,
68           FALSE, FALSE, TRUE, FALSE, "12345-6789-12", FALSE, 11},
69
70         { "POSTNET-5", N_("POSTNET-5 (ZIP only)"), gl_barcode_postnet_new,
71           FALSE, FALSE, TRUE, FALSE, "12345", FALSE, 5},
72
73         { "POSTNET-9", N_("POSTNET-9 (ZIP+4)"), gl_barcode_postnet_new,
74           FALSE, FALSE, TRUE, FALSE, "12345-6789", FALSE, 9},
75
76         { "POSTNET-11", N_("POSTNET-11 (DPBC)"), gl_barcode_postnet_new,
77           FALSE, FALSE, TRUE, FALSE, "12345-6789-12", FALSE, 11},
78
79         { "CEPNET", N_("CEPNET"), gl_barcode_postnet_new,
80           FALSE, FALSE, TRUE, FALSE, "12345-678", FALSE, 8},
81
82         { "EAN", N_("EAN (any)"), gl_barcode_gnubarcode_new,
83           TRUE, TRUE, TRUE, FALSE, "000000000000 00000", FALSE, 17},
84
85         { "EAN-8", N_("EAN-8"), gl_barcode_gnubarcode_new,
86           TRUE, TRUE, TRUE, FALSE, "0000000", FALSE, 7},
87
88         { "EAN-8+2", N_("EAN-8 +2"), gl_barcode_gnubarcode_new,
89           TRUE, TRUE, TRUE, FALSE, "0000000 00", FALSE, 9},
90
91         { "EAN-8+5", N_("EAN-8 +5"), gl_barcode_gnubarcode_new,
92           TRUE, TRUE, TRUE, FALSE, "0000000 00000", FALSE, 12},
93
94         { "EAN-13", N_("EAN-13"), gl_barcode_gnubarcode_new,
95           TRUE, TRUE, TRUE, FALSE, "000000000000", FALSE, 12},
96
97         { "EAN-13+2", N_("EAN-13 +2"), gl_barcode_gnubarcode_new,
98           TRUE, TRUE, TRUE, FALSE, "000000000000 00", FALSE, 14},
99
100         { "EAN-13+5", N_("EAN-13 +5"), gl_barcode_gnubarcode_new,
101           TRUE, TRUE, TRUE, FALSE, "000000000000 00000", FALSE, 17},
102
103         { "UPC", N_("UPC (UPC-A or UPC-E)"), gl_barcode_gnubarcode_new,
104           TRUE, TRUE, TRUE, FALSE, "00000000000 00000", FALSE, 16},
105
106         { "UPC-A", N_("UPC-A"), gl_barcode_gnubarcode_new,
107           TRUE, TRUE, TRUE, FALSE, "00000000000", FALSE, 11},
108
109         { "UPC-A+2", N_("UPC-A +2"), gl_barcode_gnubarcode_new,
110           TRUE, TRUE, TRUE, FALSE, "00000000000 00", FALSE, 13},
111
112         { "UPC-A+5", N_("UPC-A +5"), gl_barcode_gnubarcode_new,
113           TRUE, TRUE, TRUE, FALSE, "00000000000 00000", FALSE, 16},
114
115         { "UPC-E", N_("UPC-E"), gl_barcode_gnubarcode_new,
116           TRUE, TRUE, TRUE, FALSE, "000000", FALSE, 6},
117
118         { "UPC-E+2", N_("UPC-E +2"), gl_barcode_gnubarcode_new,
119           TRUE, TRUE, TRUE, FALSE, "000000 00", FALSE, 8},
120
121         { "UPC-E+5", N_("UPC-E +5"), gl_barcode_gnubarcode_new,
122           TRUE, TRUE, TRUE, FALSE, "000000 00000", FALSE, 11},
123
124         { "ISBN", N_("ISBN"), gl_barcode_gnubarcode_new,
125           TRUE, TRUE, TRUE, TRUE, "0-00000-000-0", FALSE, 10},
126
127         { "ISBN+5", N_("ISBN +5"), gl_barcode_gnubarcode_new,
128           TRUE, TRUE, TRUE, TRUE, "0-00000-000-0 00000", FALSE, 15},
129
130         { "Code39", N_("Code 39"), gl_barcode_gnubarcode_new,
131           TRUE, TRUE, TRUE, TRUE, "0000000000", TRUE, 10},
132
133         { "Code128", N_("Code 128"), gl_barcode_gnubarcode_new,
134           TRUE, TRUE, TRUE, TRUE, "0000000000", TRUE, 10},
135
136         { "Code128C", N_("Code 128C"), gl_barcode_gnubarcode_new,
137           TRUE, TRUE, TRUE, FALSE, "0000000000", TRUE, 10},
138
139         { "Code128B", N_("Code 128B"), gl_barcode_gnubarcode_new,
140           TRUE, TRUE, TRUE, TRUE, "0000000000", TRUE, 10},
141
142         { "I25", N_("Interleaved 2 of 5"), gl_barcode_gnubarcode_new,
143           TRUE, TRUE, TRUE, TRUE, "0000000000", TRUE, 10},
144
145         { "CBR", N_("Codabar"), gl_barcode_gnubarcode_new,
146           TRUE, TRUE, TRUE, TRUE, "0000000000", TRUE, 10},
147
148         { "MSI", N_("MSI"), gl_barcode_gnubarcode_new,
149           TRUE, TRUE, TRUE, TRUE, "0000000000", TRUE, 10},
150
151         { "PLS", N_("Plessey"), gl_barcode_gnubarcode_new,
152           TRUE, TRUE, TRUE, TRUE, "0000000000", TRUE, 10},
153
154         { "IEC16022", N_("IEC16022 (DataMatrix)"), gl_barcode_iec16022_new,
155           FALSE, FALSE, TRUE, FALSE, "12345678", TRUE, 8},
156
157         { NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE, NULL, FALSE, 0}
158
159 };
160
161 /*========================================================*/
162 /* Private function prototypes.                           */
163 /*========================================================*/
164
165 \f
166 /*---------------------------------------------------------------------------*/
167 /* Convert id to index into above table.                                     */
168 /*---------------------------------------------------------------------------*/
169 static gint
170 id_to_index (const gchar *id)
171 {
172         gint i;
173
174         if (id == 0) {
175                 return 0; /* NULL request default. I.e., the first element. */
176         }
177
178         for (i=0; backends[i].id != NULL; i++) {
179                 if (g_strcasecmp (id, backends[i].id) == 0) {
180                         return i;
181                 }
182         }
183
184         g_message( "Unknown barcode id \"%s\"", id );
185         return 0;
186 }
187
188 /*---------------------------------------------------------------------------*/
189 /* Convert name to index into above table.                                   */
190 /*---------------------------------------------------------------------------*/
191 static gint
192 name_to_index (const gchar *name)
193 {
194         gint i;
195
196         g_return_val_if_fail (name!=NULL, 0);
197
198         for (i=0; backends[i].id != NULL; i++) {
199                 if (g_strcasecmp (name, backends[i].name) == 0) {
200                         return i;
201                 }
202         }
203
204         g_message( "Unknown barcode name \"%s\"", name );
205         return 0;
206 }
207
208 /*****************************************************************************/
209 /* Call appropriate barcode backend to create barcode in intermediate format.*/
210 /*****************************************************************************/
211 glBarcode *
212 gl_barcode_new (const gchar    *id,
213                 gboolean        text_flag,
214                 gboolean        checksum_flag,
215                 gdouble         w,
216                 gdouble         h,
217                 const gchar    *digits)
218 {
219         glBarcode *gbc;
220         gint       i;
221
222         g_return_val_if_fail (digits!=NULL, NULL);
223
224         i = id_to_index (id);
225         gbc = backends[i].new (backends[i].id,
226                                text_flag,
227                                checksum_flag,
228                                w,
229                                h,
230                                digits);
231
232         return gbc;
233 }
234
235 /*****************************************************************************/
236 /* Free previously created barcode.                                          */
237 /*****************************************************************************/
238 void
239 gl_barcode_free (glBarcode **gbc)
240 {
241         GList *p;
242
243         if (*gbc != NULL) {
244
245                 for (p = (*gbc)->lines; p != NULL; p = p->next) {
246                         g_free (p->data);
247                         p->data = NULL;
248                 }
249                 g_list_free ((*gbc)->lines);
250                 (*gbc)->lines = NULL;
251
252                 for (p = (*gbc)->chars; p != NULL; p = p->next) {
253                         g_free (p->data);
254                         p->data = NULL;
255                 }
256                 g_list_free ((*gbc)->chars);
257                 (*gbc)->chars = NULL;
258
259                 g_free (*gbc);
260                 *gbc = NULL;
261         }
262 }
263
264 /*****************************************************************************/
265 /* Get a list of names for valid barcode styles.                             */
266 /*****************************************************************************/
267 GList *
268 gl_barcode_get_styles_list  (void)
269 {
270         gint   i;
271         GList *list = NULL;
272
273         for (i=0; backends[i].id != NULL; i++) {
274                 list = g_list_append (list, g_strdup (backends[i].name));
275         }
276
277         return list;
278 }
279
280 /*****************************************************************************/
281 /* Free up a previously allocated list of style names.                       */
282 /*****************************************************************************/
283 void
284 gl_barcode_free_styles_list (GList *styles_list)
285 {
286         GList *p;
287
288         for (p=styles_list; p != NULL; p=p->next) {
289                 g_free (p->data);
290                 p->data = NULL;
291         }
292
293         g_list_free (styles_list);
294 }
295
296
297 /*****************************************************************************/
298 /* Return an appropriate set of digits for the given barcode style.          */
299 /*****************************************************************************/
300 gchar *
301 gl_barcode_default_digits (const gchar *id,
302                            guint        n)
303 {
304         int i;
305
306         i = id_to_index (id);
307
308         if (backends[i].can_freeform) {
309
310                 return g_strnfill (MAX (n,1), '0');
311
312         } else {
313
314                 return g_strdup (backends[i].default_digits);
315
316         }
317 }
318
319 /*****************************************************************************/
320 /* Query text capabilities.                                                  */
321 /*****************************************************************************/
322 gboolean
323 gl_barcode_can_text (const gchar *id)
324 {
325         return backends[id_to_index (id)].can_text;
326 }
327
328 gboolean
329 gl_barcode_text_optional (const gchar *id)
330 {
331         return backends[id_to_index (id)].text_optional;
332 }
333
334 /*****************************************************************************/
335 /* Query checksum capabilities.                                              */
336 /*****************************************************************************/
337 gboolean
338 gl_barcode_can_csum (const gchar *id)
339 {
340         return backends[id_to_index (id)].can_checksum;
341 }
342
343 gboolean
344 gl_barcode_csum_optional (const gchar *id)
345 {
346         return backends[id_to_index (id)].checksum_optional;
347 }
348
349
350 /*****************************************************************************/
351 /* Query if freeform input is allowed.                                       */
352 /*****************************************************************************/
353 gboolean
354 gl_barcode_can_freeform     (const gchar    *id)
355 {
356         return backends[id_to_index (id)].can_freeform;
357 }
358
359 /*****************************************************************************/
360 /* Query prefered number of digits of input.                                 */
361 /*****************************************************************************/
362 guint
363 gl_barcode_get_prefered_n (const gchar    *id)
364 {
365         return backends[id_to_index (id)].prefered_n;
366 }
367
368 /*****************************************************************************/
369 /* Convert style to text.                                                    */
370 /*****************************************************************************/
371 const gchar *
372 gl_barcode_id_to_name (const gchar *id)
373 {
374         return backends[id_to_index (id)].name;
375 }
376
377 /*****************************************************************************/
378 /* Convert name to style.                                                    */
379 /*****************************************************************************/
380 const gchar *
381 gl_barcode_name_to_id (const gchar *name)
382 {
383         g_return_val_if_fail (name!=NULL, backends[0].id);
384
385         return backends[name_to_index (name)].id;
386 }