summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/sdaps/sdapscode128.tex
blob: 90835f517f39ef8b9a654e0215a18d1f265c462a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
%% Copyright 1996 Petr Olsak.
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
%
% The work has been licensed under these terms with permission
% by Petr Olsak for distribution with SDAPS.
%
% The original file follows
% See http://math.feld.cvut.cz/olsak/

% Macro for conversion of string to barcodes by Code 128 standard
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% March 1996                                 (C) Petr Ol\v{s}\'ak

% For user information see the file test128.tex

% Comments at programmer level are included in this file. First you can
% read the end of this file: The description of Code 128 standard.

\wlog{**** Macro for barcodes in "Code 128" by (C) Petr Olsak used ****}

% Declarations:
\newdimen\X            % the module size X,
\newdimen\bcorr        % the bar correction (see bellow).
\newdimen\workdimen \newdimen\barheight   % internal variables
\newtoks\inputtext \newtoks\icode
\newcount\tempnum \newcount\chnum \newcount\chtotal
\newif\ifnext \newif\ifchar
\def\empty{} \def\End{@@end}

% Implicit values:
\X=.33mm         % The X module width.
\bcorr=.020mm    % Bar reduction.
\barheight=1.5cm % The code height.

% First we declare some tables.
% "\definetable<lab><num> string \relax": Each token from "string" gets a value
% (spaces are ignored). First token gets value <num>, second <num+1>
% and so on. It is possible to reconstruct the value by
% "\csname<lab>\string<token>\endcsname".
\def\definetable#1#2 {\tempnum=#2 \def\temp{#1}\let\next=\repeatdefine \next}
\def\repeatdefine#1{\ifx#1\relax \let\next=\relax \else
  \expandafter\edef\csname\temp\string#1\endcsname{\the\tempnum}%
  \advance\tempnum by1 \fi \next}

%%%%%%%%%%%%%%%%%%%%% Basic tables for Code 128: %%%%%%%%%%%%%%%%%%%%%%%%%%%
\definetable:0  % All input characters from Code B:
  \  ! " \# \$ \% \& ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @
  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \\ ] \^ \_ `
  a b c d e f g h i j k l m n o p q r s t u v w x y z \{ | \} \~ \DEL \relax
\definetable:64 % Other input characters from Code A:
  \NUL \SOH \STX \ETX \EOT \ENQ \ACK \BEL \BS \HT \LF \VT \FF \CR \SO \SI
  \DLE \DCone \DCtwo \DCthree \DCfour \NAK \SYN \ETB \CAN \EM \SUB \ESC
  \FS \GS \RS \US \relax
\definetable:0 \
  \relax    % the \^^M must be the same as \<space>
\definetable:0 \SP \relax  % the \SP is alternative to \<space>
\definetable{D:}0 0123456789 \relax  % Digits
\definetable{B:}0 `abcdefghijklmnopqrstuvwxyz\{\|\}\~ \relax % Only in Code B
\definetable{A:}0  \NUL \SOH \STX \ETX \EOT \ENQ \ACK \BEL \BS \HT \LF \VT
  \FF \CR \SO \SI \DLE \DCone \DCtwo \DCthree \DCfour \NAK \SYN \ETB \CAN
  \EM \SUB \ESC \FS \GS \RS \US \relax % only in code A.
\def\tableofcode#1{\ifcase#1 % The output characters:
  212222\or 222122\or 222221\or 121223\or 121322\or % 0-4
  131222\or 122213\or 122312\or 132212\or 221213\or % 5-9
  221312\or 231212\or 112232\or 122132\or 122231\or % 10-14
  113222\or 123122\or 123221\or 223211\or 221132\or % 15-19
  221231\or 213212\or 223112\or 312131\or 311222\or % 20-24
  321122\or 321221\or 312212\or 322112\or 322211\or % 25-29
  212123\or 212321\or 232121\or 111323\or 131123\or % 30-34
  131321\or 112313\or 132113\or 132311\or 211313\or % 35-39
  231113\or 231311\or 112133\or 112331\or 132131\or % 40-44
  113123\or 113321\or 133121\or 313121\or 211331\or % 45-49
  231131\or 213113\or 213311\or 213131\or 311123\or % 50-54
  311321\or 331121\or 312113\or 312311\or 332111\or % 55-59
  314111\or 221411\or 431111\or 111224\or 111422\or % 60-64
  121124\or 121421\or 141122\or 141221\or 112214\or % 65-69
  112412\or 122114\or 122411\or 142112\or 142211\or % 70-74
  241211\or 221114\or 413111\or 241112\or 134111\or % 75-79
  111242\or 121142\or 121241\or 114212\or 124112\or % 80-84
  124211\or 411212\or 421112\or 421211\or 212141\or % 85-89
  214121\or 412121\or 111143\or 111341\or 131141\or % 90-94
  114113\or 114311\or 411113\or 411311\or 113141\or % 95-99
  114131\or 311141\or 411131\else 00000\fi }        % 100-102
