]> git.sur5r.net Git - iec16022/blob - iec16022ecc200.c
Import Debian changes 0.2.4-1.2
[iec16022] / iec16022ecc200.c
1 /**
2  *
3  * IEC16022 bar code generation
4  * Adrian Kennard, Andrews & Arnold Ltd
5  * with help from Cliff Hones on the RS coding
6  *
7  * (c) 2004 Adrian Kennard, Andrews & Arnold Ltd
8  * (c) 2006-2007 Stefan Schmidt <stefan@datenfreihafen.org>
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
23  *
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <time.h>
31 #include <popt.h>
32 #include <malloc.h>
33 #include "reedsol.h"
34 #include "iec16022ecc200.h"
35
36 static struct ecc200matrix_s {
37         int H, W;
38         int FH, FW;
39         int bytes;
40         int datablock, rsblock;
41 } ecc200matrix[] = {
42         10, 10, 10, 10, 3, 3, 5,        //
43             12, 12, 12, 12, 5, 5, 7,    //
44             8, 18, 8, 18, 5, 5, 7,      //
45             14, 14, 14, 14, 8, 8, 10,   //
46             8, 32, 8, 16, 10, 10, 11,   //
47             16, 16, 16, 16, 12, 12, 12, //
48             12, 26, 12, 26, 16, 16, 14, //
49             18, 18, 18, 18, 18, 18, 14, //
50             20, 20, 20, 20, 22, 22, 18, //
51             12, 36, 12, 18, 22, 22, 18, //
52             22, 22, 22, 22, 30, 30, 20, //
53             16, 36, 16, 18, 32, 32, 24, //
54             24, 24, 24, 24, 36, 36, 24, //
55             26, 26, 26, 26, 44, 44, 28, //
56             16, 48, 16, 24, 49, 49, 28, //
57             32, 32, 16, 16, 62, 62, 36, //
58             36, 36, 18, 18, 86, 86, 42, //
59             40, 40, 20, 20, 114, 114, 48,       //
60             44, 44, 22, 22, 144, 144, 56,       //
61             48, 48, 24, 24, 174, 174, 68,       //
62             52, 52, 26, 26, 204, 102, 42,       //
63             64, 64, 16, 16, 280, 140, 56,       //
64             72, 72, 18, 18, 368, 92, 36,        //
65             80, 80, 20, 20, 456, 114, 48,       //
66             88, 88, 22, 22, 576, 144, 56,       //
67             96, 96, 24, 24, 696, 174, 68,       //
68             104, 104, 26, 26, 816, 136, 56,     //
69             120, 120, 20, 20, 1050, 175, 68,    //
70             132, 132, 22, 22, 1304, 163, 62,    //
71             144, 144, 24, 24, 1558, 156, 62,    // 156*4+155*2
72             0                   // terminate
73 };
74
75  // simple checked response malloc
76 static void *safemalloc(int n)
77 {
78         void *p = malloc(n);
79         if (!p) {
80                 fprintf(stderr, "Malloc(%d) failed\n", n);
81                 exit(1);
82         }
83         return p;
84 }
85
86 // Annex M placement alorithm low level
87 static void ecc200placementbit(int *array, int NR, int NC, int r, int c,
88                                int p, char b)
89 {
90         if (r < 0) {
91                 r += NR;
92                 c += 4 - ((NR + 4) % 8);
93         }
94         if (c < 0) {
95                 c += NC;
96                 r += 4 - ((NC + 4) % 8);
97         }
98         array[r * NC + c] = (p << 3) + b;
99 }
100
101 static void ecc200placementblock(int *array, int NR, int NC, int r,
102                                  int c, int p)
103 {
104         ecc200placementbit(array, NR, NC, r - 2, c - 2, p, 7);
105         ecc200placementbit(array, NR, NC, r - 2, c - 1, p, 6);
106         ecc200placementbit(array, NR, NC, r - 1, c - 2, p, 5);
107         ecc200placementbit(array, NR, NC, r - 1, c - 1, p, 4);
108         ecc200placementbit(array, NR, NC, r - 1, c - 0, p, 3);
109         ecc200placementbit(array, NR, NC, r - 0, c - 2, p, 2);
110         ecc200placementbit(array, NR, NC, r - 0, c - 1, p, 1);
111         ecc200placementbit(array, NR, NC, r - 0, c - 0, p, 0);
112 }
113
114 static void ecc200placementcornerA(int *array, int NR, int NC, int p)
115 {
116         ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
117         ecc200placementbit(array, NR, NC, NR - 1, 1, p, 6);
118         ecc200placementbit(array, NR, NC, NR - 1, 2, p, 5);
119         ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
120         ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
121         ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
122         ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
123         ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
124 }
125
126 static void ecc200placementcornerB(int *array, int NR, int NC, int p)
127 {
128         ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
129         ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
130         ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
131         ecc200placementbit(array, NR, NC, 0, NC - 4, p, 4);
132         ecc200placementbit(array, NR, NC, 0, NC - 3, p, 3);
133         ecc200placementbit(array, NR, NC, 0, NC - 2, p, 2);
134         ecc200placementbit(array, NR, NC, 0, NC - 1, p, 1);
135         ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
136 }
137
138 static void ecc200placementcornerC(int *array, int NR, int NC, int p)
139 {
140         ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
141         ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
142         ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
143         ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
144         ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
145         ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
146         ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
147         ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
148 }
149
150 static void ecc200placementcornerD(int *array, int NR, int NC, int p)
151 {
152         ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
153         ecc200placementbit(array, NR, NC, NR - 1, NC - 1, p, 6);
154         ecc200placementbit(array, NR, NC, 0, NC - 3, p, 5);
155         ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
156         ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
157         ecc200placementbit(array, NR, NC, 1, NC - 3, p, 2);
158         ecc200placementbit(array, NR, NC, 1, NC - 2, p, 1);
159         ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
160 }
161
162 // Annex M placement alorithm main function
163 static void ecc200placement(int *array, int NR, int NC)
164 {
165         int r, c, p;
166         // invalidate
167         for (r = 0; r < NR; r++)
168                 for (c = 0; c < NC; c++)
169                         array[r * NC + c] = 0;
170         // start
171         p = 1;
172         r = 4;
173         c = 0;
174         do {
175                 // check corner
176                 if (r == NR && !c)
177                         ecc200placementcornerA(array, NR, NC, p++);
178                 if (r == NR - 2 && !c && NC % 4)
179                         ecc200placementcornerB(array, NR, NC, p++);
180                 if (r == NR - 2 && !c && (NC % 8) == 4)
181                         ecc200placementcornerC(array, NR, NC, p++);
182                 if (r == NR + 4 && c == 2 && !(NC % 8))
183                         ecc200placementcornerD(array, NR, NC, p++);
184                 // up/right
185                 do {
186                         if (r < NR && c >= 0 && !array[r * NC + c])
187                                 ecc200placementblock(array, NR, NC, r, c, p++);
188                         r -= 2;
189                         c += 2;
190                 }
191                 while (r >= 0 && c < NC);
192                 r++;
193                 c += 3;
194                 // down/left
195                 do {
196                         if (r >= 0 && c < NC && !array[r * NC + c])
197                                 ecc200placementblock(array, NR, NC, r, c, p++);
198                         r += 2;
199                         c -= 2;
200                 }
201                 while (r < NR && c >= 0);
202                 r += 3;
203                 c++;
204         }
205         while (r < NR || c < NC);
206         // unfilled corner
207         if (!array[NR * NC - 1])
208                 array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
209 }
210
211 // calculate and append ecc code, and if necessary interleave
212 static void ecc200(unsigned char *binary, int bytes, int datablock, int rsblock)
213 {
214         int blocks = (bytes + 2) / datablock, b;
215         rs_init_gf(0x12d);
216         rs_init_code(rsblock, 1);
217         for (b = 0; b < blocks; b++) {
218                 unsigned char buf[256], ecc[256];
219                 int n, p = 0;
220                 for (n = b; n < bytes; n += blocks)
221                         buf[p++] = binary[n];
222                 rs_encode(p, buf, ecc);
223                 p = rsblock - 1;        // comes back reversed
224                 for (n = b; n < rsblock * blocks; n += blocks)
225                         binary[bytes + n] = ecc[p--];
226         }
227 }
228
229 /*
230  * perform encoding for ecc200, source s len sl, to target t len tl, using
231  * optional encoding control string e return 1 if OK, 0 if failed. Does all
232  * necessary padding to tl
233  */
234
235 char ecc200encode(unsigned char *t, int tl, unsigned char *s, int sl,
236                   char *encoding, int *lenp)
237 {
238         char enc = 'a';         // start in ASCII encoding mode
239         int tp = 0, sp = 0;
240         if (strlen(encoding) < sl) {
241                 fprintf(stderr, "Encoding string too short\n");
242                 return 0;
243         }
244         // do the encoding
245         while (sp < sl && tp < tl) {
246                 char newenc = enc;      // suggest new encoding
247                 if (tl - tp <= 1 && (enc == 'c' || enc == 't') || tl - tp <= 2
248                     && enc == 'x')
249                         enc = 'a';      // auto revert to ASCII
250                 newenc = tolower(encoding[sp]);
251                 switch (newenc) {       // encode character
252                 case 'c':       // C40
253                 case 't':       // Text
254                 case 'x':       // X12
255                         {
256                                 char out[6], p = 0;
257                                 const char *e,
258                                     *s2 = "!\"#$%&'()*+,-./:;<=>?@[\\]^_",
259                                     *s3 = 0;
260                                 if (newenc == 'c') {
261                                         e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
262                                         s3 = "`abcdefghijklmnopqrstuvwxyz{|}~\177";
263                                 }
264                                 if (newenc == 't') {
265                                         e = " 0123456789abcdefghijklmnopqrstuvwxyz";
266                                         s3 = "`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~\177";
267                                 }
268                                 if (newenc == 'x')
269                                         e = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\r*>";
270                                 do {
271                                         unsigned char c = s[sp++];
272                                         char *w;
273                                         if (c & 0x80) {
274                                                 if (newenc == 'x') {
275                                                         fprintf(stderr,
276                                                                 "Cannot encode char 0x%02X in X12\n",
277                                                                 c);
278                                                         return 0;
279                                                 }
280                                                 c &= 0x7f;
281                                                 out[p++] = 1;
282                                                 out[p++] = 30;
283                                         }
284                                         w = strchr(e, c);
285                                         if (w)
286                                                 out[p++] = ((w - e) + 3) % 40;
287                                         else {
288                                                 if (newenc == 'x') {
289                                                         fprintf(stderr,
290                                                                 "Cannot encode char 0x%02X in X12\n",
291                                                                 c);
292                                                         return 0;
293                                                 }
294                                                 if (c < 32) {   // shift 1
295                                                         out[p++] = 0;
296                                                         out[p++] = c;
297                                                 } else {
298                                                         w = strchr(s2, c);
299                                                         if (w) {        // shift 2
300                                                                 out[p++] = 1;
301                                                                 out[p++] =
302                                                                     (w - s2);
303                                                         } else {
304                                                                 w = strchr(s3,
305                                                                            c);
306                                                                 if (w) {
307                                                                         out[p++]
308                                                                             = 2;
309                                                                         out[p++]
310                                                                             =
311                                                                             (w -
312                                                                              s3);
313                                                                 } else {
314                                                                         fprintf
315                                                                             (stderr,
316                                                                              "Could not encode 0x%02X, should \
317                                                                         not happen\n", c);
318                                                                         return
319                                                                             0;
320                                                                 }
321                                                         }
322                                                 }
323                                         }
324                                         while (p >= 3 || (p && sp == sl)) {
325                                                 int v;
326                                                 while (p < 3) out[p++] = 0; // pad at end
327                                                 if (tp + 2 >= tl) return 0; // not enough space
328                                                 v = out[0] * 1600 +
329                                                     out[1] * 40 + out[2] + 1;
330                                                 if (enc != newenc) {
331                                                         if (enc == 'c'
332                                                             || enc == 't'
333                                                             || enc == 'x')
334                                                                 t[tp++] = 254;  // escape C40/text/X12
335                                                         else if (enc == 'x')
336                                                                 t[tp++] = 0x7C; // escape EDIFACT
337                                                         if (newenc == 'c')
338                                                                 t[tp++] = 230;
339                                                         if (newenc == 't')
340                                                                 t[tp++] = 239;
341                                                         if (newenc == 'x')
342                                                                 t[tp++] = 238;
343                                                         enc = newenc;
344                                                 }
345                                                 t[tp++] = (v >> 8);
346                                                 t[tp++] = (v & 0xFF);
347                                                 p -= 3;
348                                                 out[0] = out[3];
349                                                 out[1] = out[4];
350                                                 out[2] = out[5];
351                                         }
352                                 }
353                                 while (p && sp < sl);
354                         }
355                         break;
356                 case 'e':       // EDIFACT
357                         {
358                                 unsigned char out[4], p = 0;
359                                 if (enc != 'a' && enc != newenc) {      // can only be from C40/Text/X12
360                                         t[tp++] = 254;
361                                         enc = 'a';
362                                 }
363                                 if (enc == 'a')
364                                 {
365                                         t[tp++] = 240;
366                                         enc = 'e';
367                                 }
368                                 while (sp < sl && tolower(encoding[sp]) == 'e'
369                                        && p < 4) {
370                                         if (s[sp] < 32 || s[sp] > 94) {
371                                                 fprintf(stderr, "Cannot encode 0x%02X in EDIFACT\n", s[sp]);
372                                                 return 0;
373                                         }
374                                         out[p++] = s[sp++];
375                                 }
376                                 if (p < 4) {
377                                         out[p++] = 0x1F;
378                                         enc = 'a';
379                                 }       // termination
380                                 t[tp] = ((out[0] & 0x3F) << 2);
381                                 t[tp++] |= ((out[1] & 0x30) >> 4);
382                                 t[tp] = ((out[1] & 0x0F) << 4);
383                                 if (p == 2)
384                                         tp++;
385                                 else {
386                                         t[tp++] |= ((out[2] & 0x3C) >> 2);
387                                         t[tp] = ((out[2] & 0x03) << 6);
388                                         t[tp++] |= (out[3] & 0x3F);
389                                 }
390                         }
391                         break;
392                 case 'a':       // ASCII
393                         if (enc != newenc) {
394                                 if (enc == 'c' || enc == 't' || enc == 'x')
395                                         t[tp++] = 254;  // escape C40/text/X12
396                                 else
397                                         t[tp++] = 0x7C; // escape EDIFACT
398                         }
399                         enc = 'a';
400                         if (sl - sp >= 2 && isdigit(s[sp])
401                             && isdigit(s[sp + 1])) {
402                                 t[tp++] =
403                                     (s[sp] - '0') * 10 + s[sp + 1] - '0' + 130;
404                                 sp += 2;
405                         } else if (s[sp] > 127) {
406                                 t[tp++] = 235;
407                                 t[tp++] = s[sp++] - 127;
408                         } else
409                                 t[tp++] = s[sp++] + 1;
410                         break;
411                 case 'b':       // Binary
412                         {
413                                 int l = 0;      // how much to encode
414                                 if (encoding) {
415                                         int p;
416                                         for (p = sp;
417                                              p < sl
418                                              && tolower(encoding[p]) == 'b';
419                                              p++)
420                                                 l++;
421                                 }
422                                 t[tp++] = 231;  // base256
423                                 if (l < 250)
424                                         t[tp++] = l;
425                                 else {
426                                         t[tp++] = 249 + (l / 250);
427                                         t[tp++] = (l % 250);
428                                 }
429                                 while (l-- && tp < tl) {
430                                         t[tp] = s[sp++] + (((tp + 1) * 149) % 255) + 1; // see annex H
431                                         tp++;
432                                 }
433                                 if (l) return 0; // not enough space
434                                 enc = 'a';      // reverse to ASCII at end
435                         }
436                         break;
437                 default:
438                         fprintf(stderr, "Unknown encoding %c\n", newenc);
439                         return 0;       // failed
440                 }
441         }
442         if (lenp)
443                 *lenp = tp;
444         if (tp < tl && enc != 'a') {
445                 if (enc == 'c' || enc == 'x' || enc == 't')
446                         t[tp++] = 254;  // escape X12/C40/Text
447                 else
448                         t[tp++] = 0x7C; // escape EDIFACT
449         }
450         if (tp < tl)
451                 t[tp++] = 129;  // pad
452         while (tp < tl) {       // more padding
453                 int v = 129 + (((tp + 1) * 149) % 253) + 1;     // see Annex H
454                 if (v > 254)
455                         v -= 254;
456                 t[tp++] = v;
457         }
458         if (tp > tl || sp < sl)
459                 return 0;       // did not fit
460         /*
461          * for (tp = 0; tp < tl; tp++) fprintf (stderr, "%02X ", t[tp]); \
462          * fprintf (stderr, "\n");
463          */
464         return 1;               // OK
465 }
466
467 // Auto encoding format functions
468 static char encchr[] = "ACTXEB";
469
470 enum {
471         E_ASCII,
472         E_C40,
473         E_TEXT,
474         E_X12,
475         E_EDIFACT,
476         E_BINARY,
477         E_MAX
478 };
479
480 unsigned char switchcost[E_MAX][E_MAX] = {
481         0, 1, 1, 1, 1, 2,       // From E_ASCII
482         1, 0, 2, 2, 2, 3,       // From E_C40
483         1, 2, 0, 2, 2, 3,       // From E_TEXT
484         1, 2, 2, 0, 2, 3,       // From E_X12
485         1, 2, 2, 2, 0, 3,       // From E_EDIFACT
486         0, 1, 1, 1, 1, 0,       // From E_BINARY
487 };
488
489 /*
490  * Creates a encoding list (malloc)
491  * returns encoding string
492  * if lenp not null, target len stored
493  * if error, null returned
494  * if exact specified, then assumes shortcuts applicable for exact fit
495  * in target
496  * 1. No unlatch to return to ASCII for last encoded byte after C40 or
497  * Text or X12
498  * 2. No unlatch to return to ASCII for last 1 or 2 encoded bytes after
499  * EDIFACT
500  * 3. Final C40 or text encoding exactly in last 2 bytes can have a shift
501  * 0 to pad to make a tripple
502  * Only use the encoding from an exact request if the len matches the target,
503  * otherwise free the result and try again with exact=0
504  */
505
506 static char *encmake(int l, unsigned char *s, int *lenp, char exact)
507 {
508         char *encoding = 0;
509         int p = l;
510         char e;
511         struct {
512                 // number of bytes of source that can be encoded in a row at this point
513                 // using this encoding mode
514                 short s;
515                 // number of bytes of target generated encoding from this point to end if
516                 // already in this encoding mode
517                 short t;
518         } enc[MAXBARCODE][E_MAX];
519         memset(&enc, 0, sizeof(enc));
520         if (!l)
521                 return "";      // no length
522         if (l > MAXBARCODE)
523                 return 0;       // not valid
524         while (p--) {
525                 char b = 0, sub;
526                 int sl, tl, bl, t;
527                 // consider each encoding from this point
528                 // ASCII
529                 sl = tl = 1;
530                 if (isdigit(s[p]) && p + 1 < l && isdigit(s[p + 1]))
531                         sl = 2; // double digit
532                 else if (s[p] & 0x80)
533                         tl = 2; // high shifted
534                 bl = 0;
535                 if (p + sl < l)
536                         for (e = 0; e < E_MAX; e++)
537                                 if (enc[p + sl][e].t && ((t = enc[p + sl][e].t +
538                                                           switchcost[E_ASCII]
539                                                           [e]) < bl || !bl)) {
540                                         bl = t;
541                                         b = e;
542                                 }
543                 enc[p][E_ASCII].t = tl + bl;
544                 enc[p][E_ASCII].s = sl;
545                 if (bl && b == E_ASCII)
546                         enc[p][b].s += enc[p + sl][b].s;
547                 // C40
548                 sub = tl = sl = 0;
549                 do {
550                         unsigned char c = s[p + sl++];
551                         if (c & 0x80) { // shift + upper
552                                 sub += 2;
553                                 c &= 0x7F;
554                         }
555                         if (c != ' ' && !isdigit(c) && !isupper(c))
556                                 sub++;  // shift
557                         sub++;
558                         while (sub >= 3) {
559                                 sub -= 3;
560                                 tl += 2;
561                         }
562                 } while (sub && p + sl < l);
563                 if (exact && sub == 2 && p + sl == l) {
564                         // special case, can encode last block with shift 0 at end (Is this
565                         // valid when not end of target buffer?)
566                         sub = 0;
567                         tl += 2;
568                 }
569                 if (!sub) {     // can encode C40
570                         bl = 0;
571                         if (p + sl < l)
572                                 for (e = 0; e < E_MAX; e++)
573                                         if (enc[p + sl][e].t
574                                             &&
575                                             ((t =
576                                               enc[p + sl][e].t +
577                                               switchcost[E_C40][e]) < bl
578                                              || !bl)) {
579                                                 bl = t;
580                                                 b = e;
581                                         }
582                         if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) {
583                                 // special case, switch to ASCII for last bytes
584                                 bl = 1;
585                                 b = E_ASCII;
586                         }
587                         enc[p][E_C40].t = tl + bl;
588                         enc[p][E_C40].s = sl;
589                         if (bl && b == E_C40)
590                                 enc[p][b].s += enc[p + sl][b].s;
591                 }
592                 // Text
593                 sub = tl = sl = 0;
594                 do {
595                         unsigned char c = s[p + sl++];
596                         if (c & 0x80) { // shift + upper
597                                 sub += 2;
598                                 c &= 0x7F;
599                         }
600                         if (c != ' ' && !isdigit(c) && !islower(c))
601                                 sub++;  // shift
602                         sub++;
603                         while (sub >= 3) {
604                                 sub -= 3;
605                                 tl += 2;
606                         }
607                 } while (sub && p + sl < l);
608                 if (exact && sub == 2 && p + sl == l) {
609                         // special case, can encode last block with shift 0 at end (Is this
610                         // valid when not end of target buffer?)
611                         sub = 0;
612                         tl += 2;
613                 }
614                 if (!sub && sl) {       // can encode Text
615                         bl = 0;
616                         if (p + sl < l)
617                                 for (e = 0; e < E_MAX; e++)
618                                         if (enc[p + sl][e].t
619                                             &&
620                                             ((t =
621                                               enc[p + sl][e].t +
622                                               switchcost[E_TEXT][e]) < bl
623                                              || !bl)) {
624                                                 bl = t;
625                                                 b = e;
626                                         }
627                         if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) {   // special case, switch to ASCII for last bytes
628                                 bl = 1;
629                                 b = E_ASCII;
630                         }
631                         enc[p][E_TEXT].t = tl + bl;
632                         enc[p][E_TEXT].s = sl;
633                         if (bl && b == E_TEXT)
634                                 enc[p][b].s += enc[p + sl][b].s;
635                 }
636                 // X12
637                 sub = tl = sl = 0;
638                 do {
639                         unsigned char c = s[p + sl++];
640                         if (c != 13 && c != '*' && c != '>' && c != ' '
641                             && !isdigit(c) && !isupper(c)) {
642                                 sl = 0;
643                                 break;
644                         }
645                         sub++;
646                         while (sub >= 3) {
647                                 sub -= 3;
648                                 tl += 2;
649                         }
650                 } while (sub && p + sl < l);
651                 if (!sub && sl) {       // can encode X12
652                         bl = 0;
653                         if (p + sl < l)
654                                 for (e = 0; e < E_MAX; e++)
655                                         if (enc[p + sl][e].t
656                                             &&
657                                             ((t =
658                                               enc[p + sl][e].t +
659                                               switchcost[E_X12][e]) < bl
660                                              || !bl)) {
661                                                 bl = t;
662                                                 b = e;
663                                         }
664                         if (exact && enc[p + sl][E_ASCII].t == 1 && 1 < bl) {
665                                 // special case, switch to ASCII for last bytes
666                                 bl = 1;
667                                 b = E_ASCII;
668                         }
669                         enc[p][E_X12].t = tl + bl;
670                         enc[p][E_X12].s = sl;
671                         if (bl && b == E_X12)
672                                 enc[p][b].s += enc[p + sl][b].s;
673                 }
674                 // EDIFACT
675                 sl = bl = 0;
676                 if (s[p + 0] >= 32 && s[p + 0] <= 94) { // can encode 1
677                         char bs = 0;
678                         if (p + 1 == l && (!bl || bl < 2)) {
679                                 bl = 2;
680                                 bs = 1;
681                         } else
682                                 for (e = 0; e < E_MAX; e++)
683                                         if (e != E_EDIFACT && enc[p + 1][e].t
684                                             &&
685                                             ((t =
686                                               2 + enc[p + 1][e].t +
687                                               switchcost[E_ASCII][e])
688                                              < bl || !bl))      // E_ASCII as allowed for unlatch
689                                         {
690                                                 bs = 1;
691                                                 bl = t;
692                                                 b = e;
693                                         }
694                         if (p + 1 < l && s[p + 1] >= 32 && s[p + 1] <= 94) {    // can encode 2
695                                 if (p + 2 == l && (!bl || bl < 2)) {
696                                         bl = 3;
697                                         bs = 2;
698                                 } else
699                                         for (e = 0; e < E_MAX; e++)
700                                                 if (e != E_EDIFACT
701                                                     && enc[p + 2][e].t
702                                                     &&
703                                                     ((t =
704                                                       3 + enc[p + 2][e].t +
705                                                       switchcost[E_ASCII][e])
706                                                      < bl || !bl))      // E_ASCII as allowed for unlatch
707                                                 {
708                                                         bs = 2;
709                                                         bl = t;
710                                                         b = e;
711                                                 }
712                                 if (p + 2 < l && s[p + 2] >= 32 && s[p + 2] <= 94) {    // can encode 3
713                                         if (p + 3 == l && (!bl || bl < 3)) {
714                                                 bl = 3;
715                                                 bs = 3;
716                                         } else
717                                                 for (e = 0; e < E_MAX; e++)
718                                                         if (e != E_EDIFACT
719                                                             && enc[p + 3][e].t
720                                                             &&
721                                                             ((t =
722                                                               3 + enc[p +
723                                                                       3][e].t +
724                                                               switchcost
725                                                               [E_ASCII][e])
726                                                              < bl || !bl))      // E_ASCII as allowed for unlatch
727                                                         {
728                                                                 bs = 3;
729                                                                 bl = t;
730                                                                 b = e;
731                                                         }
732                                         if (p + 4 < l && s[p + 3] >= 32 && s[p + 3] <= 94) {    // can encode 4
733                                                 if (p + 4 == l
734                                                     && (!bl || bl < 3)) {
735                                                         bl = 3;
736                                                         bs = 4;
737                                                 } else {
738                                                         for (e = 0; e < E_MAX;
739                                                              e++)
740                                                                 if (enc[p + 4]
741                                                                     [e].t
742                                                                     &&
743                                                                     ((t =
744                                                                       3 +
745                                                                       enc[p +
746                                                                           4][e].
747                                                                       t +
748                                                                       switchcost
749                                                                       [E_EDIFACT]
750                                                                       [e]) < bl
751                                                                      || !bl)) {
752                                                                         bs = 4;
753                                                                         bl = t;
754                                                                         b = e;
755                                                                 }
756                                                         if (exact
757                                                             && enc[p +
758                                                                    4][E_ASCII].t
759                                                             && enc[p +
760                                                                    4][E_ASCII].
761                                                             t <= 2
762                                                             && (t =
763                                                                 3 + enc[p +
764                                                                         4]
765                                                                 [E_ASCII].t) <
766                                                             bl) {
767                                                                 // special case, switch to ASCII for last 1 ot two bytes
768                                                                 bs = 4;
769                                                                 bl = t;
770                                                                 b = E_ASCII;
771                                                         }
772                                                 }
773                                         }
774                                 }
775                         }
776                         enc[p][E_EDIFACT].t = bl;
777                         enc[p][E_EDIFACT].s = bs;
778                         if (bl && b == E_EDIFACT)
779                                 enc[p][b].s += enc[p + bs][b].s;
780                 }
781                 // Binary
782                 bl = 0;
783                 for (e = 0; e < E_MAX; e++)
784                         if (enc[p + 1][e].t
785                             &&
786                             ((t =
787                               enc[p + 1][e].t + switchcost[E_BINARY][e] +
788                               ((e == E_BINARY
789                                 && enc[p + 1][e].t == 249) ? 1 : 0))
790                              < bl || !bl)) {
791                                 bl = t;
792                                 b = e;
793                         }
794                 enc[p][E_BINARY].t = 1 + bl;
795                 enc[p][E_BINARY].s = 1;
796                 if (bl && b == E_BINARY)
797                         enc[p][b].s += enc[p + 1][b].s;
798                 /*
799                  * fprintf (stderr, "%d:", p); for (e = 0; e < E_MAX; e++) fprintf \
800                  * (stderr, " %c*%d/%d", encchr[e], enc[p][e].s, enc[p][e].t); \
801                  * fprintf (stderr, "\n");
802                  */
803         }
804         encoding = safemalloc(l + 1);
805         p = 0;
806         {
807                 char cur = E_ASCII;     // starts ASCII
808                 while (p < l) {
809                         int t, m = 0;
810                         char b = 0;
811                         for (e = 0; e < E_MAX; e++)
812                                 if (enc[p][e].t
813                                     && ((t = enc[p][e].t + switchcost[cur][e]) <
814                                         m || t == m && e == cur || !m)) {
815                                         b = e;
816                                         m = t;
817                                 }
818                         cur = b;
819                         m = enc[p][b].s;
820                         if (!p && lenp)
821                                 *lenp = enc[p][b].t;
822                         while (p < l && m--)
823                                 encoding[p++] = encchr[b];
824                 }
825         }
826         encoding[p] = 0;
827         return encoding;
828 }
829
830 /*
831  * Main encoding function
832  * Returns the grid (malloced) containing the matrix. L corner at 0,0.
833  * Takes suggested size in *Wptr, *Hptr, or 0,0. Fills in actual size.
834  * Takes barcodelen and barcode to be encoded
835  * Note, if *encodingptr is null, then fills with auto picked (malloced)
836  * encoding
837  * If lenp not null, then the length of encoded data before any final
838  * unlatch or pad is stored
839  * If maxp not null, then the max storage of this size code is stored
840  * If eccp not null, then the number of ecc bytes used in this size is
841  * stored
842  * Returns 0 on error (writes to stderr with details).
843  */
844
845 unsigned char *iec16022ecc200(int *Wptr, int *Hptr, char **encodingptr,
846                               int barcodelen, unsigned char *barcode,
847                               int *lenp, int *maxp, int *eccp)
848 {
849         unsigned char binary[3000];     // encoded raw data and ecc to place in barcode
850         int W = 0, H = 0;
851         char *encoding = 0;
852         unsigned char *grid = 0;
853         struct ecc200matrix_s *matrix;
854         memset(binary, 0, sizeof(binary));
855         if (encodingptr)
856                 encoding = *encodingptr;
857         if (Wptr)
858                 W = *Wptr;
859         if (Hptr)
860                 H = *Hptr;
861
862         // encoding
863         if (W) {                // known size
864                 for (matrix = ecc200matrix; matrix->W && (matrix->W != W ||
865                                                           matrix->H != H);
866                      matrix++) ;
867                 if (!matrix->W) {
868                         fprintf(stderr, "Invalid size %dx%d\n", W, H);
869                         return 0;
870                 }
871                 if (!encoding) {
872                         int len;
873                         char *e = encmake(barcodelen, barcode, &len, 1);
874                         if (e && len != matrix->bytes) {        // try not an exact fit
875                                 free(e);
876                                 e = encmake(barcodelen, barcode, &len, 0);
877                                 if (len > matrix->bytes) {
878                                         fprintf(stderr,
879                                                 "Cannot make barcode fit %dx%d\n",
880                                                 W, H);
881                                         return 0;
882                                 }
883                         }
884                         encoding = e;
885                 }
886         } else {
887                 // find a suitable encoding
888                 if (encoding == NULL)
889                         encoding = encmake(barcodelen, barcode, NULL, 1);
890
891                 if (encoding) { // find one that fits chosen encoding
892                         for (matrix = ecc200matrix; matrix->W; matrix++)
893                                 if (ecc200encode
894                                     (binary, matrix->bytes, barcode, barcodelen,
895                                      encoding, 0))
896                                         break;
897                 } else {
898                         int len;
899                         char *e;
900                         e = encmake(barcodelen, barcode, &len, 1);
901                         for (matrix = ecc200matrix;
902                              matrix->W && matrix->bytes != len; matrix++) ;
903                         if (e && !matrix->W) {  // try for non exact fit
904                                 free(e);
905                                 e = encmake(barcodelen, barcode, &len, 0);
906                                 for (matrix = ecc200matrix;
907                                      matrix->W && matrix->bytes < len;
908                                      matrix++) ;
909                         }
910                         encoding = e;
911                 }
912                 if (!matrix->W) {
913                         fprintf(stderr,
914                                 "Cannot find suitable size, barcode too long\n");
915                         return 0;
916                 }
917                 W = matrix->W;
918                 H = matrix->H;
919         }
920         if (!ecc200encode(binary, matrix->bytes, barcode, barcodelen,
921                           encoding, lenp)) {
922                 fprintf(stderr, "Barcode too long for %dx%d\n", W, H);
923                 return 0;
924         }
925         // ecc code
926         ecc200(binary, matrix->bytes, matrix->datablock, matrix->rsblock);
927         {                       // placement
928                 int x, y, NC, NR, *places;
929                 NC = W - 2 * (W / matrix->FW);
930                 NR = H - 2 * (H / matrix->FH);
931                 places = safemalloc(NC * NR * sizeof(int));
932                 ecc200placement(places, NR, NC);
933                 grid = safemalloc(W * H);
934                 memset(grid, 0, W * H);
935                 for (y = 0; y < H; y += matrix->FH) {
936                         for (x = 0; x < W; x++)
937                                 grid[y * W + x] = 1;
938                         for (x = 0; x < W; x += 2)
939                                 grid[(y + matrix->FH - 1) * W + x] = 1;
940                 }
941                 for (x = 0; x < W; x += matrix->FW) {
942                         for (y = 0; y < H; y++)
943                                 grid[y * W + x] = 1;
944                         for (y = 0; y < H; y += 2)
945                                 grid[y * W + x + matrix->FW - 1] = 1;
946                 }
947                 for (y = 0; y < NR; y++) {
948                         for (x = 0; x < NC; x++) {
949                                 int v = places[(NR - y - 1) * NC + x];
950                                 //fprintf (stderr, "%4d", v);
951                                 if (v == 1 || v > 7
952                                     && (binary[(v >> 3) - 1] & (1 << (v & 7))))
953                                         grid[(1 + y +
954                                               2 * (y / (matrix->FH - 2))) * W +
955                                              1 + x +
956                                              2 * (x / (matrix->FW - 2))] = 1;
957                         }
958                         //fprintf (stderr, "\n");
959                 }
960                 free(places);
961         }
962         if (Wptr)
963                 *Wptr = W;
964         if (Hptr)
965                 *Hptr = H;
966         if (encodingptr)
967                 *encodingptr = encoding;
968         if (maxp)
969                 *maxp = matrix->bytes;
970         if (eccp)
971                 *eccp =
972                     (matrix->bytes + 2) / matrix->datablock * matrix->rsblock;
973         return grid;
974 }