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