]> git.sur5r.net Git - glabels/blob - barcode-0.98/i25.c
Imported Upstream version 2.2.8
[glabels] / barcode-0.98 / i25.c
1 /*
2  * i25.c -- "interleaved 2 of 5"
3  *
4  * Copyright (c) 1999,2000 Alessandro Rubini (rubini@gnu.org)
5  * Copyright (c) 1999      Prosa Srl. (prosa@prosa.it)
6  *
7  *   This program is free software; you can redistribute it and/or modify
8  *   it under the terms of the GNU General Public License as published by
9  *   the Free Software Foundation; either version 2 of the License, or
10  *   (at your option) any later version.
11  *
12  *   This program 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 General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <errno.h>
27
28 #include "barcode.h"
29
30 static char *codes[] = {
31     "11331", "31113", "13113", "33111", "11313",
32     "31311", "13311", "11133", "31131", "13131"
33 };
34
35 static char *guard[] = {"a1a1", "c1a"}; /* begin end */
36
37 int Barcode_i25_verify(unsigned char *text)
38 {
39     if (!text[0])
40         return -1;
41     while (*text && isdigit(*text))
42         text++;
43     if (*text)
44         return -1; /* a non-digit char */
45     return 0; /* ok */
46 }
47
48 int Barcode_i25_encode(struct Barcode_Item *bc)
49 {
50     unsigned char *text;
51     unsigned char *partial;  /* dynamic */
52     unsigned char *textinfo; /* dynamic */
53     unsigned char *textptr, *p1, *p2, *pd;
54     int i, len, sum[2], textpos, usesum = 0;
55
56     if (bc->partial)
57         free(bc->partial);
58     if (bc->textinfo)
59         free(bc->textinfo);
60     bc->partial = bc->textinfo = NULL; /* safe */
61
62     if (!bc->encoding)
63         bc->encoding = strdup("interleaved 2 of 5");
64
65     text = bc->ascii;
66     if (!bc->ascii) {
67         bc->error = EINVAL;
68         return -1;
69     }
70
71     if ((bc->flags & BARCODE_NO_CHECKSUM)) usesum = 0; else usesum = 1;
72
73     /* create the real text string, padded to an even number of digits */
74     text = malloc(strlen(bc->ascii) + 3); /* leading 0, checksum, term. */
75     if (!text) {
76         bc->error = errno;
77         return -1;
78     }
79     /* add the leading 0 if needed */
80     i = strlen(bc->ascii) + usesum;
81     if (i % 2) {
82         /* add a leading 0 */
83         text[0] = '0';
84         strcpy(text+1, bc->ascii);
85     } else {
86         strcpy(text, bc->ascii);
87     }
88     /* add the trailing checksum if needed, the leading 0 is ignored */
89     if (usesum) {
90         sum[0] = sum[1] = 0;
91         for (i=0; text[i]; i++) 
92             sum[i%2] += text[i]-'0';
93         /*
94          * The "even" sum must be multiplied by three, and the *
95          * rightmost digit is defined as "even". The digits' position
96          * is already correct, whether or not we added a leading zero.
97          * (e.g., they are in pos. 0..4 or 1..4 of the string)
98          */
99         i = sum[0] * 3 + sum[1];
100         strcat(text, "0");
101         text[strlen(text)-1] += (10 - (i%10)) % 10;
102     }
103
104     /* the partial code is 5 * (text + check) + 4(head) + 3(tail) + term. */
105     partial = malloc( (strlen(text) + 3) * 5 +2); /* be large... */
106     if (!partial) {
107         bc->error = errno;
108         free(text);
109         return -1;
110     }
111
112     /* the text information is at most "nnn:fff:c " * (strlen+1) +term */
113     textinfo = malloc(10*(strlen(text)+1) + 2);
114     if (!textinfo) {
115         bc->error = errno;
116         free(partial);
117         free(text);
118         return -1;
119     }
120
121
122     strcpy(partial, "0"); /* the first space */
123     strcat(partial, guard[0]); /* start */
124     textpos = 4; /* width of initial guard */
125     textptr = textinfo;
126
127     len = strlen(text);
128     for (i=0; i<len; i+=2) {
129         if (!isdigit(text[i]) || !isdigit(text[i+1])) {
130             bc->error = EINVAL; /* impossible if text is verified */
131             free(partial);
132             free(textinfo);
133             free(text);
134             return -1;
135         }
136         /* interleave two digits */
137         p1 = codes[text[i]-'0'];
138         p2 = codes[text[i+1]-'0'];
139         pd = partial + strlen(partial); /* destination */
140         while (*p1) {
141             *(pd++) = *(p1++);
142             *(pd++) = *(p2++);
143         }
144         *pd = '\0';
145         /* and print the ascii text (but don't print the checksum, if any */
146         if (usesum && strlen(text+i)==2) {
147             /* print only one digit, discard the checksum */
148             sprintf(textptr, "%i:12:%c ", textpos, text[i]);
149         } else {
150             sprintf(textptr, "%i:12:%c %i:12:%c ", textpos, text[i],
151                     textpos+9, text[i+1]);
152         }
153         textpos += 18; /* width of two codes */
154         textptr += strlen(textptr);
155     }
156     strcat(partial, guard[1]);
157
158     bc->partial = partial;
159     bc->textinfo = textinfo;
160     free(text);
161
162     return 0;
163 }
164