]> git.sur5r.net Git - glabels/blob - glabels2/barcode-0.98/code39.c
2007-04-30 Jim Evins <evins@snaught.com>
[glabels] / glabels2 / barcode-0.98 / code39.c
1 /*
2  * code39.c -- encoding for code39
3  *
4  * Copyright (c) 1999 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
31 /* this is ordered in decades to simplify encoding */
32 static char alphabet[] = 
33    "1234567890" "ABCDEFGHIJ" "KLMNOPQRST" "UVWXYZ-. *" "$/+%";
34
35 /* the checksum alphabet has a different order */
36 static char checkbet[] = 
37    "0123456789" "ABCDEFGHIJ" "KLMNOPQRST" "UVWXYZ-. $" "/+%";
38
39 /* The first 40 symbols repeat this bar pattern */
40 static char *bars[] = {
41    "31113","13113","33111","11313","31311",
42    "13311","11133","31131","13131","11331"};
43
44 /* The first 4 decades use these space patterns */
45 static char *spaces[] = {"1311","1131","1113","3111"};
46
47 /* the last four symbols are special */
48 static char *specialbars[] = {
49    "11111","11111","11111","11111"};
50
51 static char *specialspaces[] = {
52    "3331","3313","3133","1333"};
53
54 static char *fillers[]= {
55     "0a3a1c1c1a",
56     "1a3a1c1c1a"
57 };
58
59
60 /*
61  * Check that the text can be encoded. Returns 0 or -1.
62  * If it's all lowecase convert to uppercase and accept it
63  */
64 int Barcode_39_verify(unsigned char *text)
65 {
66     int i, lower=0, upper=0;
67
68     if (text[0] == '\0')
69         return -1;
70     for (i=0; text[i]; i++) {
71         if (isupper(text[i])) upper++;
72         if (islower(text[i])) lower++;
73         if (!strchr(alphabet,toupper(text[i])))
74             return -1;
75     }
76     if (lower && upper)
77         return -1;
78     return 0;
79 }
80
81 static int add_one(char *ptr, int code)
82 {
83     char *b, *s;
84
85     if (code < 40) {
86         b = bars[code%10];
87         s = spaces[code/10];
88     } else {
89         b = specialbars[code-40];
90         s = specialspaces[code-40];
91     }
92     sprintf(ptr,"1%c%c%c%c%c%c%c%c%c", /* separator */
93             b[0], s[0], b[1], s[1], b[2], s[2],
94             b[3], s[3], b[4]);
95     return 0;
96 }
97
98 /*
99  * The encoding functions fills the "partial" and "textinfo" fields.
100  * Lowercase chars are converted to uppercase
101  */
102 int Barcode_39_encode(struct Barcode_Item *bc)
103 {
104     static char *text;
105     static char *partial;  /* dynamic */
106     static char *textinfo; /* dynamic */
107     char *c, *ptr, *textptr;
108     int i, code, textpos, checksum = 0;
109
110     if (bc->partial)
111         free(bc->partial);
112     if (bc->textinfo)
113         free(bc->textinfo);
114     bc->partial = bc->textinfo = NULL; /* safe */
115
116     if (!bc->encoding)
117         bc->encoding = strdup("code 39");
118
119     text = bc->ascii;
120     if (!text) {
121         bc->error = EINVAL;
122         return -1;
123     }
124     /* the partial code is 10* (head + text + check + tail) + margin + term. */
125     partial = malloc( (strlen(text) + 3) * 10 +2);
126     if (!partial) {
127         bc->error = errno;
128         return -1;
129     }
130
131     /* the text information is at most "nnn:fff:c " * strlen +term */
132     textinfo = malloc(10*strlen(text) + 2);
133     if (!textinfo) {
134         bc->error = errno;
135         free(partial);
136         return -1;
137     }
138
139     strcpy(partial, fillers[0]);
140     ptr = partial + strlen(partial);
141     textptr = textinfo;
142     textpos = 22;
143
144     for (i=0; text[i]; i++) {
145         c = strchr(alphabet, toupper(text[i]));
146         if (!c) {
147             bc->error = EINVAL; /* impossible if text is verified */
148             free(partial);
149             free(textinfo);
150             return -1;
151         }
152         code = c - alphabet;
153         add_one(ptr, code);
154         c = strchr(checkbet,*c);
155         if (c) /* the '*' is not there */
156             checksum += (c-checkbet);
157         sprintf(textptr, "%i:12:%c ", textpos, toupper(text[i]));
158         
159         textpos += 16; /* width of each code */
160         textptr += strlen(textptr);
161         ptr += strlen(ptr); 
162     }
163     /* Add the checksum */
164     if ( (bc->flags & BARCODE_NO_CHECKSUM)==0 ) {
165         code = (strchr(alphabet, checkbet[checksum % 43]) - alphabet);
166         add_one(ptr, code);
167     }
168     strcat(ptr, fillers[1]); /* end */
169     bc->partial = partial;
170     bc->textinfo = textinfo;
171
172     return 0;
173 }