% 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 113311\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.




