% 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 string \relax": Each token from "string" gets a value % (spaces are ignored). First token gets value , second % and so on. It is possible to reconstruct the value by % "\csname\string\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 \ \definetable:0 \SP \relax % the \SP is alternative to \ \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 " the "\ifchar" has following meaning: % true, if is in digits, only in A or only in B respectively with % 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 string\stop" is used, the "\ifnext" has % the following meaning: % 1. 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. 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 adds the numerical value of (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 % represents the line of code table (see standard of Code 128 bellow) % of output characters. The amount of 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 . % 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 . % else include 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 % 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 . % else include 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 % else switch to mode B using \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 96 113311 97 97 411113 98 98 411311 99 99 113141 100 114131 101 311141 102 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 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 braces are not possible in input. They are special for decoder. The and are used in our macro, but 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 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 command switches to codeA mode definitively unless next switch command is used. The commands and 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.