\def\startA{211412}
\def\startB{211214}
\def\startC{211232}
\def\stop{23311120}

% Implementations of tests:
% After "\testchar <lab><token>" the "\ifchar" has following meaning:
% true, if <token> is in digits, only in A or only in B respectively with
% <lab> is {D:}, {A:} or {B:}.
\def\testchar #1#2{\expandafter\ifx\csname#1\string#2\endcsname \relax
          \charfalse \else \chartrue \fi}

% After "\numofdigits string\stop" is used, the \tempnum register contain
% the number of digits from first continuosly group of digits from left in
% "string". If "string" starts with no digit then \tempnum=0.
\def\numofdigits{\tempnum=0 \let\next=\cyklnumber \cyklnumber}
\def\cyklnumber#1{\testchar {D:}#1%
   \ifchar \advance\tempnum by1
   \else \ifx #1\stop\def\next{}%
         \else \def\next##1\stop{}\fi
   \fi \next}

% After "\testnext<lab> string\stop" is used, the "\ifnext" has
% the following meaning:
% 1. <lab> is {A:}: "\ifnext" is true, if first character from "string" is
% only in A code after skip all common characters shared in codeA and B.
% 2. <lab> is {B:}: "\ifnext" is true, if first character from "string" is
% only in B code after skip all common characters shared in codeA and B.
\def\testA{A:}
\def\testnext#1{\nextfalse
  \def\tempA{#1}%
  \ifx\tempA\testA \def\tempB{B:}\else \def\tempB{A:}\fi
  \let\next=\cyklcontrol \next}
\def\cyklcontrol#1{%
   \ifx#1\stop \let\next=\relax
   \else \testchar \tempB #1%
         \ifchar \def\next##1\stop{}%
         \else \testchar \tempA #1%
               \ifchar \nexttrue \def\next##1\stop{}\fi \fi
   \fi \next}

% "\addtok \cs" adds the "\cs," into \icode.
% "\addtoks{string} adds the "string," into \icode. "string" is the number
% of line in table 1, so we re-calculate the current check sum.
% "\addchar <token> adds the numerical value of <token> (declared in
% \definetable:) into \icode. This value is followed by comma too.
\def\addtok#1{\edef\act{\noexpand\icode={\the\icode\noexpand#1,}}\act}
\def\addtoks#1{\edef\act{\noexpand\icode={\the\icode#1,}}\act
  \tempnum=#1 \multiply\tempnum by\chnum
  \advance\chtotal by\tempnum \advance\chnum by 1\relax}
