1 /*
2  * code128.c -- encoding for code128 (A, B, C)
3  *
4  * Copyright (c) 1999,2000 Alessandro Rubini (rubini@gnu.org)
5  * Copyright (c) 1999 Prosa Srl. (prosa@prosa.it)
6  * Copyright (c) 2000 Leonid A. Broukhis (leob@mailcom.com)
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <errno.h>
28 
29 #include "barcode.h"
30 
31 static char *codeset[] = {
32     "212222", "222122", "222221", "121223", "121322",  /*  0 -  4 */
33     "131222", "122213", "122312", "132212", "221213",
34     "221312", "231212", "112232", "122132", "122231",  /* 10 - 14 */
35     "113222", "123122", "123221", "223211", "221132",
36     "221231", "213212", "223112", "312131", "311222",  /* 20 - 24 */
37     "321122", "321221", "312212", "322112", "322211",
38     "212123", "212321", "232121", "111323", "131123",  /* 30 - 34 */
39     "131321", "112313", "132113", "132311", "211313",
40     "231113", "231311", "112133", "112331", "132131",  /* 40 - 44 */
41     "113123", "113321", "133121", "313121", "211331",
42     "231131", "213113", "213311", "213131", "311123",  /* 50 - 54 */
43     "311321", "331121", "312113", "312311", "332111",
44     "314111", "221411", "431111", "111224", "111422",  /* 60 - 64 */
45     "121124", "121421", "141122", "141221", "112214",
46     "112412", "122114", "122411", "142112", "142211",  /* 70 - 74 */
47     "241211", "221114", "413111", "241112", "134111",
48     "111242", "121142", "121241", "114212", "124112",  /* 80 - 84 */
49     "124211", "411212", "421112", "421211", "212141",
50     "214121", "412121", "111143", "111341", "131141",  /* 90 - 94 */
51     "114113", "114311", "411113", "411311", "113141",
52     "114131", "311141", "411131", "b1a4a2", "b1a2a4",  /* 100 - 104 */
53     "b1a2c2", "b3c1a1b"
54 };
55 
56 #define START_A 103
57 #define START_B 104
58 #define START_C 105
59 #define STOP    106
60 #define SHIFT    98 /* only A and B */
61 #define CODE_A  101 /* only B and C */
62 #define CODE_B  100 /* only A and C */
63 #define CODE_C   99 /* only A and B */
64 #define FUNC_1  102 /* all of them */
65 #define FUNC_2   97 /* only A and B */
66 #define FUNC_3   96 /* only A and B */
67 /* FUNC_4 is CODE_A when in A and CODE_B when in B */
68 
69 #define SYMBOL_WID 11 /* all of them are 11-bar wide */
70 
71 /*
72  * code 128-b includes all printable ascii chars
73  */
74 
Barcode_128b_verify(unsigned char * text)75 int Barcode_128b_verify(unsigned char *text)
76 {
77     if (text[0] == '\0')
78 	return -1;
79     while (*text && *text>=32 && !(*text&0x80))
80 	text++;
81     if (*text)
82 	return -1; /* a non-ascii char */
83     return 0; /* ok */
84 }
85 
Barcode_128b_encode(struct Barcode_Item * bc)86 int Barcode_128b_encode(struct Barcode_Item *bc)
87 {
88     static char *text;
89     static char *partial;  /* dynamic */
90     static char *textinfo; /* dynamic */
91     char *textptr;
92     int i, code, textpos, checksum = 0;
93 
94     if (bc->partial)
95 	free(bc->partial);
96     if (bc->textinfo)
97 	free(bc->textinfo);
98     bc->partial = bc->textinfo = NULL; /* safe */
99 
100     if (!bc->encoding)
101 	bc->encoding = strdup("code 128-B");
102 
103     text = bc->ascii;
104     if (!text) {
105         bc->error = EINVAL;
106         return -1;
107     }
108     /* the partial code is 6* (head + text + check + tail) + final + term. */
109     partial = malloc( (strlen(text) + 4) * 6 +2);
110     if (!partial) {
111         bc->error = errno;
112         return -1;
113     }
114 
115     /* the text information is at most "nnn:fff:c " * strlen +term */
116     textinfo = malloc(10*strlen(text) + 2);
117     if (!textinfo) {
118         bc->error = errno;
119         free(partial);
120         return -1;
121     }
122 
123     /* up to now, it was the same code as other encodings */
124 
125     strcpy(partial, "0"); /* the first space */
126     strcat(partial, codeset[START_B]);
127     checksum += START_B; /* the start char is counted in the checksum */
128     textptr = textinfo;
129     textpos = SYMBOL_WID;
130 
131     for (i=0; i<strlen(text); i++) {
132         if ( text[i] < 32 || (text[i] & 0x80)) {
133             bc->error = EINVAL; /* impossible if text is verified */
134             free(partial);
135             free(textinfo);
136             return -1;
137         }
138 	code = text[i]-32;
139 	strcat(partial, codeset[code]);
140 	checksum += code * (i+1); /* first * 1 + second * 2 + third * 3... */
141         sprintf(textptr, "%i:12:%c ", textpos, text[i]);
142         textptr += strlen(textptr);
143         textpos += SYMBOL_WID; /* width of each code */
144     }
145     /* Add the checksum, independent of BARCODE_NO_CHECKSUM */
146     checksum %= 103;
147     strcat(partial, codeset[checksum]);
148     /* and the end marker */
149     strcat(partial, codeset[STOP]);
150 
151     bc->partial = partial;
152     bc->textinfo = textinfo;
153 
154     return 0;
155 }
156 
157 /*
158  * code 128-c is only digits, but two per symbol
159  */
160 
Barcode_128c_verify(unsigned char * text)161 int Barcode_128c_verify(unsigned char *text)
162 {
163     if (text[0] == '\0')
164 	return -1;
165     /* must be an even number of digits */
166     if (strlen(text)%2)
167 	return -1;
168     /* and must be all digits */
169     for (; *text; text++)
170 	if (!isdigit(*text))
171 	    return -1;
172     return 0;
173 }
174 
Barcode_128c_encode(struct Barcode_Item * bc)175 int Barcode_128c_encode(struct Barcode_Item *bc)
176 {
177     static char *text;
178     static char *partial;  /* dynamic */
179     static char *textinfo; /* dynamic */
180     char *textptr;
181     int i, code, textpos, checksum = 0;
182 
183     if (bc->partial)
184 	free(bc->partial);
185     if (bc->textinfo)
186 	free(bc->textinfo);
187     bc->partial = bc->textinfo = NULL; /* safe */
188 
189     if (!bc->encoding)
190 	bc->encoding = strdup("code 128-C");
191 
192     text = bc->ascii;
193     if (!text) {
194         bc->error = EINVAL;
195         return -1;
196     }
197     /* the partial code is 6* (head + text + check + tail) + final + term. */
198     partial = malloc( (strlen(text) + 3) * 6 +2);
199     if (!partial) {
200         bc->error = errno;
201         return -1;
202     }
203 
204     /* the text information is at most "nnn.5:fff:c " * strlen +term */
205     textinfo = malloc(12*strlen(text) + 2);
206     if (!textinfo) {
207         bc->error = errno;
208         free(partial);
209         return -1;
210     }
211 
212     strcpy(partial, "0"); /* the first space */
213     strcat(partial, codeset[START_C]);
214     checksum += START_C; /* the start char is counted in the checksum */
215     textptr = textinfo;
216     textpos = SYMBOL_WID;
217 
218     for (i=0; text[i]; i+=2) {
219         if (!isdigit(text[i]) || !isdigit(text[i+1])) {
220             bc->error = EINVAL; /* impossible if text is verified */
221             free(partial);
222             free(textinfo);
223             return -1;
224         }
225         code = (text[i]-'0') * 10 + text[i+1]-'0';
226 	strcat(partial, codeset[code]);
227 	checksum += code * (i/2+1); /* first * 1 + second * 2 + third * 3... */
228 
229 	/* print as "%s", because we have ".5" positions */
230         sprintf(textptr, "%g:9:%c %g:9:%c ", (double)textpos, text[i],
231 		textpos + (double)SYMBOL_WID/2,	text[i+1]);
232         textptr += strlen(textptr);
233         textpos += SYMBOL_WID; /* width of each code */
234     }
235     /* Add the checksum, independent of BARCODE_NO_CHECKSUM */
236     checksum %= 103;
237     strcat(partial, codeset[checksum]);
238     /* and the end marker */
239     strcat(partial, codeset[STOP]);
240 
241     bc->partial = partial;
242     bc->textinfo = textinfo;
243 
244     return 0;
245 }
246 
247 /*
248  * generic (full-featured) code128 implementation: it selects between
249  * A, B, C according to the data being encoded. F1, F2, F3, F4 are expressed
250  * using ascii chars 0xc1, 0xc2, 0xc3, 0xc4 (0301, 0302, 0303, 0304).
251  * Char '\0' is expressed by 0x80 (0200).
252  */
253 
Barcode_128_verify(unsigned char * text)254 int Barcode_128_verify(unsigned char *text)
255 {
256     if (text[0] == '\0')
257 	return -1;
258     while (*text && (*text<=0x80 || (*text >= 0xc1 && *text <= 0xc4)))
259 	text++;
260     if (*text)
261 	return -1; /* unencodable character */
262     return 0; /* ok */
263 }
264 
265 
266 /*
267  * These functions are extracted from Barcode_128_encode for clarity.
268  * It deals with choosing the symbols used to represent the text
269  * and returns a dynamic array of integers, terminated by -1.
270  *
271  * The algorithm used in choosing the codes comes from App 2 of
272  * "El Codigo Estandar EAN/UCC 128", courtesy of AECOC, Spain.
273  * Thanks to Dani Pardo for getting permission and giving me a copy
274  * of the document
275  */
276 
277 #define NEED_CODE_A(c) ((c)<32 || (c)==0x80)
278 #define NEED_CODE_B(c) ((c)>=96 && (c)<128)
279 
Barcode_a_or_b(unsigned char * text)280 static int Barcode_a_or_b(unsigned char *text)
281 {
282     for ( ; *text; text++) {
283 	if (NEED_CODE_A(*text))
284 	    return 'A';
285 	if (NEED_CODE_B(*text))
286 	    return 'B';
287     }
288     return 0; /* any */
289 }
290 
291 /* code is either 'A' or 'B', and value must be valid */
Barcode_encode_as(int code,int value)292 static int Barcode_encode_as(int code, int value)
293 {
294 
295     /* first check the special chars */
296     if (value == 0xC1) return FUNC_1;
297     if (value == 0xC2) return FUNC_2;
298     if (value == 0xC3) return FUNC_3;
299     if (value == 0xC4) { /* F4 */
300 	if (code == 'A') return CODE_A;
301 	return CODE_B;
302     }
303 
304     /* then check ascii values */
305     if (value >= 0x20 && value <= 0x5F)
306 	return value - 0x20; /* both codes */
307     if (value == 0x80) return 64; /* code A */
308     if (value < 0x20) return value+64; /* code A */
309     if (value >= 0x60) return value - 0x20; /* code B */
310     /* can't happen */
311     return -1;
312 }
313 
Barcode_128_make_array(struct Barcode_Item * bc,int * lptr)314 static int *Barcode_128_make_array(struct Barcode_Item *bc, int *lptr)
315 {
316     int len, *codes;
317     unsigned char *s;
318     int i=0, j, code, checksum;
319 
320     /* allocate twice the text length + 5, as this is the worst case */
321     len = 2 * strlen(bc->ascii) + 5;
322     codes = malloc(len * sizeof(int));
323     s = bc->ascii;
324 
325     /* choose the starting code */
326     if (s[2]=='\0' && isdigit(s[0]) && isdigit(s[1])) {
327       code = 'C';
328     } else if (isdigit(s[0])&&isdigit(s[1]) && isdigit(s[2])&&isdigit(s[3])) {
329 	code = 'C';
330     } else {
331 	code = Barcode_a_or_b(s);
332 	if (!code) code = 'B'; /* default */
333     }
334     codes[i++] = START_A + code - 'A';
335 
336     for (s = bc->ascii; *s; /* increments are in the loop */) {
337 	switch(code) {
338 
339 	    case 'C':
340 		if (s[0] == 0xC1) { /* F1 is valid */
341 		    codes[i++] = FUNC_1;
342 		    s++;
343 		} else if (isdigit(s[0]) && isdigit(s[1])) {
344 		    /* encode two digits */
345 		    codes[i++] = (s[0]-'0') * 10 + s[1]-'0';
346 		    s += 2;
347 		} else {
348 		    /* change code */
349 		    code = Barcode_a_or_b(s);
350 		    if (!code) code = 'B';
351 		    codes[i++] = (code == 'A') ? CODE_A : CODE_B;
352 		}
353 		break;
354 
355 	    case 'B':
356 	    case 'A':
357 		for (j=0; isdigit(s[j]); j++)
358 		    ;
359 		if (j>=4) { /* if there are 4 or more digits, turn to C */
360 		    if (j&1) {
361 			/* odd number: encode one first */
362 			codes[i++] = *(s++) - ' ';
363 		    }
364 		    codes[i++] = CODE_C;
365 		    code = 'C';
366 		} else if (code == 'A' && NEED_CODE_B(*s)) {
367 		    /* check whether we should use SHIFT or change code */
368 		    j = Barcode_a_or_b(s+1);
369 		    if (j == 'B') {
370 			codes[i++] = CODE_B;
371 			code = 'B';
372 		    } else {
373 			codes[i++] = SHIFT;
374 			codes[i++] = Barcode_encode_as('B', *s);
375 			s++;
376 		    }
377 		} else if (code == 'B' && NEED_CODE_A(*s)) {
378 		    /* check whether we should use SHIFT or change code */
379 		    j = Barcode_a_or_b(s+1);
380 		    if (j == 'A') {
381 			codes[i++] = CODE_A;
382 			code = 'A';
383 		    } else {
384 			codes[i++] = SHIFT;
385 			codes[i++] = Barcode_encode_as('A', *s);
386 			s++;
387 		    }
388 		} else {
389 		    codes[i++] = Barcode_encode_as(code, *s);
390 		    s++;
391 		}
392 		break;
393 	}
394     }
395     /* add the checksum */
396     checksum = codes[0];
397     for (j=1; j<i; j++)
398 	checksum += j * codes[j];
399     checksum %= 103;
400     codes[i++] = checksum;
401     codes[i++] = STOP;
402     if (i > len) {
403 	fprintf(stderr, "impossible: length is > allocated len\n");
404     }
405     *lptr = i;
406     return codes;
407 }
408 
409 /*
410  * Encoding is tricky, in that we cannot print the ascii
411  * representation in an easy way. Therefore, just skip non-printable
412  * chars and try to fit the rest somehow.
413  */
Barcode_128_encode(struct Barcode_Item * bc)414 int Barcode_128_encode(struct Barcode_Item *bc)
415 {
416     static char *text;
417     static char *partial;  /* dynamic */
418     static char *textinfo; /* dynamic */
419     char *textptr;
420     int *codes; /* dynamic */
421     int i, c, len;
422     double textpos, size, step;
423 
424     if (bc->partial)
425 	free(bc->partial);
426     if (bc->textinfo)
427 	free(bc->textinfo);
428     bc->partial = bc->textinfo = NULL; /* safe */
429 
430     if (!bc->encoding)
431 	bc->encoding = strdup("code 128");
432 
433     text = bc->ascii;
434     if (!text) {
435         bc->error = EINVAL;
436         return -1;
437     }
438 
439     codes = Barcode_128_make_array(bc, &len);
440     if (!codes) return -1;
441 
442     /* the partial code is 6*codelen + ini + term (+margin) */
443     partial = malloc( 6 * len + 4);
444     if (!partial) {
445         bc->error = errno;
446 	free(codes);
447         return -1;
448     }
449 
450     /* the text information is at most "nnn.n:ff.f:c " * strlen +term */
451     textptr = textinfo = malloc(13*strlen(text) + 2);
452     if (!textinfo) {
453         bc->error = errno;
454         free(partial);
455 	free(codes);
456         return -1;
457     }
458 
459     /* up to now, it was almost the same code as other encodings */
460 
461     strcpy(partial, "0"); /* the first space */
462     for (i=0; i<len; i++) /* the symbols */
463 	strcat(partial, codeset[codes[i]]);
464 
465     /* avoid bars that fall lower than other bars */
466     for (i=0; partial[i]; i++)
467 	if (isalpha(partial[i]))
468 	    partial[i] += '1' - 'a';
469 
470     /*
471      * the accompanying text: reserve a space for every char.
472      * F[1-4] are rendered as spaces (separators), other unprintable chars
473      * are rendered as underscoress (placeholders)
474      */
475 
476     /*
477      * A size of 9 is good for code-C (used above), so 18 for each symbol,
478      * but we place an upper limit of 12 to avoid overlapping on the bars.
479      */
480     size = (int)(180.0 * (len-3) / strlen(text) + .5) / 10.0;
481     if (size > 12.0) size = 12.0;
482 
483     /* align the text to the left, using its natural size */
484     step = (int)(10 * (size/18.0 * SYMBOL_WID) + .5) / 10.0;
485     textpos = SYMBOL_WID;
486 
487     for (i=0; i<strlen(text); i++) {
488 	c = text[i];
489 	if (c < 32 || c == 0x80) c = '_'; /* not printable */
490 	if (c > 0xc0) c = ' '; /* F code */
491         sprintf(textptr, "%g:%g:%c ", textpos, size, c);
492         textptr += strlen(textptr);
493         textpos += step;
494     }
495 
496     bc->partial = partial;
497     bc->textinfo = textinfo;
498     free(codes);
499     return 0;
500 }
501 
502 /*
503  * A raw 128 code is given as a sequence of space separated numbers
504  * from 0 to 105, starting from the start code to be (Leonid)
505  */
506 
Barcode_128raw_verify(unsigned char * text)507 int Barcode_128raw_verify(unsigned char *text)
508 {
509     int n;
510     unsigned val;
511 
512     if (!strlen(text))
513 	return -1;
514     while (*text) {
515 	if (sscanf(text, "%u%n", &val, &n) < 1)
516 	    return -1;
517 	if (val > 105)
518 	    return -1;
519 	text += n;
520     }
521     return 0;
522 }
523 
Barcode_128raw_encode(struct Barcode_Item * bc)524 int Barcode_128raw_encode(struct Barcode_Item *bc)
525 {
526     static char *text;
527     static char *partial;  /* dynamic */
528     static char *textinfo; /* dynamic */
529     char *textptr;
530     int i, n, count, code, textpos, checksum = 0;
531 
532     if (bc->partial)
533 	free(bc->partial);
534     if (bc->textinfo)
535 	free(bc->textinfo);
536     bc->partial = bc->textinfo = NULL; /* safe */
537 
538     if (!bc->encoding)
539 	bc->encoding = strdup("128raw");
540 
541     text = bc->ascii;
542     if (!text) {
543         bc->error = EINVAL;
544         return -1;
545     }
546     /*
547      * length of partial code is unknown in advance, but it is
548      * at most  6* (1+text/2 + check + tail) + final + terminator
549      */
550     partial = malloc( (3+ strlen(text)/2) * 6 + 2);
551     if (!partial) {
552         bc->error = errno;
553         return -1;
554     }
555 
556     /* the text information is at most "nnn.5:fff:c " * 1+strlen/2 +term */
557     textinfo = malloc(12 * (1+strlen(text)/2) + 2);
558     if (!textinfo) {
559         bc->error = errno;
560         free(partial);
561         return -1;
562     }
563 
564     strcpy(partial, "0"); /* the first space */
565     textptr = textinfo;
566     textpos = 0;
567 
568     for (i=0, count = 0; i < strlen(text); count++) {
569 	if (sscanf(text + i, "%u%n", &code, &n) < 1) {
570             bc->error = EINVAL; /* impossible if text is verified */
571             free(partial);
572             free(textinfo);
573             return -1;
574 	}
575 	strcat(partial, codeset[code]);
576 
577 	/*
578 	 * since the start code is part of the "raw" input, it is
579 	 * counted in the checksum by itself
580 	 */
581 	if (!count) checksum += code; /* the start code */
582 	else        checksum += code * count; /* first * 1 + second * 2 ... */
583 
584 	/*
585 	 * print as "%s", because we have ".5" positions
586 	 * also, use a size of 9 like codeC above, as each symbol is
587 	 * represented by two chars
588 	 */
589         sprintf(textptr, "%g:9:%c %g:9:%c ", (double)textpos,
590 		code >= 100 ? 'A' : code/10 + '0',
591 		textpos + (double)SYMBOL_WID/2,	code%10 + '0');
592         textptr += strlen(textptr);
593         textpos += SYMBOL_WID; /* width of each code */
594 	i += n;
595     }
596     /* Add the checksum, independent of BARCODE_NO_CHECKSUM */
597     checksum %= 103;
598     strcat(partial, codeset[checksum]);
599     /* and the end marker */
600     strcat(partial, codeset[STOP]);
601 
602     bc->partial = partial;
603     bc->textinfo = textinfo;
604 
605     return 0;
606 }
607 
608