\def\addchar#1{\expandafter\ifx\csname:\string#1\endcsname\relax
  \errmessage{The input token "\string#1" is not included in Code 128
              table, will ignored}%
  \else \expandafter\addtoks\expandafter{\csname:\string#1\endcsname}\fi}

% \code{text} first converts the input text into internal representation in
% \icode. The format of \icode is: "\start,num,num,num,\stop,", where
% "\start" is one of "\startA" or "\startB" or "\startC". The <num>
% represents the line of code table (see standard of Code 128 bellow)
% of output characters. The amount of <num>s is not restricted. The sequence
% is terminated by "\stop,". See to .log for example of this format.
%
% The choice of the start character:
% If next 4 input characters are digits then \startC
% else if the next uncommon char is from code A and not from B then \startA
%      else \startB
% The "next uncommon char" is first character from left which falls
% into code A xor code B
\def\code#1{\inputtext={#1}\wlog{** Code 128 ** input: \the\inputtext}%
  \icode={}\chnum=1
  \numofdigits#1\stop % in \tempnum is the number of digits now
  \ifnum\tempnum>3 \addtok\startC \chtotal=2 \let\Next=\codeC \else
     \testnext{A:} #1\stop
     \ifnext \addtok\startA \chtotal=0 \let\Next=\codeA
     \else \addtok\startB \chtotal=1 \let\Next=\codeB \fi
  \fi \Next #1\End\End}

% There is mode A. Test to change the mode:
% If the next 4 input characters are digits and the number of digits are even
%    then switch to modeC using <codeC>.
% If the next char is from Code B and not from Code A then:
%    if the next uncommnon char is from Code B and not from A then
%         switch to mode B using <codeB>.
%    else include <SHIFT> and stay in mode A.
\def\codeA #1#2#3\End{\addchar#1%
  \numofdigits#2#3\stop
  \ifnum\tempnum>3 \ifodd\tempnum\else
      \addtoks{99}\let\Next=\codeC \fi
  \else \ifx#2\End \let\Next=\finalcode
        \else \testchar{B:} #2%
              \ifchar \testnext{B:} #3\stop
                      \ifnext \addtoks{100}\let\Next=\codeB
                      \else \addtoks{98}\fi \fi \fi \fi
  \Next #2#3\End}

% There is mode B. Test to change the mode:
% If the next 4 input characters are digits and the number of digits are even
%    then switch to modeC using <codeC>
% If the next char is from Code A and not from Code B then:
%    if the next uncommnon char is from Code A and not from B then
%         switch to mode A using <codeA>.
%    else include <SHIFT> and stay in mode B.
\def\codeB #1#2#3\End{\addchar#1%
  \numofdigits#2#3\stop
  \ifnum\tempnum>3 \ifodd\tempnum\else
      \addtoks{99}\let\Next=\codeC \fi
  \else \ifx#2\End \let\Next=\finalcode
        \else \testchar{A:} #2%
              \ifchar \testnext{A:} #3\stop
                      \ifnext \addtoks{101}\let\Next=\codeA
                      \else \addtoks{98}\fi \fi \fi \fi
  \Next #2#3\End}

% There is mode C. Test to change the mode:
% If not next two chars are digits switch to code A or B by following rule:
% If the next uncommon char is from Code A and not from B then
%      switch to mode A using <codeA>
% else switch to mode B using <codeB>
\def\codeC #1#2#3#4\End{\addtoks{#1#2}%
  \ifx#3\End \let\Next=\finalcode
  \else \testchar{D:} #3%
        \ifchar \def\temp{#4}%
                \ifx\temp\empty \switchtoAorB #3\stop
                \else \separate #4\stop
                      \edef\act{\noexpand\testchar{D:}\temp}\act
                      \ifchar
                      \else \switchtoAorB #3#4\stop \fi \fi
        \else \switchtoAorB #3#4\stop \fi
  \fi \Next #3#4\End}
\def\separate#1#2\stop{\def\temp{#1}}
\def\switchtoAorB #1\stop{\testnext{A:} #1\stop
   \ifnext \addtoks{101}\let\Next=\codeA
   \else \addtoks{100}\let\Next=\codeB \fi}

\def\finalcode\End\End{\addchecksum \addtok\stop \wlog{encoded: \the\icode}%
  \expandafter\makecode\the\icode}

% \addchecksum adds the check sum into \icode
\def\addchecksum{\tempnum=\chtotal
  \divide\tempnum by 103 \multiply\tempnum by 103
  \advance\chtotal by-\tempnum \addtoks{\the\chtotal}}

% The \makecode converts the \icode from format "\start,num,num,\stop,"
% into sequence of digits. Each digit repersents the multiple of X module
% size for bar or space if it is at odd or even position. For example
% 21141223311120. It means bar of 2X, space 1X, bar 1X, space 4X and so on.
% This representation of code is stored in macro \internalcode.
\def\makecode#1,{\let\next=\cyklcode \edef\internalcode{#1}\next}
\def\cyklcode#1,{%
  \ifx\stop#1\let\next=\finalmakecode \edef\internalcode{\internalcode\stop}%
  \else \edef\internalcode{\internalcode\tableofcode{#1}}\fi \next}
\def\finalmakecode{\wlog{black-white: \internalcode}%
  \begcode \let\next=\makebars \expandafter\makebars\internalcode}

% \makebars simply makes the \vrules and \kerns of appropriate sizes from
% \internalcode representation. Each width of \vrule is corrected by \bcorr
% and opposite for \kern.
\def\makebars#1#2{\if0#2\let\next=\endcode\fi
  \workdimen=#1\X \advance\workdimen by-\bcorr \vrule width\workdimen
  \workdimen=#2\X \advance\workdimen by \bcorr \kern\workdimen
  \next}

% The begin and end of completed \hbox:
\def\begcode{\hbox\bgroup\vrule height\barheight width0pt}
\def\endcode{\egroup}

% User can use \codetext or \codeothertext instead \code:
\def\codeothertext#1#2{\vbox{\halign{\hfil##\hfil\cr\code{#1}\cr{\tt#2}\cr}}}
\def\codetext#1{\codeothertext{#1}{#1}}

\endinput %%%%%%%%%%%%%%% End of macros %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

               The description of Code 128 standard
               ************************************

The characters from input string are converted from left to right
to so called "output characters" by table 1 (see below). Each output
character has three bars and spaces. The width of bars and the dimensions
of spaces between bars are significant. This values are expresed by
multiples of basic dimension: so called X module size (see \X in macro).
The multiples varies from 1 to 4. We are using the six digits expression of
output character. It expressed dimensions of bar, space, bar, space, bar,
space. For example 122412 means one output character drawn as: 1X bar, 2X
space, 2X bar, 4X space, 1X bar and 2X space.

The table 1:

num.line  code A    code B    codeC     output character
-------------------------------------------------------
  0       [space]    [space]    00        212222
  1            !         !      01        222122
  2            "         "      02        222221
  3            #         #      03        121223
... and so on ...
 63            _         _      63        111224
 64         \NUL         `      64        111422
 65         \SOH         a      65        121124
 66         \STX         b      66        121421
... and so on ...
 93          \GS         }      93        111341
 94          \RS         ~      94        131141
 95          \US      \DEL      95        114113
 96       <FNC3>    <FNC3>      96        113311
 97       <FNC2>    <FNC2>      97        411113
 98      <SHIFT>   <SHIFT>      98        411311
 99      <codeC>   <codeC>      99        113141
100      <codeB>    <FNC4>   <codeB>      114131
101       <FNC4>   <codeA>   <codeA>      311141
102       <FNC1>    <FNC1>    <FNC1>      411131

The whole table is not presented here because you can simply reconstruct it
from macros.

The columns "code A", "code B", and "code C" inlude all possible input
characters in input string (excluding "special commands" in lines 96--102
written in <angle> braces). The special \TeX{} characters must be escaped
(i.e. user have to write \# and no #). The escaped words (in capitals)
represents so called "control characters" from ASCII. The meaning of this
sequences depends on application. The "special commands" in lines 96--102
written in <angle> braces are not possible in input. They are special for
decoder. The <SHIFT> and <codeA-C> are used in our macro, but <FNC?> are
not because they are reserved for special purposes.

The Code B column is whole expressed in \definetable:0 (see in macro). The
Code A column has the same values in lines 0--63 (capitals, digits and some
other ASCII characters are included here). Code A differ from Code B in
lines 64--102. The lowercase letters and another ASCII characters are
included in "Code B", but control sequences are included in "Code A".
The different part of "Code A" column is expressed in \definetable:64 (see
in macro). The "code C" column includes the digits pairs and corresponds to
number of line in table 1. Two digits in input go to one output character.
The whole "output character" column is expressed in \tableofcode (see in
macro).

The "start character" is appended before each barcode. There are three
types of start character depending on which column of table is used for
next encoding (so called mode). See macros \startA, \startB and \startC.
For examlpe: If \startC is used, next output character represents two
digits in input (codeC mode). If \startB is used, next output character
represents one ASCII character in input (codeB mode). If \startA is used,
next output character represents probably the control sequence in input or
capitals, but not lowercase ASCII (codeA mode).

If some mode for encoding is currently used and next input character is not
included in appropriate column, the "switching command" is included into
sequence of output character. The <SHIFT> command switches from mode A to
B or from B to A only for one next input character and the other input
characters are coded in the same mode (A or B). The <codeA> command
switches to codeA mode definitively unless next switch command is used.
The commands <codeB> and <codeC> makes the same service, but to switch into
mode B or C respectively. All these commands are expessed in table 1.

It is recomended to chose the start character and switching commands by the
way, that the resulting length of code is minimised. There are some
recommendations of this choice. These recommendations are included into our
macros (see the commnets and macros for \code, \codeA, \codeB and \codeC).

The checksum character is added after the end of input string. Finally,
the "stop character" is appended after the end of barcode. This character
has exclusively four bars and not only three. See macro \stop.

The checksum character is calculated from output characters used in the
code. The number of line in table 1 of each output character is asumed. The
start character is covered too, but checksum character itself and the
stop character are not included into calculation. The startA or startB or
startC characters has its number of line 103 or 104 or 105 respectively. Each
output character (more exactly its number of line in table 1) is multiplied
by "weight number" and the total sum is calculated. The weight number of
start character is one. The weight number of first output characet after
start is one too. Second character has weight number two, and so on. The
n-th character has weight number n. The total sum modulo 103 is the line of
the calculated checksum character.

Example for checksum calculation:
Input:    123456
Encoded:  StartC, 12, 34, 56
Total sum of checksum: 105 + 1*12 + 2*34 + 3*56 = 535
Modulo 103: 44
The character from line 44 is apended as checksum.
The whole encoded code: StartC, 12, 34, 56, 44, Stop

%%% End of file.