summaryrefslogtreecommitdiff
path: root/macros/generic/formlett
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/generic/formlett
Initial commit
Diffstat (limited to 'macros/generic/formlett')
-rw-r--r--macros/generic/formlett/formlett.sty1868
-rw-r--r--macros/generic/formlett/prog_manual.pdfbin0 -> 198659 bytes
-rw-r--r--macros/generic/formlett/prog_manual.tex1906
-rw-r--r--macros/generic/formlett/user_manual.pdfbin0 -> 172966 bytes
-rw-r--r--macros/generic/formlett/user_manual.tex1113
5 files changed, 4887 insertions, 0 deletions
diff --git a/macros/generic/formlett/formlett.sty b/macros/generic/formlett/formlett.sty
new file mode 100644
index 0000000000..418dafd360
--- /dev/null
+++ b/macros/generic/formlett/formlett.sty
@@ -0,0 +1,1868 @@
+% MAKE FORM LETTER for multiple receivers via
+% plain TeX, LaTeX 2.09 or LaTeX2e
+%
+% written by Zhuhan JIANG
+% University of Western Sydney
+% Parramatta NSW 2150.
+% Email: z.jiang@uws.edu.au
+%
+% FILENAME: formlett.sty
+% VERSION: 2.3 May 2003
+% COPYRIGHT: GNU convention preferred.
+%
+%
+% NEW COMMANDS
+% \paras \blockparas \addressparas \PAGENO \NOPAGENUMBERS
+% \paradefaults \loaddefaultparas \delparadefaults \paranames
+% \showparas \preview \previewtrue \previewfalse \existfile
+% \localparastrue \localparasfalse \nodefaultstrue \nodefaultsfalse
+% \beginpilemode \endpilemode \delimiters \defaultmarks \blockmarks
+% \beginblockmode \endblockmode \beginlinemode \endlinemode
+% \beginrawblockmode \endrawblockmode \beginrawlinemode \endrawlinemode
+% \beginletter \endletter \moreletter \inputletter \inputfile
+% \boxmore \textbox \addressbox \ADDRESSBOX \fillzeros
+% \beginlist \endlist \beginrawlist \endrawlist \printfile
+% \begincomment \endcomment \begincolumns \endcolumns \readstyles
+% \beginlabels \endlables \smooth \initstyle \initclass \labelsquit
+% \firstread \beginfile \endfile \checkparas \ifemptyparas \cachedata
+% \newarray \delarray \readarray \checkARRAYNAME \ifemptydata
+%
+%
+% NOTE
+% You only need to know a SMALL portion of the above commands
+% in order to use the style file: easy to use is our key purpose!
+%
+%
+% VERSION HISTORY:
+% 1.0 8/93
+% 1.2 10/93 major rewriting, only basic mode still
+% compatible with 1.0;
+% support for raw text list added
+% 1.3 fixed a minor bug of 1.2;
+% support for commenting out letters added
+% 2.0 11/93 compatible with 1.2, 1.3;
+% labels utility added; support for fixed number
+% of parameter lines added
+% 2.03 2/94 TAB char represents 8 spaces instead of 4;
+% fixed a bug on multi-columns output
+% 2.1 1/95 added parameter checker and dynamic array facilities;
+% compatible with LaTeX2e;
+% slight name changes: \figbox -->\textbox
+% 2.2 1/95 renamed an internal command (\array) to avoid
+% conflict with LaTex.
+% 2.3 5/2003 separated programmer's manual from the style file,
+% added a new user manual.
+%
+%
+% %SIMPLE EXAMPLE in Plain TeX:
+%
+% \input formlett.sty
+% \beginletter \pageno=1
+% \paras--\paras[2]--\paras[3]\par
+% \paras[1][2] -- \paras[2][2] -- \paras[4][4] -- \paras[][2]
+% \vfill\eject
+% \endletter
+% \preview
+% \moreletter % first letter
+% 1-ONE;;;1-FOUR+%
+% 2-ONE;2-TWO;2-THREE;++;;;4-FOUR!
+%
+% \moreletter % second letter
+% 1-one;1-two;1-three;1-four
+% +2-one;;2-three; ++ ;;;4-four!
+% \end
+%
+%
+% %TYPICAL EXAMPLE in LaTeX
+%
+% \documentstyle[formlett]{article}
+% \textwidth=3.2in
+% \begin{document}
+%
+% \beginletter
+% \paranames % optional
+% \tt<<FULL NAME>>;%
+% \tt<<ADDRESS-etc>>;%
+% +\tt<<GIVEN NAME>>;%
+% \tt<<MISSING ITEM>>;%
+% \tt<<PHONE NUMBER>>!
+% \loaddefaultparas % optional
+%
+% \NOPAGENUMBERS\parindent=0pt
+% \noindent{\it\paras[1]}\par
+% \blockparas[2]\par\bigskip
+%
+% Dear \paras[1][2],\par\medskip
+% We have been looking for
+% \paras[2][2] for quite a while
+% without any luck, could you help
+% us out? If so, please ring
+% \paras[3][2]. \par\medskip
+% Cheers!\hfill Michael\vfill\eject
+% \endletter
+% \preview \showparas
+%
+% \paradefaults % optional
+% To whom this may concern
+% +Sir or Madam;something;%
+% 061-225-9905!
+%
+%
+% %\beginlabels % optional
+% % uncomment the above line and its matching
+% % \endlabels later on, if you want to get the
+% % mailing labels.
+% % So one LaTeX run to get all the letters, and
+% % an EXTRA run to produce all the labels by
+% % activating \beginlabels
+%
+%
+% \blockmarks
+% \beginblockmode
+%
+% Mrs L Stenson
+% \#1-20 Sunset Street
+% Hillside, Norway
+% ------ separate groups
+% Louise
+% a Bible
+% 220-8888
+% ========= separate cluster
+%
+% ...... force entry next line
+%
+% Above empty line active
+%
+% \endblockmode comment ignored
+%
+% \defaultmarks
+% \moreletter
+% S Wales,;%
+% \addressbox[2in][1em]{%
+% University of Manchester Institute
+% of Science and Technology, This is
+% a long address line: it will be
+% wrapped up automatically.}%
+% +;a \TeX\ package \gstr\ manual and
+% many more (\cstr)!
+%
+% \beginlinemode
+% Z Jiang
+% UNE, Arimdale
+%
+% T Ribbons
+% UMIST, Manchester
+% \endlinemode
+%
+% \beginpilemode
+%
+% C Anderson;42nd Street;USA+Christine;your service invoice!
+%
+% D Holmes;Flat \#2, Finneybank Rd;London+David;the tax receipt;%
+% 071-902 7799!
+%
+% \endpilemode
+%
+% %\endlabels
+% % uncomment the above line and if its matching
+% % \beginlabels is set previously for labels
+%
+%
+% \begincomment{} % this is only a tip
+% % Comment out the letters that you already sent
+%
+% \moreletter parameters for letter one!
+% \moreletter letter two!
+%
+% \endcomment
+%
+% \end{document}
+%
+%
+%%%%% To run the above examples, remove the first '%' character in each line
+%
+%
+%
+%
+%BEGINMACROS
+%
+%
+\ifx\ENDINPUT\undefined\else\message{skipped}\endinput\fi
+%
+\message{2.3 <26/5/2003>}%
+%
+{\catcode`\@=11\relax \def\temp@macro{\space\space\space\space}%
+\wlog{\temp@macro FORMLETT version 2.3 May 2003 By Z Jiang}%
+\wlog{\temp@macro University of Western Sydney, Australia}%
+\wlog{\temp@macro Email: z.jiang@uws.edu.au}}%
+%
+% SAVE @'s STATUS
+%
+\xdef\EntryFormLett{\the\catcode`\@}\catcode`\@=11\relax
+\gdef\MAX@CHR@CODE{255}% maximum charcode for saving catcode
+% % change it to 127 for TeX 2
+% % may change it to 0 if no raw mode is to be used
+% IS LATEX ?
+%
+\newif\ifISLATEX
+\ifx\pageno\undefined@\global\ISLATEXtrue\else\global\ISLATEXfalse\fi
+%
+% a private \l@@p
+\def\l@@p#1\repe@t{\def\b@dy{#1}\iter@te}%
+\def\iter@te{\b@dy\let\n@xt=\iter@te \else\let\n@xt=\relax\fi \n@xt}%
+\let\repe@t=\fi %
+%
+% NEW MEASURES etc
+%
+\def\new@measures{%
+ \def\temp@@macro##1##2##3{\expandafter\ifx\csname ##3temp##2##1\endcsname
+ \relax\edef\next{\noexpand\csname new##1\noexpand\endcsname
+ \csname ##3temp##2##1\endcsname}%
+ \else\let\next\relax\fi\next}%
+ \def\temp@macro##1{%
+ \temp@@macro{##1}{@}{}\temp@@macro{##1}{@@}{}\temp@@macro{##1}{@@@}{}}%
+ \temp@macro{count}\temp@macro{toks}\temp@macro{box}\temp@macro{read}%
+ \temp@@macro{if}{@}{if}\temp@@macro{if}{@@}{if}\temp@@macro{if}{@@@}{if}%
+ \def\temp@@macro##1{\expandafter\ifx\csname temp##1dim\endcsname
+ \relax\edef\next{\noexpand\csname newdimen\noexpand\endcsname
+ \csname temp##1dim\endcsname}%
+ \else\let\next\relax\fi\next}%
+ \temp@@macro{@}\temp@@macro{@@}\temp@@macro{@@@}%
+}%
+\let\temp@@@macro=\wlog\def\wlog#1{}\new@measures
+%
+%
+%%% GENERAL STACK
+%
+\def\make@STKcount{\csname newcount\endcsname
+ \STKcount\global\STKcount=0\relax}%
+\ifx\STKcount\undefined@
+ \def\next{\make@STKcount}\else\def\next{}\fi
+\next % ensures stack pointer not flushed if this piece of code
+ % is loaded again
+%
+\long\def\push#1{\global\advance\STKcount1\relax
+\expandafter\gdef\csname STK\the\STKcount\string~\endcsname{#1}}%
+%
+\def\popnil{\expandafter\let\expandafter\temp@macro
+ \csname STK\the\STKcount\string~\endcsname
+ \ifnum\STKcount>0\global\expandafter\let
+ \csname STK\the\STKcount\string~\endcsname=\undefined@
+ \global\advance\STKcount-1%
+ \else
+ \def\temp@macro{}\global\STKcount=0%
+ \fi\relax % \temp@macro for pop
+}%
+%
+\def\pop{\popnil\temp@macro}%
+%
+%
+%% GET PARAMETERS
+%
+\long\def\get@nepara[#1][#2]{{\def\next@{#2}%
+\ifx\next@\empty\push{#1}\else\push{#2}\fi}\ag@in}%
+%
+\long\def\get@para\left@#1\right@{%
+\def\check@{%
+ \ifx[\next@ \def\full@####1{\get@nepara[#1]####1}%
+ \else \def\full@{\get@nepara[#1][#1]}\fi
+ \full@}%
+\futurelet\next@\check@}%
+%
+\long\def\do@nepara\left@#1\right@#2\p@r@end{%
+\gdef\p@r@data{#2}\global\advance\p@r@count1\get@para\left@#1\right@}%
+%
+\def\ag@in{\ifx\p@r@data\empty \def\next@{\relax
+\getp@r@s\run@CMD}\else
+\def\next@{\expandafter\do@nepara\p@r@data\p@r@end}\fi
+\next@}%
+%
+\def\run@CMD{\csname STK\the\STKcount\string~\endcsname}%
+%
+\newcount\p@r@count
+\long\def\st@ckparas#1\p@r@end{%
+\global\p@r@count=0\gdef\p@r@data{#1}\ag@in}%
+%
+%
+% PARAMETER ASSIGNMENT
+%
+%% \newcount\temp@count
+\newtoks\p@r@one \newtoks\p@r@two \newtoks\p@r@three
+\newtoks\p@r@four \newtoks\p@r@five \newtoks\p@r@six
+\newtoks\p@r@seven \newtoks\p@r@eight \newtoks\p@r@nine
+\def\getp@r@s{\temp@count=\p@r@count
+{\loop
+ \ifnum\temp@count>0 %
+ \expandafter\let\expandafter
+ \temp@macro\csname STK\the\STKcount\string~\endcsname
+ \ifcase\temp@count
+ \or \global\p@r@one=\expandafter{\temp@macro}%
+ \or \global\p@r@two=\expandafter{\temp@macro}%
+ \or \global\p@r@three=\expandafter{\temp@macro}%
+ \or \global\p@r@four=\expandafter{\temp@macro}%
+ \or \global\p@r@five=\expandafter{\temp@macro}%
+ \or \global\p@r@six=\expandafter{\temp@macro}%
+ \or \global\p@r@seven=\expandafter{\temp@macro}%
+ \or \global\p@r@eight=\expandafter{\temp@macro}%
+ \or \global\p@r@nine=\expandafter{\temp@macro}%
+ \else \errmessage{Parameter capacity exceeded.}%
+ % this should never happen: TeX's max para no. is 9
+ \fi
+ \global\expandafter\let
+ \csname STK\the\STKcount\string~\endcsname=\undefined@%
+ \global\advance\STKcount-1%
+ \global\advance\temp@count-1\relax
+ \fi
+ \ifnum\temp@count>0 %
+\repeat}}%
+%
+\def\clrp@r@s{%GLOBALLY clear
+\global\p@r@one={}\global\p@r@two={}\global\p@r@three={}%
+\global\p@r@four={}\global\p@r@five={}\global\p@r@six={}%
+\global\p@r@seven={}\global\p@r@eight={}\global\p@r@nine={}}%
+% The above is the minimum for setting default parametrisation
+%
+%
+% ARRAY STRUCTURE
+%
+% \newarray\ARRAYNAME
+% \delarray\ARRAYNAME
+%
+% \ARRAYNAME(A1,..,An)={T}
+% \readarray{ARRAYNAME}{ B1 & B2 & ... & Bm }
+% \dataheight
+%
+% \data(A1,...,An)=\data( A1 + (A2-1)*\dataheight +
+% ... + (An-1)*\dataheight^{n-1} )
+% if \normalindextrue
+% =\data( An + (An-1 -1)*\dataheight +
+% ... + (A1)*\dataheight^{n-1} )
+% if \normalindexfalse
+%
+% \checkARRAYNAME(A1,..,An)
+% \ifemptydata valid when \checkARRAYNAME is just executed
+% \cachedata: keeps the data of \ARRAYNAME(m)
+% when \checkARRAYNAME(m) is executed
+%
+% e.g.
+%
+% \newarray\Table
+% \readarray{Table}{one&two& \unknownmacro && &six}
+% \Table(7)={seven}
+% \dataheight=0 % or 1 or < 0
+% \Table(7) = \Table(2,6,1) % 7=1+(2-1)+(6-1)+(1-1)
+% \normalindexfalse
+% \dataheight=3
+% \Table(7) = \Table(1,7) = \Table(3,1)
+% \normalindextrue
+% \Table(7) = \Table(7,1) = \Table(1,3)
+%
+% \checkTable(4) \ifemptydata (4)=empty \fi
+% \checkTable(5) \ifemptydata\else (5)=nonempty \fi
+% \ifx\cachedata\space ={\tt <space>}\fi
+% \checkTable(1000) \ifemptydata (1000)=empty \fi
+%
+% \delarray\Table
+%
+%
+\xdef\EntryArrayJob{\the\catcode`\@}\catcode`\@=11\relax
+\newif\ifemptydata \newcount\dataheight
+\newif\ifnormalindex \normalindexfalse
+%
+\newcount\array@width \newcount\index@count \newcount\index@total
+\newif\ifone@VEC \newif\if@rev@index
+% \newtoks\temp@toks \newcount\temp@count
+% \newcount\temp@@count \newcount\temp@@@count
+%
+\long\def\assign@VEC#1(#2)=#3{\temp@count=#2 \relax
+\get@max@count{total@#1}\temp@count
+\expandafter\gdef\csname#1#2\string~\endcsname{#3}}
+\def\get@VEC#1(#2){\csname#1#2\string~\endcsname}
+\def\clrarr@y#1(#2){%
+ \global\expandafter\let\csname#1#2\string~\endcsname=\undefined@}
+%
+\def\testarr@y#1(#2){%
+ \expandafter\let\expandafter\temp@macro\csname#1#2\string~\endcsname
+ \ifx\temp@macro\relax \def\temp@macro{}\fi}%
+%
+\def\arr@y#1(#2){\def\check@VEC{%
+ \ifx=\next@VEC \def\full@VEC####1{\assign@VEC#1(#2)####1}%
+ \else \def\full@VEC{\get@VEC#1(#2)}\fi \full@VEC}%check@VEC
+\futurelet\next@VEC\check@VEC}
+%
+\def\get@index(#1)#2\safty@mark{\one@VEC#2,\safty@mark
+ \def\next@@VEC{#1}\ifx\next@@VEC\empty\def\next@@VEC{\array@width}\fi
+ \if@rev@index
+ {\temp@count=1 \advance\index@count1 \relax
+ \ifnum\index@count<\index@total
+ \loop \multiply\temp@count \next@@VEC
+ \advance\index@count-1 \relax
+ \ifnum\index@count>0 \repeat
+ \fi \global\temp@@count\temp@count }%
+ \else \multiply\temp@@count \next@@VEC \fi
+ \ifnum\temp@@count=0 \temp@@count=1 \relax \fi
+ \advance\temp@count-1 \ifnum\temp@count<0 \temp@count=0 \fi
+ \multiply\temp@count \temp@@count
+ \advance\temp@@@count by \temp@count \advance\index@count1
+ \ifone@VEC
+ \def\next@@VEC{\index@total=\index@count \advance\temp@@@count1 }%
+ \else \one@VEC#2\safty@mark \edef\next@@VEC{\noexpand\get@index(#1)%
+ \the\temp@toks\noexpand\safty@mark}%
+ \fi \next@@VEC}%
+%
+\def\one@VEC#1,#2\safty@mark{\def\temp@macro{#2}\temp@toks={#2}%
+ \ifx\temp@macro\empty \one@VECtrue \else \one@VECfalse \fi
+ \temp@count=#1 \relax }%
+%
+\def\get@all@index(#1)#2\safty@mark{%
+ \temp@@@count=0 \temp@@count=0 \index@count=0 \@rev@indexfalse
+ \get@index(#1)#2\safty@mark
+ \ifnormalindex\else
+ \temp@@@count=0 \temp@@count=0 \index@count=0 \@rev@indextrue
+ \get@index(#1)#2\safty@mark \fi }%
+%
+\def\read@array[#1]#2#3{\temp@count=1
+ \def\one@item##1#1##2\safty@mark{\def\temp@macro{##2}\temp@toks={##2}%
+ \ifx\temp@macro\empty\else
+ \def\temp@macro{\one@item##2\safty@mark}\fi
+ {\temp@toks={##1}\def\temp@@macro{\arr@y{#2}(\the\temp@count)=}%
+ \expandafter\temp@@macro\expandafter{\the\temp@toks}}%
+ \expandafter\edef\csname total@#2\endcsname{\the\temp@count}%
+ \advance\temp@count1 \temp@macro}%
+ \one@item#3#1\safty@mark }%
+%
+\def\strip@esc#1{\temp@count=\escapechar \escapechar=-1 %
+ \temp@toks=\expandafter{\string#1}\escapechar\temp@count}
+\def\get@max@count#1#2{\edef\temp@macro{\csname #1\endcsname}%
+ \ifnum\temp@macro<#2 \expandafter\xdef\csname #1\endcsname{\the#2}\fi}%
+%
+\def\newarray#1{\strip@esc{#1}%
+ \expandafter\gdef\csname total@\the\temp@toks\endcsname{0}%
+ \expandafter\edef\csname\the\temp@toks\endcsname(##1)%
+ {\noexpand\get@all@index(\noexpand\dataheight)##1\noexpand\safty@mark
+% \noexpand\get@max@count{total@\the\temp@toks}\noexpand\temp@@@count
+ \noexpand\arr@y{\the\temp@toks}(\noexpand\the\noexpand\temp@@@count)}%
+ \expandafter\edef\csname check\the\temp@toks\endcsname(##1)%
+ {\noexpand\get@all@index(\noexpand\dataheight)##1\noexpand\safty@mark
+ \noexpand\testarr@y{\the\temp@toks}(\noexpand\the
+ \noexpand\temp@@@count)\noexpand\let\noexpand\cachedata
+ \noexpand\temp@macro\noexpand\ifx\noexpand\temp@macro\noexpand\empty
+ \noexpand\emptydatatrue\noexpand\else\noexpand\emptydatafalse
+ \noexpand\fi}}%
+%
+\def\delarray#1{\strip@esc{#1}% delete array globally
+ \temp@count=0 \temp@@count=\csname total@\the\temp@toks\endcsname
+ \loop \expandafter\global\expandafter\let
+ \csname\the\temp@toks\string~\endcsname\undefined@
+ \advance\temp@count1 %
+ \ifnum\temp@count<\temp@@count \repeat % global loop for less memory
+ \global\expandafter\let\csname total@\the\temp@toks\endcsname\undefined@
+ \global\expandafter\let\csname \the\temp@toks\endcsname\undefined@
+ \global\expandafter\let\csname check\the\temp@toks\endcsname\undefined@ }%
+%
+\def\readarray#1#2{\read@array[&]{#1}{#2}}%
+%
+\catcode`\@=\EntryArrayJob\relax
+%
+%
+% EXIST FILE ?
+%
+% \temp@iftrue if the file #1 exist when tested via \existfile{#1}%
+% \newread\temp@read
+\def\existfile#1{\temp@iftrue
+\openin\temp@read=#1\relax
+\ifeof\temp@read \temp@iffalse \fi \closein\temp@read}%
+%
+% RAW CHARACTERS
+%
+\def\raw@chars[#1][#2][#3][#4][#5]{%
+ % #1=11, #2=\`=12, #3=^^I=10, #4=char32=10, #5=^^M=5
+ % all chars of catcode 11 or 12 are NOT changed
+ \temp@count=-1\relax %
+ \l@@p \advance\temp@count1\relax %
+ \temp@@count=\the\catcode\temp@count \relax
+ \ifnum\temp@@count=11 \else
+ \ifnum\temp@@count=12 \else
+ \catcode\temp@count=11\relax \fi\fi
+ \ifnum\temp@count<\MAX@CHR@CODE\repe@t %
+ \catcode`\%=#1\catcode`\^=#1\catcode`\_=#1%
+ \catcode`\&=#1\catcode`\$=#1\catcode`\#=#1%
+ \catcode`\{=#1\catcode`\}=#1\catcode`\@=#1%
+ \catcode`\~=#1\catcode`\\=#1%
+ \catcode`\`=#2\catcode`\^^I=#3\catcode`\ =#4%
+ \catcode`\^^M=#5\relax %
+}%
+%
+\chardef\temp@char=`\`\catcode`\`=13\relax
+\def\rm@ligature{\def`{\null\string`}}%
+\catcode\temp@char=12\relax
+%
+\catcode`\^^I=13\relax%
+\def\set@tab{\def^^I{\ \ \ \ \ \ \ \ }}\catcode`\^^I=10\relax%
+\catcode`\^^M=13\relax\def\set@cr{\def^^M{\par}}\catcode`\^^M=5\relax%
+\catcode`\ =13\relax\def\set@space{\def {\ }}\catcode`\ =10\relax%
+%
+% TEST EMPTY LINE
+%
+\catcode`\ =13\relax% space active
+%
+% Delete leading spaces (catcode=13)
+% Throw the rest to \temp@macro
+\long\def\del@truespaces#1#2\s@fetymark{\temp@iffalse%
+\def\temp@macro{#1}\def\one@space{ }\def\temp@@macro{}%
+\ifx\temp@macro\one@space% front spaces not allowed
+\def\temp@macro{#2}%
+\ifx\temp@macro\empty\temp@iftrue%
+\else\def\temp@@macro{\del@truespaces#2\s@fetymark}\fi%
+\fi%
+\temp@@macro}%
+%
+\catcode`\ =10\relax%
+%
+% \temp@iftrue if empty line,
+% \temp@macro holds nonspace part (space catcode=13 or normal)
+\long\def\is@emptyline#1{\def\one@space{ }%
+ \def\temp@macro{#1}\def\temp@@macro{}\temp@iftrue
+ \ifx\temp@macro\empty
+ \else \ifx\temp@macro\one@space
+ \else \def\temp@@macro{\del@truespaces#1\s@fetymark}%
+ \fi
+ \fi
+\temp@@macro}%
+%
+% TEST STRING
+%
+%% \newif\iftemp@if \newtoks\temp@toks
+% return \iftemp@iftrue if yes,
+% \first@half,\second@half are global
+\long\def\test@str#1#2{%
+ \long\def\strip@endmark##1\s@fetymarkI#1\s@fetymark{%
+ \gdef\second@half{##1}}%
+ \long\def\strip@markI##1\s@fetymarkI\s@fetymark{%
+ \gdef\first@half{##1}}%
+ \long\def\p@rse##1#1##2\s@fetymark{%
+ \gdef\first@half{##1}%
+ \gdef\second@half{##2}%
+ \ifx\second@half\empty
+ \strip@markI##1\s@fetymark \temp@iffalse
+ \else
+ \strip@endmark##2\s@fetymark \temp@iftrue
+ \fi}%
+ \temp@toks={#2\s@fetymarkI#1\s@fetymark}%
+ \expandafter\p@rse\the\temp@toks }%
+%
+% #1 supposed to a toks register
+\long\def\test@tokstr#1#2{% #1 =toks
+ \temp@toks={#2}%
+ \edef\temp@macro{\noexpand\test@str{#1}{\the\temp@toks}}%
+ \temp@macro }%
+%
+% MAKE ESCAPE CHAR
+%
+% \esc@=the character '\' of catcode 11
+\newtoks\name@endtoks \newtoks\true@endtoks
+\catcode`\*=0\relax *catcode`*\=11*relax
+*gdef*esc@{\}%*name@endtoks={\endrawlist}%
+*catcode`*\=0*relax \catcode`\*=12\relax
+%
+%
+% TWO DIMENSIONAL ARRAY / LETTER PARAMETER STACKS
+%
+\def\stack@num@twodim[#1]{\temp@count=-1%
+ \expandafter\ifx\csname #1*0\string~\endcsname\undefined@
+ \temp@count=0\fi
+ \expandafter\ifx\csname #1*0\string~\endcsname\relax
+ \temp@count=0\fi \relax
+ \ifnum\temp@count<0
+ \temp@count=\csname #1*0\string~\endcsname \relax
+ \else \expandafter\gdef
+ \csname #1*0\string~\endcsname{0}%
+ \fi }%
+%
+%
+\newcount\R@Wcount \R@Wcount=0
+\newcount\R@Dcount \R@Dcount=0
+\newif\ifload@defaults \load@defaultsfalse % i.e. to LET stack (not DEF)
+%
+\long\def\rowpush#1{%
+\ifload@defaults % for default para stack
+ \ifnum\R@Dcount>0\else \global\R@Dcount=1 \fi
+ \stack@num@twodim[DEF\the\R@Dcount]%
+ \advance\temp@count1\relax
+ \expandafter\gdef
+ \csname DEF\the\R@Dcount*\the\temp@count\string~\endcsname{#1}%
+ \expandafter\xdef\csname DEF\the\R@Dcount*0\string~\endcsname
+ {\the\temp@count}%
+\else
+ \ifnum\R@Wcount>0\else \global\R@Wcount=1 \fi
+ \stack@num@twodim[LET\the\R@Wcount]%
+ \advance\temp@count1\relax
+ \expandafter\gdef
+ \csname LET\the\R@Wcount*\the\temp@count\string~\endcsname{#1}%
+ \expandafter\xdef\csname LET\the\R@Wcount*0\string~\endcsname
+ {\the\temp@count}%
+\fi
+}%
+%
+\def\clr@row{%
+\ifload@defaults % for default para stack
+ \stack@num@twodim[DEF\the\R@Dcount]%
+ {\loop \ifnum\temp@count>0\relax
+ \global\expandafter\let
+ \csname DEF\the\R@Dcount*\the\temp@count\string~\endcsname=\undefined@%
+ \advance\temp@count-1\relax \fi
+ \ifnum\temp@count>0 \repeat}%
+ \global\expandafter\let
+ \csname DEF\the\R@Dcount*0\string~\endcsname=\undefined@
+\else
+ \stack@num@twodim[LET\the\R@Wcount]%
+ {\loop \ifnum\temp@count>0\relax
+ \global\expandafter\let
+ \csname LET\the\R@Wcount*\the\temp@count\string~\endcsname=\undefined@%
+ \advance\temp@count-1\relax \fi
+ \ifnum\temp@count>0 \repeat}%
+ \global\expandafter\let
+ \csname LET\the\R@Wcount*0\string~\endcsname=\undefined@
+\fi
+}%
+%
+\def\clr@allrows{%
+\ifload@defaults
+% for default para stack
+ {\loop \ifnum\R@Dcount>0\relax {\clr@row}%
+ \global\advance\R@Dcount-1\relax \fi
+ \ifnum\R@Dcount>0 \repeat}%
+ \global\R@Dcount=0\relax
+\else
+ {\loop \ifnum\R@Wcount>0\relax {\clr@row}%
+ \global\advance\R@Wcount-1\relax \fi
+ \ifnum\R@Wcount>0 \repeat}%
+ \global\R@Wcount=0\relax
+\fi
+}%
+%
+% LOAD DEFAULT
+% update paras in LET array with defaults in DEF array
+%
+% \newtoks\temp@toks
+\newif\ifnodefaults \nodefaultsfalse
+\def\sub@loop{% \sub@loop is always called via {\sub@loop}
+ \loop % inner loop: reverse order
+ \temp@@count=0 % flag -> not counter: 0=no need for updating
+ \expandafter\ifx\csname LET\the\temp@@@count*\the\temp@count
+ \string~\endcsname\undefined@ \temp@@count=1\fi
+ \expandafter\ifx\csname LET\the\temp@@@count*\the\temp@count
+ \string~\endcsname\relax \temp@@count=1\fi\relax
+ %
+ \expandafter\ifx\csname LET\the\temp@@@count*\the\temp@count
+ \string~\endcsname\trivi@l \temp@@count=1\fi\relax
+ %
+ \ifnum\temp@@count>0
+ \expandafter\let\expandafter\temp@macro
+ \csname DEF\the\temp@@@count*\the\temp@count\string~\endcsname
+ \temp@toks=\expandafter{\temp@macro}%
+ \ifx\temp@macro\relax \global\expandafter\let
+ \csname LET\the\temp@@@count*\the\temp@count\string~\endcsname
+ =\undefined@
+ \else \expandafter\xdef
+ \csname LET\the\temp@@@count*\the\temp@count\string~\endcsname
+ {\the\temp@toks}\fi
+ \fi
+ \advance\temp@count-1\relax
+ \ifnum\temp@count>0
+ \repeat}% for speed
+%
+% above macro not to stand alone
+% it is removed from \loaddefaultparas for better speed
+%
+\def\loaddefaultparas{%
+\ifnodefaults\else % active only if \nodefaultsfalse
+ \def\trivi@l{\b@group\relax\e@group}% == empty parameter
+ \temp@count=\R@Wcount
+ {\loop % legalise LET array's extension
+ \advance\temp@count1\relax
+ \ifnum\temp@count>\R@Dcount\else
+ \expandafter\xdef
+ \csname LET\the\temp@count*0\string~\endcsname{0}\fi
+ \ifnum\temp@count<\R@Dcount \repeat}%
+ \ifnum\R@Wcount<\R@Dcount \global\R@Wcount=\R@Dcount \fi
+%
+ \temp@@@count=1 % row counter
+ {\loop
+ \stack@num@twodim[DEF\the\temp@@@count]%
+ \temp@@count=\temp@count\relax
+ \stack@num@twodim[LET\the\temp@@@count]%
+ \ifnum\temp@count<\temp@@count \temp@count=\temp@@count\relax \fi
+ % update LET array's counter
+ \expandafter\xdef
+ \csname LET\the\temp@@@count*0\string~\endcsname{\the\temp@count}%
+ % now \temp@count is current max row width
+ {\sub@loop}% update a row
+ \advance\temp@@@count 1\relax
+ \ifnum\temp@@@count>\R@Wcount\temp@@count=0\else\temp@@count=1\fi
+ \relax
+ \ifnum\temp@@count>0 \repeat}%
+\fi % of \ifnodefaults
+}%
+%
+% HOUSE KEEPING
+%
+\newif\ifshowp@r@ \showp@r@true % default mode
+\def\show@paras{\showp@r@true\lettercontents}%
+\def\showparas{\show@paras}%
+%
+\def\b@group{\iflocalparas\bgroup\fi}%
+\def\e@group{\iflocalparas\egroup\fi}%
+%
+\long\def\lettercontents{}%
+%
+\def\inputletter#1{\save@catcodes[OLD][0][\MAX@CHR@CODE][/13/]\beginletter
+ \save@catcodes[TMP][0][\MAX@CHR@CODE][]\get@catcodes[OLD]\existfile{#1}%
+ \iftemp@if \input#1%
+ \else \immediate\write16{Letter File <#1> not found.}\fi
+ \get@catcodes[TMP]\endletter}%
+%
+\def\inputfile#1{\relax\existfile{#1}\iftemp@if
+ \input#1 \else \immediate\write16{File <#1> not found.}\fi
+ \relax}%
+%
+\def\preview{\preview@}%
+%
+%
+% PAGE NUMBER
+% for both TeX and LaTeX
+%
+\ifISLATEX
+ \let\PAGENO=\c@page \def\NOPAGENUMBERS{\pagestyle{empty}}\else
+ \let\PAGENO=\pageno \let\NOPAGENUMBERS=\nopagenumbers \fi
+%
+%
+% SINGLE PARAMETER
+%
+\def\paras{\push{%
+ \edef\next@@{\noexpand\rowcolp@r@s[\the\p@r@two][\the\p@r@one]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas\left@1\right@\left@1\right@\p@r@end}%
+%
+% NOTE:
+% 1. default parameters are enclosed between \left@ and \right@,
+% and is supplied after \st@ckparas. All defaults (may be empty) must
+% be supplied.
+% 2. \rowcolp@r@s is the name of the macro that doesn't take defaults
+% 3. \the\p@r@one, .., \the\p@r@nine represent #1,.., #9 .
+% 4. \paras is the new macro that behaves like \rowcolp@r@s but now
+% takes defaults
+% 5. change accordingly if one wants to implement defaults to other
+% existing macros.
+% 6. limitation: '[' and ']' are now not allowed as macro parameters.
+%
+%
+\def\rowcolp@r@s[#1][#2]{%
+ \ifpreview {\leavevmode
+ \boxmore[1pt]{\boxmore[3pt]{\hbox
+ {\font\tiny@rm=cmr5\tiny@rm ~#1 -- #2~}}}}\relax
+ \else \csname LET#1*#2\string~\endcsname \fi}%
+%
+%
+% GET \paras[m][n] AND TEST EMPTYNESS
+% \checkparas[m][n]{T} stores true content of \Tm*n~ into \cachedata
+% and set \ifemptyparas to true if the content is empty
+%
+% Typical use: \checkparas[m][n]{LET} \checkparas[m][n]{DEF}
+%
+\newif\ifemptyparas
+\def\check@@paras[#1][#2]#3{%
+ \expandafter\let\expandafter\cachedata\csname #3#1*#2\string~\endcsname
+ \ifx\cachedata\relax \def\cachedata{}\else
+ \temp@toks=\expandafter{\cachedata}%
+ \def\cachedata\b@group\relax##1\e@group\safty@mark{\def\cachedata{##1}}%
+ \expandafter\cachedata\the\temp@toks\safty@mark \fi
+ \ifx\cachedata\empty\emptyparastrue\else\emptyparasfalse\fi}%
+\def\check@paras[#1][#2]#{\check@@paras[#1][#2]}%
+\def\checkparas{\push{%
+ \edef\next@@{\noexpand\check@paras[\the\p@r@two][\the\p@r@one]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas\left@1\right@\left@1\right@\p@r@end}%
+%
+%
+% ADDRESS BOXES
+%
+% \newbox\temp@box\newdimen\temp@dim
+\long\def\fig@box[#1]#2{%#1=width of box
+ \setbox\temp@box=\vbox{\hsize #1\noindent\strut #2\strut}%
+ \temp@dim=\ht\temp@box
+ \advance\temp@dim\dp\temp@box\advance\temp@dim-2ex
+ \dp\temp@box=\temp@dim\ht\temp@box=2ex\box\temp@box}%
+%
+\long\def\textbox{\push{%
+ \edef\next@@{\noexpand\fig@box[\the\p@r@one]}%
+ \popnil\next@@}\st@ckparas\left@8truecm\right@\p@r@end}%
+%
+\ifx\figbox\undefined@\let\figbox\textbox\fi % compatibility with ver 2.03
+%
+\long\def\box@more[#1]#2{\vbox{\hrule\hbox{\vrule\kern#1\vbox
+ {\kern#1\hbox{#2}\kern#1}\kern#1\vrule}\hrule}}%
+%
+\long\def\boxmore{\push{%
+ \edef\next@@{\noexpand\box@more[\the\p@r@one]}%
+ \popnil\next@@}\st@ckparas\left@3pt\right@\p@r@end}%
+%
+\long\def\address@box[#1][#2]#3{%
+ \noindent\hskip#2\textbox[#1]{\hskip-#2\relax #3}}%
+%
+\long\def\addressbox{\push{%
+ \edef\next@@{\noexpand\address@box%
+ [\the\p@r@one][\the\p@r@two]}%
+ \popnil\next@@}\st@ckparas\left@8truecm\right@\left@1.5em\right@\p@r@end}%
+%
+\long\def\ADDRESSBOX#1#2#3{% intended for \blockparas
+ \noindent\hskip#2\textbox[#1]{\hskip-#2\relax #3}}%
+%
+%
+% BLOCKPARAS and ADDRESSPARAS
+%
+\newcount\blockC@Lcount \newcount\blockT@Pcount
+\long\def\block@paras[#1][#2][#3][#4]{% #2-th group, from #1 to end,
+ % each para is surrounded by #3 from left and #4 from right
+ % If #4=\relax, an extra {} is applied to the \paras so that
+ % #3 may be a macro acting on the \paras
+ \def\next@one{#2}\def\next@two{#1}\def\next@three{#3}\def\next@four{#4}%
+ \ifx\next@one\empty\def\next@one{1}\fi
+ \ifx\next@two\empty\def\next@two{1}\fi
+ \ifpreview {\leavevmode % three line border box
+ \boxmore[1pt]{\boxmore[1pt]{\boxmore[3pt]{\hbox
+ {\font\tiny@rm=cmr5\tiny@rm \font\small@tt=cmtt8%
+ ~\next@one ~-- \next@two~(+):~
+ \small@tt\meaning\next@three
+ ~<<paras>> \meaning\next@four}}}}}\relax
+ \else
+ \blockC@Lcount=-1%
+ \expandafter\ifx\csname LET\next@one*0\string~\endcsname\undefined@
+ \blockC@Lcount=0\fi
+ \expandafter\ifx\csname LET\next@one*0\string~\endcsname\relax
+ \blockC@Lcount=0\fi \relax
+ \ifnum\blockC@Lcount<0
+ \blockC@Lcount=\csname LET\next@one*0\string~\endcsname\relax \fi
+ \blockT@Pcount=\next@two
+ \advance\blockT@Pcount by-1\relax
+ \l@@p % not to be grouped
+ \advance\blockT@Pcount1\relax
+ \ifnum\blockT@Pcount>\blockC@Lcount\else
+ \def\temp@macro{\relax}% some overhead, but safer
+ \ifx\next@four\temp@macro % add {} to \paras, so that a macro can act
+ % on the whole \paras
+ \next@three{\csname LET\next@one*\the\blockT@Pcount\string~\endcsname}%
+ \else
+ \next@three\csname LET\next@one*\the\blockT@Pcount
+ \string~\endcsname\next@four
+ \fi
+ \fi
+ \ifnum\blockT@Pcount<\blockC@Lcount\repe@t
+\fi}%
+%
+%
+\def\blockparas{\push{%
+ \edef\next@@{\noexpand\block@paras[\the\p@r@one][\the\p@r@two]%
+ [\the\p@r@three][\the\p@r@four]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas\left@1\right@\left@1\right@%
+ \left@\noindent\right@\left@\par\right@\p@r@end}%
+%
+%
+\long\def\address@paras[#1][#2][#3][#4]{%
+ \block@paras[#1][#2][\par\noindent\ADDRESSBOX{#3}{#4}][\relax]\par}%
+%
+\def\addressparas{\push{%
+ \edef\next@@{\noexpand\address@paras[\the\p@r@one][\the\p@r@two]%
+ [\the\p@r@three][\the\p@r@four]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas\left@1\right@\left@1\right@%
+ \left@8truecm\right@\left@1.5em\right@\p@r@end}%
+%
+%
+% MAIN PROCESSING MACRO
+%
+\newif\ifconti@one \newif\ifconti@two
+\newif\ifl@stline \newif\ifl@stLINE
+\newif\ifpreview \previewfalse
+\newif\iflocalparas \localparastrue
+%
+\newtoks\name@paratoks \name@paratoks={;}%
+\newtoks\name@grouptoks \name@grouptoks={+}%
+\newtoks\name@clustertoks \name@clustertoks={!}%
+%
+%
+\long\def\delimiters#1#2#3{% LONG MACRO
+%
+%%%% MAIN GET: get a group of parameters from a cluster
+%
+\long\def\refillst@ck##1#3{\def\d@t@one{##1#3}%
+ {\loop\conti@onefalse
+ \ifx\d@t@one\undefined@ \else \@ddoneline\conti@onetrue\fi
+ \ifconti@one\repeat}}%
+%
+\long\def\testl@stline##1#2##2#3##3\s@fetymark{%
+ \def\next{##2}\ifx\next\empty
+ \l@stlinetrue \else \l@stlinefalse \fi
+ \def\next{##3}\def\nextsample{#2#3}%
+ \ifx\next\nextsample\l@stlinefalse\fi}%
+%
+\long\def\l@stline##1#3{{\sub@fill{##1}}\let\d@t@one=\undefined@}%
+\long\def\onem@reline##1#2##2#3{{\sub@fill{##1}}\def\d@t@one{##2#3}}%
+%
+\long\def\@ddoneline{\temp@toks=\expandafter{\d@t@one}%
+ \expandafter\testl@stline\the\temp@toks#2#3\s@fetymark
+ \ifl@stline \expandafter\l@stline\the\temp@toks
+ \else \expandafter\onem@reline\the\temp@toks \fi}%
+%
+%%%% SUB GET : get parameters from a group
+%
+\long\def\sub@fill##1{%
+ \ifload@defaults \global\advance\R@Dcount by 1\else
+ \global\advance\R@Wcount by 1\fi\relax
+ \clr@row\def\d@t@two{\relax##1#3}% %%care: extra \relax added
+ {\loop\conti@twofalse
+ \ifx\d@t@two\undefined@ \else \@ddoneLINE\conti@twotrue\fi
+ \ifconti@two\repeat}}%
+%
+\long\def\moreletter##1#3{\showp@r@false
+ \clr@allrows\refillst@ck##1#3\lettercontents\clr@allrows\showp@r@true}%
+%
+\def\endletter{\relax}%
+\long\def\true@letter##1\endletter{\long\def
+ \lettercontents{\begingroup\catcode`\^^M=5\relax
+ \def\pstr{#1}\def\gstr{#2}\def\cstr{#3}\relax##1\relax\endgroup}}%
+\let\beginletter\true@letter
+%
+\long\def\testl@stLINE##1#1##2#3##3\s@fetymark{%
+ \def\next{##2}\ifx\next\empty%
+ \l@stLINEtrue \else \l@stLINEfalse \fi%
+ \def\next{##3}\def\nextsample{#1#3}%
+ \ifx\next\nextsample\l@stLINEfalse\fi}%
+%
+\long\def\l@stLINE##1#3{%
+ \rowpush{\b@group##1\e@group}\let\d@t@two=\undefined@}%
+ \long\def\onem@reLINE##1#1##2#3{%
+ \rowpush{\b@group##1\e@group}\def\d@t@two{\relax##2#3}}%%care
+%
+\long\def\@ddoneLINE{\temp@toks=\expandafter{\d@t@two}%
+ \expandafter\testl@stLINE\the\temp@toks#1#3\s@fetymark%
+ \ifl@stLINE\expandafter\l@stLINE\the\temp@toks %
+ \else \expandafter\onem@reLINE\the\temp@toks \fi}%
+%
+\def\para@names{\ifshowp@r@
+ \def\next@@{{\load@defaultsfalse\clr@allrows}\refillst@ck}\else
+ \long\def\next@@####1#3{\relax}\fi \next@@}%
+%
+\long\def\para@defaults##1#3{\load@defaultstrue
+ \clr@allrows\refillst@ck##1#3\load@defaultsfalse}%
+%
+\def\preview@{{\previewtrue\moreletter #3}}%
+%
+\long\def\out@letter##1#3{\showp@r@false\clr@allrows
+ \refillst@ck##1#3\lettercontents\clr@allrows\showp@r@true
+ \pile@letters}%
+%
+\name@paratoks={#1}\name@grouptoks={#2}\name@clustertoks={#3}%
+%
+}% END OF LONG MACRO
+%
+\long\def\paranames#1!{\ifshowp@r@
+ \begingroup\delimiters{;}{+}{!}\para@names#1!\endgroup\fi}%
+\long\def\paradefaults#1!{%
+ \begingroup\delimiters{;}{+}{!}\para@defaults#1!\endgroup}%
+%
+\def\delparadefaults{{\load@defaultstrue\clr@allrows}}%
+%
+\def\defaultmarks{\delimiters{;}{+}{!}}%
+\def\blockmarks{\delimiters{....}{----}{====}}%
+%
+%
+% TEST MACRO
+%
+% test if a token is a macro
+% \newif\iftemp@if
+\def\sub@ismacro#1#2#3#4#5#6#7\s@fetymark{% check only 'm,c,:'
+ \if#1m\else\temp@iffalse\fi % \if#2a\else\temp@iffalse\fi
+ \if#3c\else\temp@iffalse\fi % \if#4r\else\temp@iffalse\fi
+ \if#6:\else\temp@iffalse\fi }% \if#5o\else\temp@iffalse\fi
+%
+\def\ismacro#1#2\s@fetymark{%\expandafter\ismacro\meaning\token\s@fetymark
+ \temp@iftrue
+ \if#1\esc@\else
+ \sub@ismacro#1#2\s@fetymark
+ \fi }%
+%
+\long\def\del@token#1{}%
+\def\del@space#1 {}%
+%
+% PILEMODE: the basic mode
+%
+\def\pile@letters{%
+\def\check@{%
+ \def\buffer@{\out@letter}%
+ \def\one@space{ }%
+ \expandafter\ismacro\meaning\next@\s@fetymark %
+ \ifx\next@\undefined@\temp@iftrue \fi %
+ \iftemp@if %
+ \ifx\par\next@ \def\buffer@{\expandafter\pile@letters\del@token}%
+ \else \ifx\endpilemode\next@\def\buffer@{}\fi %
+ \fi %
+ \else %
+ \if\one@space\next@%
+ \def\buffer@{\expandafter\pile@letters\del@space}%
+ \fi %
+ \fi\buffer@}%
+\futurelet\next@\check@}%
+%
+\def\beginpilemode{\showp@r@false
+ \def\preview{}\def\showparas{}\pile@letters}%
+\def\endpilemode{%
+ \def\preview{\preview@}\def\showparas{\show@paras}\showp@r@true}%
+%
+%
+% LINEMODE: cr separate paras, empty line eject letter
+%
+\catcode`\^^M=13\relax%
+%
+% remove empty or space only lines, then control to \line@chkline
+\long\def\line@curbfront#1^^M{%
+ \is@emptyline{#1}%
+ \iftemp@if \def\buffer@{\line@curbfront}%
+ \else \def\buffer@{\line@chkline#1^^M}% control to \line@chkline
+ \fi \buffer@ }%
+%
+% \newtoks\temp@@toks
+% \name@endtoks and \true\end@toks must be given on entry
+\long\def\line@chkline#1^^M{%
+ \test@tokstr{\the\name@endtoks}{#1}%
+ \iftemp@if %
+ \temp@toks=\expandafter{\first@half}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if\else%
+ \expandafter\rowpush\expandafter{\expandafter%
+ \b@group\expandafter\relax\the\temp@toks\e@group}%
+ \fi%
+ \temp@toks=\expandafter{\second@half}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if \temp@toks={}\fi%
+ \iftemp@if\else %
+ {\is@rawmode9/1/13/13/1/13/32/1/13/96/1/13/0/0/0/%
+ \iftemp@if \message{<!>}\let\ =\space %
+ \wlog{(Verbatim: \second@half)}\fi}\fi%
+ \ifnum\R@Wcount=0\temp@@toks={}\else%
+ \temp@@toks={\showp@r@false\lettercontents\clr@allrows\showp@r@true}%
+ \fi%
+ \edef\buffer@{\the\temp@@toks\the\true@endtoks\the\temp@toks}%
+ \else %
+ \temp@toks=\expandafter{\first@half}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if%
+ \temp@@toks={\showp@r@false\lettercontents\clr@allrows\showp@r@true}%
+ \edef\buffer@{\the\temp@@toks\noexpand\line@curbfront}%
+ \else%
+ \expandafter\rowpush\expandafter{\expandafter%
+ \b@group\expandafter\relax\the\temp@toks\e@group}%
+ \let\buffer@=\line@chkline%
+ \fi%
+ \fi \buffer@%
+}%
+%
+\catcode`\^^M=5\relax%
+%
+% NORMAL LINEMODE HANDLER
+%
+\def\beginlinemode{%
+ \true@endtoks={\endlinemode}%
+ \name@endtoks={\endlinemode}\showp@r@false\catcode`\^^M=13\relax %
+ \def\preview{}\def\showparas{}\clr@allrows\line@curbfront }%
+%
+\def\endlinemode{\catcode`\^^M=5\relax%\defaultmarks
+ \def\preview{\preview@}\def\showparas{\show@paras}\showp@r@true }%
+%
+% RAW TEXT LINEMODE HANDLER
+%
+\def\endrawlinemode{\get@catcodes[RAW]\showp@r@true}%
+\def\beginrawlinemode#{\begin@rawlinemode}%
+\def\begin@rawlinemode#1{\save@catcodes[RAW][0][\MAX@CHR@CODE][]%
+ \def\temp@macro{#1}% #1=token to end the list
+ \ifx\temp@macro\empty
+ \temp@toks=\expandafter{\esc@}%
+ \name@endtoks=\expandafter{\the\temp@toks endrawlinemode}%
+ \else \name@endtoks={#1}%
+ \fi
+ \true@endtoks={\endlinemode\endrawlinemode}%
+ \rm@ligature\set@space\set@tab\raw@chars[11][13][13][13][13]%
+ \showp@r@false\clr@allrows\line@curbfront }%
+%
+%
+% BLOCKMODE: cr separate paras
+%
+% line containing '+' (\name@grouptoks) separates groups
+% line containing '!' (\name@clustertoks) separates clusters
+%
+\catcode`\^^M=13\relax%
+%
+% remove empty or space only lines, then control to \block@chkline
+\long\def\block@curbfront#1^^M{%
+ \is@emptyline{#1}%
+ \iftemp@if \let\buffer@=\block@curbfront %
+ \else \test@tokstr{\the\name@endtoks}{#1}%
+ \iftemp@if \def\buffer@{\block@chkline#1^^M}%
+ \else \test@tokstr{\the\name@clustertoks}{#1}%
+ \iftemp@if \let\buffer@=\block@curbfront%
+ \else \test@tokstr{\the\name@grouptoks}{#1}%
+ \iftemp@if \def\buffer@{\block@chkline#1^^M}%
+ \else \test@tokstr{\the\name@paratoks}{#1}%
+ \iftemp@if \let\buffer@=\block@chkline%
+ \else \def\buffer@{\block@chkline#1^^M}% control to \block@chkline
+ \fi %
+ \fi %
+ \fi%
+ \fi %
+ \fi \buffer@ }%
+%
+% \name@endtoks and \true\end@toks must be given on entry
+\long\def\block@chkline#1^^M{%
+ \test@tokstr{\the\name@endtoks}{#1}%
+ \iftemp@if %
+ \ifnum\R@Wcount=0%
+ \temp@toks={\clr@allrows\showp@r@true}%
+ \else%
+ \temp@toks={\showp@r@false\lettercontents\clr@allrows\showp@r@true}%
+ \fi%
+ \edef\buffer@{\the\temp@toks\the\true@endtoks}%
+ \else %
+ \test@tokstr{\the\name@clustertoks}{#1}%
+ \iftemp@if%
+ \def\buffer@{\showp@r@false\lettercontents\clr@allrows%
+ \showp@r@true\block@curbfront}%
+ \else%
+ \test@tokstr{\the\name@grouptoks}{#1}%
+ \iftemp@if%
+ \ifnum\R@Wcount<1\global\R@Wcount=1\relax\fi %
+ \global\advance\R@Wcount1\relax%
+ \else%
+ \rowpush{\b@group\relax#1\e@group}%
+ \fi%
+ \let\buffer@=\block@chkline %
+ \fi%
+ \fi \buffer@%
+}%
+%
+\catcode`\^^M=5\relax%
+%
+% NORMAL BLOCKMODE HANDLER
+%
+\def\beginblockmode{%
+ \true@endtoks={\endblockmode}%
+ \name@endtoks={\endblockmode}\showp@r@false\catcode`\^^M=13\relax %
+ \def\preview{}\def\showparas{}\clr@allrows\block@curbfront }%
+%
+\def\endblockmode{\catcode`\^^M=5\relax%\defaultmarks
+ \def\preview{\preview@}\def\showparas{\show@paras}\showp@r@true }%
+%
+% RAW TEXT BLOCKMODE HANDLER
+%
+\def\endrawblockmode{\get@catcodes[RAW]\showp@r@true}%
+\def\beginrawblockmode#{\begin@rawblockmode}%
+\def\begin@rawblockmode#1{\save@catcodes[RAW][0][\MAX@CHR@CODE][]%
+ \def\temp@macro{#1}% #1=token to end the list
+ \ifx\temp@macro\empty
+ \temp@toks=\expandafter{\esc@}%
+ \name@endtoks=\expandafter{\the\temp@toks endrawblockmode}%
+ \else \name@endtoks={#1}%
+ \fi
+ \true@endtoks={\endblockmode\endrawblockmode}%
+ \rm@ligature\set@space\set@tab\raw@chars[11][13][13][13][13]%
+ \showp@r@false \clr@allrows\block@curbfront }%
+%
+%
+% DATAMODE: every <m> lines eject a letter (raw tex mode)
+%
+\catcode`\^^M=13\relax %
+\newcount\data@count %
+%
+% \name@endtoks and \true\end@toks must be given on entry
+\long\def\data@chkline#1^^M{\test@tokstr{\the\name@endtoks}{#1}%
+ \iftemp@if % \first@half is raw text
+ \temp@toks=\expandafter{\first@half}%
+ \temp@@toks=\expandafter{\second@half}%
+ \edef\temp@macro{\the\temp@toks\the\temp@@toks}%
+ \temp@toks=\expandafter{\temp@macro}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if \else\message{<!>}\let\ =\space %
+ \wlog{(Ignored: \first@half<->\second@half)}\fi %
+ \ifnum\R@Wcount=0\temp@@toks={}\else%
+ \ifnum\R@Wcount=\total@data@num\else \message{<!>}%
+ \wlog{(Number of data lines at odds)}\fi %
+ \temp@@toks={\showp@r@false\lettercontents\clr@allrows\showp@r@true}%
+ \fi%
+ \edef\buffer@{\the\temp@@toks\the\true@endtoks}%
+ \else %
+ \temp@toks=\expandafter{\first@half}\advance\data@count1 %
+ \expandafter\rowpush\expandafter{\expandafter%
+ \b@group\expandafter\relax\the\temp@toks\e@group}%
+ \ifnum\data@count<\total@data@num %
+ \let\buffer@=\data@chkline%
+ \else \data@count=0 %
+ \temp@@toks={\showp@r@false\lettercontents\clr@allrows\showp@r@true}%
+ \edef\buffer@{\the\temp@@toks\noexpand\data@chkline}%
+ \fi%
+ \fi \buffer@ }%
+%
+\def\begindatamode{\push{%
+ \edef\next@@{\noexpand\begin@datamode[\the\p@r@one]}%
+ \popnil\next@@}\st@ckparas\left@\right@\p@r@end}%
+%
+\def\begin@datamode[#1]#{\begin@@datamode[#1]}%
+\def\begin@@datamode[#1]#2{\save@catcodes[RAW][0][\MAX@CHR@CODE][]%
+% #1=token to end the list, #2=number of lines for each block
+ \edef\total@data@num{#2}\def\temp@macro{#1}%
+ \ifx\total@data@num\empty \def\total@data@num{1}\fi %
+ \ifnum\total@data@num<1 \def\total@data@num{1}\fi %
+ \ifx\temp@macro\empty %
+ \temp@toks=\expandafter{\esc@}%
+ \name@endtoks=\expandafter{\the\temp@toks enddatamode}%
+ \else \name@endtoks={#1}\fi %
+ \true@endtoks={\endlinemode\endrawlinemode}%
+ \rm@ligature\set@space\set@tab\raw@chars[11][13][13][13][13]%
+ \showp@r@false\clr@allrows\data@count=0 %
+ \def\temp@macro##1^^M{%
+ \test@tokstr{\the\name@endtoks}{##1}%
+ \iftemp@if\else \temp@toks={##1}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if\else \message{<!>}\let\ =\space %
+ \wlog{(Ignored: ##1)}\fi %
+ \fi %
+ \test@tokstr{\the\name@endtoks}{##1}%
+ \iftemp@if \temp@toks=\expandafter{\first@half}%
+ \temp@@toks=\expandafter{\second@half}%
+ \edef\temp@@macro{\noexpand\data@chkline %
+ \the\temp@toks\the\name@endtoks\the\temp@@toks\noexpand^^M}%
+ \else\def\temp@@macro{\data@chkline}\fi\temp@@macro }%
+ \temp@macro }%
+%
+\catcode`\^^M=5\relax%
+%
+%
+% BASIC SETUP
+%
+\new@measures
+\defaultmarks % set up the default delimiters
+%
+%
+% RAW TEXT LISTING and MORE ON MACRO PARAMETER DEFAULTING
+%
+%
+% FLUSH ZEROS \fillzeros[<WIDTH>]<NUMBER>
+%
+%% \newcount\temp@count \newcount\temp@@count
+\def\fillzeros[#1]#2{\temp@@count=#2\relax
+ \ifnum\temp@@count<0 \temp@@count=-\temp@@count\fi
+ \temp@count=1\relax
+ {\loop\ifnum\temp@@count<10 \else
+ \global\divide\temp@@count by 10 \global\advance\temp@count by 1 \fi
+ \ifnum\temp@@count=10\relax\global\temp@@count=11\relax\fi
+ \ifnum\temp@@count>10 \repeat}%
+ \ifnum#2<0 \advance\temp@count1\relax-\fi
+ {\loop\ifnum\temp@count<#1\relax0\advance\temp@count1\fi
+ \ifnum\temp@count<#1 \repeat}%
+ \temp@@count=#2\relax\ifnum\temp@@count<0 \temp@@count=-\temp@@count\fi
+ \the\temp@@count}%
+%
+%
+% BEGINLIST--ENDLIST: activate <space> and <linebreak>
+%
+\catcode`\^^M=13%
+\newcount\linecount\global\linecount=1%
+{\obeyspaces\gdef {\ }}%
+%
+%
+%
+% \name@endtoks: token to end the list
+% \true@endtoks: tokens to be executed at the end
+% \name@endtoks and \true@endtoks must be defined on entry
+% \no@emptylinefalse: the first or the last line empty
+%
+\newif\ifno@emptyline % iftemp@if
+\newif\ifprint@file \global\print@filefalse %
+\def\begin@list[#1][#2][#3][#4][#5][#6]{%
+ \global\linecount=#1\catcode`\^^M=13\no@emptylinetrue %
+ \ifprint@file \def^^M{\put@linenumber}\else\def^^M{\par}\fi %
+ \def\put@linenumber{\par\noindent\hbox to #5{}%
+ \rlap{\hskip-1em\hskip#6%
+ \ifnum#3>0\relax\hbox to0em{\hss#4\fillzeros[#3]\linecount~~}\fi}%
+ \global\advance\linecount#2\relax}%
+ \def\out@aline{%
+ \ifno@emptyline %
+ \expandafter\is@emptyline\expandafter{\first@half}%
+ \ifprint@file \temp@@iffalse \else\temp@@iftrue \fi %
+ \else \temp@iffalse \temp@@iftrue %
+ \fi \no@emptylinefalse%
+ \iftemp@if \else %
+ \iftemp@@if \put@linenumber \fi %
+ \first@half \par % extra \par is absorbed, put here for last line
+ \fi }%
+ \def\readyt@quit{\no@emptylinetrue%
+ {\is@rawmode9/1/13/13/1/13/32/1/13/96/1/13/0/0/0/%
+ \iftemp@if \expandafter\is@emptyline\expandafter{\second@half}%
+ \iftemp@if\else\message{<!>}\let\ =\space %
+ \wlog{(Verbatim: \second@half)}\fi\fi}%
+ \temp@toks=\expandafter{\first@half}%
+ \temp@@toks=\expandafter{\second@half}%
+ \edef\first@half{\the\temp@toks\the\temp@@toks}\out@aline %
+ \edef\temp@macro{\the\true@endtoks}%
+ \temp@macro % \second@half removed
+ }%
+ \def\moret@get{\out@aline\get@phys@line}%
+ \long\def\get@phys@line##1^^M{%
+ \test@tokstr{\the\name@endtoks}{##1}%
+ \iftemp@if \let\temp@macro=\readyt@quit
+ \else \let\temp@macro=\moret@get %
+ \fi %
+ \temp@macro }%
+ \catcode`\ =13\relax\get@phys@line%
+}%
+%
+%
+\def\endlist{\catcode`\^^M=13%
+\catcode`\ =10\let^^M=\par\catcode`\^^M=5}%
+\def\beginlist[#1][#2][#3][#4][#5][#6]{%
+ \name@endtoks={\endlist}\true@endtoks={\endlist}%
+ \begin@list[#1][#2][#3][#4][#5][#6]}%
+%
+\catcode`\^^M=5\relax%
+%
+%
+% BEGINRAWLIST -- ENDRAWLIST \beginrawlist [...]{endtoken}
+% defaults for [..] supported, last {..} compulsory ({} allowed though)
+%
+% \beginrawlist [<INICOUNT>][<STEP>][<DIGITS>][<FONT>]%
+% [<TEXTSHIFT>][<MARKINGSHIFT>]{<ENDMARK>}
+% <INICOUNT>=\linecount: starts with where it is left
+% <ENDMARK>= empty: \endrawlist ends the rawlist, otherwise
+% <ENDMARK> ends it
+% <DIGITS>=0: no line numbering
+% Use \leftskip and \rightskip to control the wrapped positions
+%
+\def\endrawlist{\endgroup}%
+\def\begin@@rawlist[#1][#2][#3][#4][#5][#6]#7{\begingroup
+ \def\temp@macro{#7}% #7=token to end the list
+ \ifx\temp@macro\empty
+ \name@endtoks=\expandafter{\esc@ endrawlist}%
+ \else \name@endtoks={#7}%
+ \fi
+ \true@endtoks={\endlist\endrawlist}%
+ \rm@ligature\set@tab\set@cr\set@space
+ \raw@chars[11][13][13][13][13]%
+ \begin@list[#1][#2][#3][#4][#5][#6]}%
+%
+\def\begin@rawlist[#1][#2][#3][#4][#5][#6]#{%
+ \begin@@rawlist[#1][#2][#3][#4][#5][#6]}%
+%
+\def\beginrawlist{\push{%
+ \edef\next@@{\noexpand\begin@rawlist
+ [\the\p@r@one][\the\p@r@two][\the\p@r@three][\the\p@r@four]%
+ [\the\p@r@five][\the\p@r@six]}%
+ \popnil\clrp@r@s\next@@}% end of push
+ \font\tiny@rm=cmr5%
+ \edef\temp@macro{%
+ \noexpand\left@\the\linecount\noexpand\right@
+ \noexpand\left@1\noexpand\right@
+ \noexpand\left@0\noexpand\right@
+ \noexpand\left@\noexpand\tiny@rm\noexpand\right@
+ \noexpand\left@0pt\noexpand\right@
+ \noexpand\left@0pt\noexpand\right@}%
+ \expandafter\st@ckparas\temp@macro\p@r@end}%
+%
+%
+%
+% PRINTFILE verbatim \printfile [...]{filename}
+% [...] same as \beginrawlist
+%
+\catcode`\^^M=13\relax %
+\def\print@@file[#1][#2][#3][#4][#5][#6]#7{%
+ \temp@toks={\bgroup\print@filetrue %
+ \beginrawlist[#1][#2][#3][#4][#5][#6]{}}%
+ \existfile{#7}%
+ \iftemp@if %
+ \edef\temp@macro##1{\the\temp@toks %
+ \noexpand\input##1\leavevmode %
+ \setbox\temp@box=\lastbox\esc@ endrawlist^^M%
+ \global\advance\linecount-1\relax\egroup\vskip-\baselineskip}%
+ \else \def\temp@macro##1{\message{(File #7 not found)}}%
+ \fi %
+ \temp@macro{#7}}%
+\catcode`\^^M=5\relax %
+%
+\def\print@file[#1][#2][#3][#4][#5][#6]#{%
+ \print@@file[#1][#2][#3][#4][#5][#6]}%
+%
+\def\printfile{\push{%
+ \edef\next@@{\noexpand\print@file
+ [\the\p@r@one][\the\p@r@two][\the\p@r@three][\the\p@r@four]%
+ [\the\p@r@five][\the\p@r@six]}%
+ \popnil\clrp@r@s\next@@}% end of push
+ \font\tiny@rm=cmr5%
+ \edef\temp@macro{%
+ \noexpand\left@\the\linecount\noexpand\right@
+ \noexpand\left@1\noexpand\right@
+ \noexpand\left@6\noexpand\right@
+ \noexpand\left@\noexpand\tiny@rm\noexpand\right@
+ \noexpand\left@0pt\noexpand\right@
+ \noexpand\left@-10pt\noexpand\right@}%
+ \expandafter\st@ckparas\temp@macro\p@r@end}%
+%
+%
+% COMMENT OUT TEXT
+% \begincomment{password} <text> \endcomment or password
+%
+\catcode`\^^M=13%
+\def\begin@@comment{\let\par\relax %
+ \catcode`\^^M=13\message{< Skip}%
+ \temp@count=0\temp@@count=0\relax%
+ \long\def\get@phys@line##1^^M{%
+ \ifnum\temp@@count<500\advance\temp@@count1\else %
+ \message{\the\temp@count}\temp@@count=1\fi\relax %
+ \global\advance\temp@count1\relax %
+ \test@tokstr{\the\name@endtoks}{##1}%
+ \iftemp@if %
+ \def\temp@macro{\message{\the\temp@count\space lines}%
+ \expandafter\is@emptyline\expandafter{\second@half}%
+ \iftemp@if\message{>}\else %
+ \message{<!> >}%
+ \wlog{(Ignored: \second@half)}%
+ \fi \the\true@endtoks }%
+ \else \let\temp@macro=\get@phys@line %
+ \fi \temp@macro }%
+ \catcode`\ =13\relax\get@phys@line}%
+%
+\def\end@comment{\catcode`\^^M=13\catcode`\ =10\def^^M{\par}\catcode`\^^M=5}%
+\catcode`\^^M=5\relax%
+%
+\def\endcomment{\endgroup}% \read@buffline\temp@macro
+\def\begin@comment#1{\begingroup\nullfont
+ \tolerance=10000 \hbadness=10000 \vbadness=10000
+ \hfuzz=\maxdimen \vfuzz=\maxdimen
+ \def\temp@macro{#1}% #1=token to end the list
+ \ifx\temp@macro\empty
+ \name@endtoks=\expandafter{\esc@ endcomment}%
+ \else \name@endtoks={#1}%
+ \fi \true@endtoks={\end@comment\endcomment}%
+ \rm@ligature\set@tab\set@cr\set@space\def\ { }%
+ \raw@chars[11][11][11][13][13]\begin@@comment}%
+%
+\def\begincomment#{\begin@comment}% essentially an \outer macro
+%
+% SAVE CATCODES
+%
+\def\toks@of@catcodes#1#2[#3]{{% #3=/13/221/233/ must be increasing,or empty
+% return: global \temp@toks=0/0/0/
+% or /startnum/totalnum/catcode/ ... /0/0/0/
+ \def\get@triplet/##1/##2\ZZ{\temp@@@count=##1\relax
+ \def\temp@macro{##2}\ifx\temp@macro\empty\else\def\temp@macro{/##2}\fi}%
+ \def\temp@macro{#3}\def\temp@@macro{}\temp@count=#1\relax
+ \loop \temp@@count=#2\relax \temp@@@count=\temp@@count\relax
+ \ifx\temp@macro\empty \temp@iffalse\else
+ \expandafter\get@triplet\temp@macro\ZZ % \ZZ is not defined
+ \ifnum\temp@@@count>#2 \else
+ \temp@@count=\temp@@@count \advance\temp@@count-1\relax \fi\fi
+ \edef\temp@@@macro{\noexpand\str@@catcodes
+ {\the\temp@count}{\the\temp@@count}}\temp@@@macro
+ \temp@@toks=\expandafter{\temp@@macro}%
+ \edef\temp@@macro{\the\temp@@toks\the\temp@toks}%
+ \ifnum\temp@@@count>\temp@@count \temp@count\temp@@@count
+ \else\temp@count\temp@@count \fi \advance\temp@count1\relax
+ \ifnum\temp@count>#2 \temp@iffalse \else \temp@iftrue\fi
+ \iftemp@if \repeat \global\temp@toks=\expandafter{\temp@@macro0/0/0/}}}%
+%
+\def\str@@catcodes#1#2{\ifnum#1>#2 \global\temp@toks={}\else
+ {\temp@@@count#1\relax \global\temp@toks={}% result in \temp@toks
+ \loop \temp@count=0\temp@@count=\the\catcode\temp@@@count\relax
+ \l@@p \advance\temp@count1\advance\temp@@@count1\relax
+ \ifnum\temp@@@count>#2\relax\temp@iffalse\else\temp@iftrue\fi
+ \iftemp@if\ifnum\the\catcode\temp@@@count=\temp@@count
+ \else\temp@iffalse\fi\fi
+ \iftemp@if\repe@t
+ \temp@@count=\temp@@@count \advance\temp@@count-\temp@count\relax
+ \edef\temp@macro{\the\temp@toks
+ \the\temp@@count/\the\temp@count/\the\catcode\temp@@count/}%
+ \global\temp@toks=\expandafter{\temp@macro}%
+ \ifnum\temp@@@count>#2\relax\temp@iffalse\else\temp@iftrue\fi
+ \iftemp@if \repeat }\fi}%
+%
+\def\act@catcodes#1/#2/#3/{% activate catcodes, must be ended by /0/0/0/
+ \temp@count=#2\relax
+ \ifnum\temp@count>0 \let\temp@macro\act@catcodes\temp@@iftrue
+ \else \let\temp@macro\relax\temp@@iffalse\fi
+ \temp@count=0 \temp@@count=#1\relax
+ \iftemp@@if\else\temp@count=#2\relax\fi
+ \l@@p
+ \iftemp@@if
+ \temp@@@count=\the\catcode\temp@@count \relax
+ \ifnum\temp@@@count=#3\relax\else
+ \catcode\the\temp@@count=#3\relax\fi
+ \advance\temp@count1 \advance\temp@@count1\relax
+ \fi
+ \ifnum\temp@count<#2 \repe@t \temp@macro}%
+%
+%
+\def\is@rawmode#1/#2/#3/{% chk if catcode is 11 or 12,
+ % exceptions must be ended by /0/0/0/
+ \temp@iftrue\temp@count=#2\relax
+ \ifnum\temp@count>0 \let\temp@macro\act@catcodes\temp@@iftrue
+ \else \let\temp@macro\relax\temp@@iffalse\fi
+ \temp@count=0 \temp@@count=#1\relax
+ \iftemp@@if\else\temp@count=#2\relax\fi
+ \l@@p
+ \iftemp@@if
+ \temp@@@count=\the\catcode\temp@@count \relax
+ \ifnum\temp@@@count=#3\relax\else
+ \ifnum\temp@@@count=11\relax\else
+ \ifnum\temp@@@count=12\relax\else
+ \temp@iffalse \fi\fi\fi
+ \advance\temp@count1 \advance\temp@@count1\relax
+ \fi
+ \ifnum\temp@count<#2 \repe@t\temp@macro}%
+%
+%
+% #1=name, #2=1st char, #3=last char, #4=exceptions
+\def\save@catcodes[#1][#2][#3][#4]{\toks@of@catcodes{#2}{#3}[#4]%
+ \expandafter\xdef\csname CAT@#1@CODES\endcsname{\the\temp@toks}}%
+%
+\def\get@catcodes[#1]{%
+ \expandafter\let\expandafter\temp@macro\csname CAT@#1@CODES\endcsname
+ \expandafter\act@catcodes\temp@macro}%
+%
+% SAVE STATUS
+%
+\def\save@status{\edef\temp@macro{% status to \temp@macro
+ \noexpand\pagegoal=\the\pagegoal
+ \noexpand\hsize=\the\hsize
+ \noexpand\vsize=\the\vsize
+ \noexpand\hyphenpenalty=\the\hyphenpenalty
+ \noexpand\overfullrule=\the\overfullrule
+ \noexpand\pretolerance=\the\pretolerance
+ \noexpand\tolerance=\the\tolerance
+ \noexpand\hbadness=\the\hbadness
+ \noexpand\vbadness=\the\vbadness
+ \noexpand\hfuzz=\the\hfuzz
+ \noexpand\vfuzz=\the\vfuzz
+ \noexpand\spaceskip=\the\spaceskip
+ \noexpand\xspaceskip=\the\xspaceskip
+ \noexpand\looseness=\the\looseness
+ \noexpand\parfillskip=\the\parfillskip }}%
+%
+%
+% MULTI-COLUMNS
+%
+\newif\ifwarn@me \newbox\partial@page
+\newtoks \old@output@toks
+%\newtoks\new@footline
+% replacing \footline for a TeX bug if footline is lost
+%
+% makeshift remedy for LaTeX
+% One must define \makefootline etc for realistic export to general LaTeX
+\ifx\makeheadline\undefined@ \let\makeheadline\relax\fi
+\ifx\makefootline\undefined@ \def\makefootline{}\fi
+\ifx\advancepageno\undefined@\def\advancepageno{\global\advance\count0 1}\fi
+%
+\def\make@headline{{\hsize=\page@width \makeheadline}}%
+\def\make@footline{{\hsize=\page@width \makefootline}}%
+\def\simple@pageout#1{\shipout\vbox{\make@headline
+ \vbox to\page@height{#1}\make@footline}\advancepageno}%
+%
+\def\page@sofar[#1]{\unvbox\partial@page \temp@count=0 %
+ \loop\ifnum\temp@count<#1 \wd\temp@count=\hsize\advance\temp@count1 \repeat
+ \temp@count=1 \hbox to\page@width{\box0 %
+ \loop\ifnum\temp@count<#1 \hfil\box\temp@count
+ \advance\temp@count by1 \repeat}\temp@count=0 %
+ \ifx\topins\undefined@\else\ifvoid\topins\else\temp@count=1 \fi\fi
+ \ifx\footins\undefined@\else\ifvoid\footins\else\temp@count=1 \fi\fi
+ \ifwarn@me \ifnum\temp@count=1 \message{<!>}%
+ \wlog{Insertions (e.g. footnotes) may be pushed to later pages.
+ Try manual pagebreak to overcome possible overfull vbox due to
+ insertions. I pray for you.}\global\warn@mefalse \fi\fi}%
+%
+\def\columns@out[#1]{\splittopskip=\topskip\splitmaxdepth=\maxdepth
+ \temp@dim=\page@height \advance\temp@dim by -\ht\partial@page
+ \temp@count=0 \loop\ifnum\temp@count<#1
+ \ifdim\temp@dim>0pt
+ \setbox\temp@count=\vsplit255 to\temp@dim
+ \else \setbox\temp@count=\vbox{}\fi
+ \advance\temp@count by1 \repeat
+ \simple@pageout{\page@sofar[#1]}\unvbox255\penalty\outputpenalty}%
+%
+\def\balance@columns[#1]{\setbox\temp@box=\vbox{\unvbox255}%
+%% For materials more than one page but less than two pages
+ \temp@@dim=\ht\partial@page \temp@dim=\ht\temp@box
+ \divide\temp@dim by \column@num
+ \advance\temp@dim by \temp@@dim \advance\temp@dim by \dp\temp@box
+ \ifdim\temp@dim>\page@height \message{(!)}%
+ \temp@@@dim=\temp@@dim \advance\temp@@@dim by -\page@height
+ \advance\temp@@@dim by \baselineskip
+ \ifdim\temp@@@dim>0pt \message{<!>}%
+ \wlog{Space left in previous page too narrow.}\else
+ {\vbadness=10000 \vfuzz=\maxdimen
+ \predisplaypenalty 0 \postdisplaypenalty 0 %
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ \temp@dim=\page@height \advance\temp@dim by -\temp@@dim
+ \advance\temp@dim by \maxdepth
+ \temp@count=0 \loop \ifnum\temp@count<#1 %
+ \setbox\temp@count=\vsplit\temp@box to\temp@dim
+ \advance\temp@count by1 \repeat
+ \global\setbox\temp@box\box\temp@box
+ \simple@pageout{\page@sofar[#1]}}\fi\fi
+% push the rest into the next page
+ \temp@dim=\ht\temp@box \advance\temp@dim by\topskip
+ \advance\temp@dim by -\baselineskip
+ \divide\temp@dim by #1 \splittopskip=\topskip
+ {\vbadness=10000 \vfuzz=\maxdimen \splitmaxdepth=\maxdepth
+ \loop \setbox\temp@@box=\copy\temp@box
+ \temp@count=1 \l@@p \ifnum\temp@count<#1 %
+ \setbox\temp@count=\vsplit\temp@@box to\temp@dim
+ \advance\temp@count by1 \repe@t
+ \ifdim\ht\temp@@box>\temp@dim \advance\temp@dim by1pt \repeat
+ \temp@count=1 \temp@@count=0
+ \loop \ifnum\temp@count<#1 %
+ \setbox\temp@@count=\vbox to\temp@dim{\unvbox\temp@count}%
+ \advance\temp@count by1 \advance\temp@@count by1 \repeat
+ \temp@count=#1 \advance\temp@count by-1 %
+ \setbox\temp@count=\vbox to \temp@dim{\unvbox\temp@@box}\page@sofar[#1]}%
+ \global\setbox\temp@box=\null\global\setbox\temp@@box=\null}%
+%
+\def\begincolumns{\push{%
+ \edef\next@@{\noexpand\begin@columns[\the\p@r@one][\the\p@r@two]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas\left@2\right@\left@10pt\right@\p@r@end}%
+%
+\def\begin@columns[#1][#2]{% #1 will be expanded via \edef
+ \save@status \old@output@toks=\expandafter{\the\output}%
+ \let\old@entry@status\temp@macro %\begingroup
+ \edef\column@num{#1}\warn@metrue
+ \temp@@count=0 \temp@count=\column@num \relax
+ \ifnum\temp@count>9 \temp@@count=1 \fi
+ \ifnum\temp@count<1 \temp@@count=1 \fi
+ \ifnum\temp@@count>0 %
+ \errhelp{I think a format other than 1-9 columns in a page is crazy.
+ But if you do have such devious wishes, I can only keep my
+ fingers crossed for you.}%
+ \errmessage{Column number \column@num\space is too ambitious!}\fi
+ \ifISLATEX\edef\page@width{\the\textwidth}\edef\page@height{\the\textheight}%
+ \else \edef\page@width{\the\hsize}\edef\page@height{\the\vsize}\fi
+ \tolerance=10000 \hbadness=10000 \vbadness=10000
+ \hfuzz=\maxdimen \vfuzz=\maxdimen \overfullrule=0pt
+ \par\penalty-1 %avoid page loss near the page break margin
+ \message{(\column@num\space cols|#2)}%
+ \output={\global\setbox\partial@page=\vbox{\unvbox255\bigskip}}\eject
+ \output={\columns@out[\column@num]}%
+ \divide\hsize by \column@num \temp@dim=#2
+ \ifnum \temp@dim<0 \message{Intercolumn skip [#2] insensible, reset to 0pt.}%
+ \else \advance\hsize by -#2 \fi\multiply\vsize by \column@num
+ \advance\vsize by 1pc}%
+%
+\def\endcolumns{%
+ \hbox{}\output={\balance@columns[\column@num]}\eject%\endgroup
+ \old@entry@status \output=\expandafter{\the\old@output@toks}%
+ \global\setbox\partial@page=\null}% \pagegoal=\vsize
+%
+% SMOOTH PASSAGES FOR MULTICOLUMNS
+%
+\def\smooth{\spaceskip=0.3em plus .8em minus .1em
+ \xspaceskip=0.6pt plus 1em minus .2em
+ \pretolerance=10 \tolerance=10000 \looseness=-10000
+ \parfillskip=0pt plus10fill\relax}%
+%
+% MAKE LABELS
+% \beginlabels[#1][#2][#3][#4][#5][#6]
+% defaults: #1=15pt #2=\sl #3=1 #4=1 #5=2.6in #6=2em
+% \endlabels
+%
+\def\begin@labels[#1][#2][#3][#4][#5][#6]{%
+ \ifISLATEX \temp@dim=\textwidth \else\temp@dim=\hsize\fi
+ \temp@@dim=#1 \advance\temp@@dim #5 \def\label@size{#5}%
+ \advance\temp@@dim\temp@@dim \advance\temp@@dim10pt
+ \ifdim\temp@@dim<\temp@dim \temp@count=2
+ \else \temp@count=1 \temp@dim=0pt \fi\relax
+ \edef\temp@macro{\noexpand\begincolumns[\the\temp@count][10pt]}%
+ \temp@macro %\nullfont
+ \long\def\peudo@letter##1\endletter{%
+ \def\lettercontents{\begingroup \hbadness=10000 \vbadness=10000
+ \hfuzz=\maxdimen \vfuzz=\maxdimen \overfullrule=0pt
+ \vbox{#2 \par\vskip\baselineskip
+ \vskip#1\addressparas[#3][#4][#5][#6]\vskip#1
+ \hbox{\font\tiny@rm=cmr5 \tiny@rm
+ \leaders\hbox to .8em{\hss.\hss}\hskip\label@size}\par}%
+ \endgroup}}%
+ \let\beginletter\peudo@letter\beginletter\endletter}%
+%
+\def\beginlabels{\push{%
+ \edef\next@@{\noexpand\begin@labels[\the\p@r@one][\the\p@r@two]%
+ [\the\p@r@three][\the\p@r@four][\the\p@r@five][\the\p@r@six]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas
+ \left@ 20pt\right@ \left@ \tt\raggedright\right@
+ \left@ 1\right@ \left@ 1\right@
+ \left@ 2.6in\right@ \left@ 2em\right@ \p@r@end}%
+%
+\def\endlabels{\endcolumns\let\beginletter\true@letter}%
+%
+%
+% LABELS: make labels via a 2nd read of file
+%
+\long\def\firstread#1{% nil if read after \labelsquit
+ \ifx\ENDINPUT\undefined\def\temp@macro{#1}\else\def\temp@macro{}\fi
+ \temp@macro}%
+%
+%
+\def\initstyle{\push{%
+ \edef\next@@{\noexpand\init@labels[\the\p@r@one]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas\left@\right@\p@r@end}%
+\let\initlabels\initstyle % for compatibility with version 2.03
+%
+\long\def\init@labels[#1]#{\init@@labels[#1]}%
+\long\def\init@@labels[#1]#2#{\init@@@labels[#1]#2}%
+\long\def\init@@@labels[#1]#2#3{\def\labels@initiated{}\let\next\relax
+ \ifISLATEX \ifx\ENDINPUT\undefined@ \def\temp@macro{#2}%
+ \ifx\temp@macro\empty\temp@toks={article}\else\temp@toks={#2}\fi
+ \temp@@toks={#3}\edef\temp@@macro{\noexpand\documentstyle
+ [#1]{\the\temp@toks}\the\temp@@toks\noexpand\begin{document}}%
+ \else\def\temp@@macro{}\fi
+ \else \def\temp@@macro{}\message{<!>}%
+ \wlog{(\string\initstyle\space ignored for plain TeX)}\fi
+ \temp@@macro}%
+%
+%
+\def\initclass{\push{%
+ \edef\next@@{\noexpand\init@class[\the\p@r@one][\the\p@r@two]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas\left@\right@\left@\right@\p@r@end}%
+%
+\long\def\init@class[#1][#2]#{\init@@class[#1][#2]}%
+\long\def\init@@class[#1][#2]#3#{\init@@@class[#1][#2]#3}%
+\long\def\init@@@class[#1][#2]#3#4{\def\labels@initiated{}\let\next\relax
+ \ifISLATEX \ifx\ENDINPUT\undefined@ \def\temp@macro{#3}%
+ \ifx\temp@macro\empty\temp@toks={article}\else\temp@toks={#3}\fi
+ \temp@@toks={#4}\edef\temp@@macro{\noexpand\documentstyle
+ [#1]{\the\temp@toks}\the\temp@@toks\noexpand\begin{document}}%
+ \ifx\documentclass\undefined@\else
+ \edef\temp@@macro{\noexpand\documentclass[#2]{\the\temp@toks}%
+ \noexpand\read@style[,]{#1}\the\temp@@toks
+ \noexpand\begin{document}}%
+ \fi
+ \else\def\temp@@macro{}\fi
+ \else \def\temp@@macro{}\message{<!>}%
+ \wlog{(\string\initclass\space ignored for plain TeX)}\fi
+ \temp@@macro}%
+%
+\def\readstyles#1{\xdef\EntryReadStyle{\the\catcode`\@}\catcode`\@=11\relax
+ \read@style[,]{#1}\catcode`\@=\EntryReadStyle\relax}%
+%
+\def\read@style[#1]#2{\def\one@item##1#1##2\safty@mark{\temp@toks={##1}%
+ \expandafter\input@a@style\the\temp@toks..\safty@mark\def\temp@macro{##2}%
+ \ifx\temp@macro\empty\else\def\temp@macro{\one@item##2\safty@mark}\fi
+ \temp@macro}\one@item#2#1\safty@mark }%
+\def\input@a@style#1.#2.#3\safty@mark{\def\temp@macro{#2}%
+ \ifx\temp@macro\empty\def\temp@macro{sty}\fi\def\temp@@macro{#1.}%
+ \temp@toks=\expandafter\expandafter\expandafter
+ {\expandafter\temp@@macro\temp@macro}\def\temp@@macro{#1}%
+ \ifx\temp@@macro\empty\else\ifx\temp@@macro\space\else
+ \expandafter\inputfile\expandafter{\the\temp@toks}\fi\fi }%
+%
+%
+\def\labelsquit{\push{%
+ \edef\next@@{\noexpand\labels@quit[\the\p@r@one][\the\p@r@two]%
+ [\the\p@r@three][\the\p@r@four][\the\p@r@five][\the\p@r@six]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas
+ \left@ 20pt\right@ \left@ \tt\raggedright\right@
+ \left@ 1\right@ \left@ 1\right@
+ \left@ 2.6in\right@ \left@ 2em\right@ \p@r@end}%
+%
+\def\labels@quit[#1][#2][#3][#4][#5][#6]#{%
+ \labels@@quit[#1][#2][#3][#4][#5][#6]}%
+\def\labels@@quit[#1][#2][#3][#4][#5][#6]#7{%
+ \ifISLATEX \else\def\labels@initiated{}\fi
+ \ifx\labels@initiated\undefined
+ \message{<!>}\wlog{(\string\initstyle\space must be activated first)}%
+ \let\next\relax
+ \else \def\temp@macro{#7}%
+ \ifx\temp@macro\empty\def\temp@macro{\jobname}\fi
+ \ifx\ENDINPUT\undefined
+ \temp@toks={[#1][#2][#3][#4][#5][#6]}%
+ \message{(Re-read \jobname.tex)}%
+ \edef\next{\noexpand\beginlabels
+ \the\temp@toks\noexpand\input \temp@macro}%
+ \else \def\next{\endlabels\end{document}}\fi
+ \let\ENDINPUT\relax
+ \fi \next}%
+%
+%
+% WRITE FILE
+%
+\catcode`\^^M=13\relax %
+%
+% \temp@read, \name@endtoks and \true\end@toks must be given on entry
+\long\def\file@chkline#1^^M{\test@tokstr{\the\name@endtoks}{#1}%
+ \iftemp@if \temp@toks=\expandafter{\first@half}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if\else \expandafter %
+ \immediate\write\expandafter\temp@read\expandafter{\first@half}\fi %
+ \immediate\closeout\temp@read \temp@toks=\expandafter{\second@half}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if \else\message{<!>}\wlog{(Ignored: \the\temp@toks)}\fi %
+ \edef\buffer@{\the\true@endtoks}%
+ \else \expandafter\immediate\expandafter %
+ \write\expandafter\temp@read\expandafter{\first@half}%
+ \let\buffer@\file@chkline %
+ \fi \buffer@ }%
+%
+\def\beginfile{\push{%
+ \edef\next@@{\noexpand\begin@file[\the\p@r@one]}%
+ \popnil\next@@}\st@ckparas\left@\right@\p@r@end}%
+%
+\def\begin@file[#1]#{\begin@@file[#1]}%
+\def\begin@@file[#1]#2{\save@catcodes[RAW][0][\MAX@CHR@CODE][]%
+% #1=token to end the list, #2=filename
+ \edef\temp@macro{#2}%
+ \ifx\temp@macro\empty \def\temp@macro{scr@tch@.tex}\fi %
+ \wlog{(File <\temp@macro> written)}%
+ \immediate\openout\temp@read=\temp@macro \def\temp@macro{#1}%
+ \ifx\temp@macro\empty \temp@toks=\expandafter{\esc@}%
+ \name@endtoks=\expandafter{\the\temp@toks endfile}%
+ \else \name@endtoks={#1}\fi\true@endtoks={\endlinemode\endrawlinemode}%
+ \rm@ligature\set@space\set@tab\raw@chars[11][11][11][13][13]\let\ =\space %
+ \def\temp@macro##1^^M{%
+ \test@tokstr{\the\name@endtoks}{##1}%
+ \iftemp@if\else \temp@toks={##1}%
+ \expandafter\is@emptyline\expandafter{\the\temp@toks}%
+ \iftemp@if\else \expandafter\immediate\expandafter %
+ \write\expandafter\temp@read\expandafter{\the\temp@toks}\fi %
+ \fi %
+ \test@tokstr{\the\name@endtoks}{##1}%
+ \iftemp@if \temp@toks=\expandafter{\first@half}%
+ \temp@@toks=\expandafter{\second@half}%
+ \edef\temp@@macro{\noexpand\file@chkline %
+ \the\temp@toks\the\name@endtoks\the\temp@@toks\noexpand^^M}%
+ \else\def\temp@@macro{\file@chkline}\fi\temp@@macro }%
+ \temp@macro }%
+%
+\catcode`\^^M=5\relax%
+%
+%
+% FONTS
+%
+%\font\BOLD=cmbx10 at 24.88pt \font\hbold=cmbx10 at 20.74pt
+%\font\lbold=cmbx10 at 17.28pt \font\bbold=cmbx10 at 14.4pt
+%\font\bold=cmbx10 at 12pt \font\sbold=cmbx8
+%\font\tbold=cmbx5 \font\ssan=cmss8
+%\font\SAN=cmss10 at 24.88pt \font\hsan=cmss10 at 20.74pt
+%\font\lsan=cmss10 at 17.28pt \font\bsan=cmss10 at 14.4pt
+%\font\san=cmss10 at 12pt \font\nsan=cmss10
+%\font\ROMAN=cmr10 at 24.88pt \font\hroman=cmr10 at 20.74pt
+%\font\lroman=cmr10 at 17.28pt \font\broman=cmr10 at 14.4pt
+%\font\roman=cmr10 at 12pt \font\sroman=cmr8
+%\font\troman=cmr5 \font\stt=cmtt8
+%
+%
+% LEAVE MACROS
+%
+\let\wlog\temp@@@macro\let\temp@@@macro\undefined@
+%
+\catcode`\@=\EntryFormLett\relax
+\endinput
+%
+%ENDMACROS
diff --git a/macros/generic/formlett/prog_manual.pdf b/macros/generic/formlett/prog_manual.pdf
new file mode 100644
index 0000000000..091e0c2142
--- /dev/null
+++ b/macros/generic/formlett/prog_manual.pdf
Binary files differ
diff --git a/macros/generic/formlett/prog_manual.tex b/macros/generic/formlett/prog_manual.tex
new file mode 100644
index 0000000000..3cf57fc993
--- /dev/null
+++ b/macros/generic/formlett/prog_manual.tex
@@ -0,0 +1,1906 @@
+% PROGRAMMER'S MANUAL in Plain TeX
+
+\input formlett.sty
+
+% FONTS
+\font\hbold=cmbx10 at 17.28pt
+\font\lbold=cmbx10 at 14.4pt
+\font\bbold=cmbx10 at 12pt
+\font\small=cmr8
+\font\tiny=cmr5
+\font\stt=cmtt9
+\catcode`\@=11\relax
+%
+%
+%
+% OTHER MACROS
+%
+\catcode`\~=11\relax \def\t{{\tt ~}}
+\catcode`\~=\active\relax
+\catcode`\!=0\relax !catcode`!\=11!relax
+!def!esc{\}!def!escs{\! }
+!catcode`!\=0!relax \catcode`\!=12\relax
+\def\rqs{\rq\ }
+\def\LaTeX{{\rm L\kern-.36em\raise.3ex\hbox{\font\sc=cmcsc10\sc a}\kern-.15em
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
+
+% makeshift macro
+\catcode`\^^M=13\relax%
+\def\setraw{\bgroup\rm@ligature\set@space\set@tab%
+\set@cr\stt\raw@chars[11][13][13][13][13]\def^^M{\strut\par}\setraw@@}%
+\edef\temp@macro{%
+ \noexpand\long\noexpand\def\noexpand\setraw@@\noexpand##1^^M##2%
+ \esc@ unsetraw{##1##2\noexpand\egroup}}\temp@macro %
+\catcode`\^^M=5\relax%
+
+
+\font\ninerm=cmr9 \font\eightrm=cmr8
+\font\ninei=cmmi9 \font\eighti=cmmi8
+\font\ninesy=cmsy9 \font\eightsy=cmsy8
+\font\ninebf=cmbx9 \font\eightbf=cmbx8
+\font\ninett=cmtt9 \font\eighttt=cmtt8
+\font\nineit=cmti9 \font\eightit=cmti8
+\font\ninesl=cmsl9 \font\eightsl=cmsl8
+
+\font\sixrm=cmr6
+\font\sixi=cmmi6
+\font\sixsy=cmsy6
+\font\sixbf=cmbx6
+
+\skewchar\ninei='177 \skewchar\eighti='177 \skewchar\sixi='177
+\skewchar\ninesy='60 \skewchar\eightsy='60 \skewchar\sixsy='60
+\hyphenchar\ninett=-1 \hyphenchar\eighttt=-1 \hyphenchar\tentt=-1
+
+\font\tentex=cmtex10
+\font\inchhigh=cminch
+\font\titlefont=cmssdc10 at 40pt % titles in chapter openings
+\font\eightss=cmssq8 % quotations in chapter closings
+\font\eightssi=cmssqi8 % ditto, slanted
+\font\tenu=cmu10 % unslanted te~t italic
+\font\manual=manfnt % METAFONT logo and special symbols
+\font\magnifiedfiverm=cmr5 at 10pt % to demonstrate magnification
+
+\newskip\ttglue
+\def\eightpoint{\def\rm{\fam0\eightrm}% switch to 8-point type
+ \textfont0=\eightrm \scriptfont0=\sixrm \scriptscriptfont0=\fiverm
+ \textfont1=\eighti \scriptfont1=\sixi \scriptscriptfont1=\fivei
+ \textfont2=\eightsy \scriptfont2=\sixsy \scriptscriptfont2=\fivesy
+ \textfont3=\tenex \scriptfont3=\tenex \scriptscriptfont3=\tenex
+ \textfont\itfam=\eightit \def\it{\fam\itfam\eightit}%
+ \textfont\slfam=\eightsl \def\sl{\fam\slfam\eightsl}%
+ \textfont\ttfam=\eighttt \def\tt{\fam\ttfam\eighttt}%
+ \textfont\bffam=\eightbf \scriptfont\bffam=\sixbf
+ \scriptscriptfont\bffam=\fivebf \def\bf{\fam\bffam\eightbf}%,
+ \tt \ttglue=.5em plus.25em minus.15em
+ \normalbaselineskip=9pt
+ \setbox\strutbox=\hbox{\vrule height7pt depth2pt width0pt}%
+ \let\sc=\sixrm \let\big=\eightbig \normalbaselines\rm}
+
+
+%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%
+%
+% END OF EXTRA MACROS AND FONTS
+%
+%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%
+
+
+
+\message{<<document for programmers>>}
+\catcode`\@=11\relax
+\PAGENO=1
+\voffset=-0.3in
+
+
+\ifx\pageno\undefined
+\errmessage{Please run TeX if you want this article on how to use
+<formlett.sty> to be processed as well!}
+\fi
+
+
+\parindent=0pt
+\hsize=469.75499pt % the default
+\vsize=9.6in %8.83in
+%\vsize=8.83in
+
+\def\makefootline{\baselineskip=24pt \line{\the\footline}}
+\footline={\lower5pt
+\hbox to \hsize
+ {{\tenrm Jiang Z ~~~{\tensl Formlett: ~for letters to multiple receivers}
+\hss \folio}}}
+
+\leftline{\hbold FORMLETT: ~~~for Letters to Multiple Receivers}
+\bigskip
+
+
+{\advance\leftskip by13mm \overfullrule=0pt
+\advance\rightskip by 20mm %28mm
+\sl
+\noindent Zhuhan JIANG\par
+\noindent School of Computing and Information Technology,
+ University of Western Sydney, Victoria Road, Parramatta NSW 2150, Australia.
+{\sl ~~Email}:~z.jiang@uws.edu.au\par
+\medskip
+\rm\smooth
+\noindent (Last updated on 26 May 2003)\par
+\medskip
+
+\noindent
+In this article, the author explains how to use a form-letter
+style {\tt formlett.sty}, designed for plain \TeX\ and \LaTeX
+\ or \LaTeX2e. {\tt formlett.sty} supports different parameter input
+methods, parameter naming and defaulting mechanism, as well as
+facilities for previewing parameter positions and printing
+labels. It is written for the purpose of being powerful, robust
+and above all easy to use.\par }
+
+
+\begincolumns
+
+{\lbold Introduction}
+
+\smallskip
+
+In this modern world of ours, we often need to send a set of form
+letters, personalised or non-personalised, to many receivers at
+the same time. Or perhaps we would like to have a collection of
+business letters or information brochures which we would like to
+call upon {\sl instantly} whenever we need them.
+
+\medskip
+
+Our purpose here is therefore to describe a comprehensive
+implementation of such a macro system, handling form letters
+under \TeX\ or \LaTeX. The main objective is to provide an easy
+way to output many form letters with their own parameters, with
+or without the use of multiple files. There will be a coherent
+and simple format for putting parameters inside a form letter,
+with a number of helping facilities for such as naming parameters
+and previewing their positions. A minimum support for printing
+mailing labels is also provided.
+
+
+\medskip
+
+The concept of macros [1] for form letters is not new: there
+already exist macros in this connection such as {\tt merge}, {\tt
+textmerg} and {\tt address} to name a few, see [2,3] for further
+details. Our stress here is therefore laid on the ease to use,
+along with the power and the robustness of the macros.
+
+\bigskip
+{\lbold Format}
+
+\smallskip
+
+In this section, we always assume that the file {\tt formlett.sty}
+or {\tt formlett.tex} of version {\tt 2.3} has
+already been input. Certain version of {\tt formlett.sty} can be
+obtained via anonymous ftp from CTAN sites at
+{\tt macros /generic}.
+
+\medskip
+
+Essentially, each form letter, or letter format or letter
+template, will be included between {\tt \string\beginletter} and
+{\tt \string\endletter}. Letter parameters that will be specified
+later on for each particular letter can be given by {\tt
+\string\paras[<m>][<n>]}, representing the {\tt <m>}-th parameter
+of the {\tt<n>}-the parameter group, at the positions you want
+them to be. Let a cluster denote a complete collection of
+parameters that may be specified for a form letter. Then we can
+specify letter parameters group by group for a cluster such that
+inside each group the parameters are given {\sl sequentially} and
+a termination of one group should not affect the
+resynchronisation for the next group. For instance we can keep
+the address of a receiver as a single group, as it often contains
+different number of (parameter) lines.
+
+
+\medskip
+We often want to treat a particular group of letter
+parameters somewhat uniformly. This can be achieved by one of the
+following commands
+
+\setraw
+ \blockparas[<m>][<n>][<pre>][<post>]
+ \addressparas[<m>][<n>][<width>][<indent>]
+\unsetraw
+
+They represent parameters in the {\tt<n>}-th group, from the {\tt
+<m>}-th to the last parameter of that group. For {\tt
+\string\blockparas}, tokens {\tt <pre>} and {\tt <post>} are
+those to be added in front and behind respectively each of the
+legitimate parameters mentioned above. If {\tt <post>} is
+{\tt\string\relax}, it will then not be appended at the end.
+Instead, each chosen parameter will be put into a {\tt $\{\}$}-
+pair before preceded by the token {\tt <pre>}. The reason for
+this exception is that while {\tt <pre> and <post>} are meant to
+be the front and end macros for each selected parameter, in the
+case of {\tt <post>} being {\tt \string\relax}, we may regard
+{\tt<pre>} as {\sl acting upon} each chosen parameter.
+
+
+\medskip
+The command {\tt \string\addressparas}, however, uses
+{\tt \string\blockparas} indirectly and will put the chosen
+parameters into a box of width {\tt<width>}. If any selected
+parameter is longer than {\tt<width>}, then the line will be
+wrapped around, with all wrapped potions being indented by an
+{\tt<indent>}. This may be used to deal with very long address
+lines. Incidentally, we may use {\tt \string\textbox} or {\tt
+\string\addressbox} or {\tt \string\ADDRESSBOX} to control the
+width of a single parameter. The general format reads
+
+
+\setraw
+ \textbox[<width]{<materials>}
+ \addressbox[<width>][<indent>]{<materials>}
+ \ADDRESSBOX{<width>}{<indent>}{<materials>}
+\unsetraw
+
+where the meaning of the macro parameters are self-explanatory.
+
+
+\medskip
+
+For the macro parameters, we have for convenience provided the
+following defaults for those in the squared brackets
+
+\setraw
+ <m>=1
+ <n>=1
+ <pre>=\noindent
+ <post>=\par
+ <width>= 8truecm
+ <indent>= 1.5em
+\unsetraw
+
+This way, for instance, {\tt\string\paras[1][1]} is equivalent
+to any of the following commands
+
+\setraw
+ \paras, \paras[1], \paras[][1],
+ \paras[1][], \paras[][]
+\unsetraw
+
+and the following three commands are also the same
+
+\setraw
+ \addressbox{one address line}
+ \addressbox[8truecm]{one address line}
+ \addressbox[][1.5em]{one address line}
+\unsetraw
+
+
+\medskip
+
+Incidentally this is the reason why we used the second parameter
+{\tt<n>} to represent the group number: the defaults can often be
+dropped off more frequently. By default, all letter parameters
+specified will be put into a group environment before putting
+them into the form letter, unless {\tt \string\localparasfalse}
+is issued beforehand.
+
+\medskip
+To output a new letter entity, i.e a complete letter,
+we may use
+
+
+\setraw
+ \moreletter
+ para-1-1;para-1-2;para-1-3; ...
+ +para-2-1;para-2-2;...
+ + ...
+ +para-n-1;para-n-2; ... ;para-n-m !
+\unsetraw
+
+
+where \lq{\tt ;}\rqs separate parameters inside a same group,
+\lq{\tt +}\rqs separates groups, \lq{\tt !}\rqs ends a cluster of
+parameters, and \lq{\tt ...}\rqs represent further letter
+parameters. These three tokens are nothing special: we may change
+them to for instance \lq{\tt ....}\rq, \lq{\tt ----}\rqs and
+\lq{\tt ====}\rqs respectively by {\tt \string\blockmarks}, and
+change them back to \lq{\tt ; + !}\rqs by {\tt
+\string\defaultmarks}. For more general case, use
+
+\setraw
+ \delimiters{<A>}{<B>}{<C>}
+\unsetraw
+
+where {\tt <A>}, {\tt <B>} and {\tt <C>} are the new toks
+replacing \lq{\tt ; + !}\rqs respectively. If we have to use
+these three special characters or tokens inside our {\sl letter
+parameters}, then use {\tt \string\pstr}, {\tt\string\gstr} and
+{\tt\string\cstr} respectively instead.
+
+\medskip
+
+For the case of many clusters, we may enclose them, separated by
+any white spaces or empty lines, between {\tt
+\string\beginpilemode} and {\tt \string\endpilemode} so that we
+don't have to put {\tt \string\moreletter} in front of each
+cluster of parameters.
+
+
+\medskip
+We may also enter letter parameters line by line. In other words,
+we may essentially replace \lq{\tt;}\rqs in the {\tt
+\string\moreletter} format by a normal line break. In this case,
+we shall put clusters of parameters between {\tt
+\string\beginblockmode} and {\tt \string\endblockmode}. Thus the
+following commands
+
+
+\setraw
+ \beginblockmode
+ <para-1-1>
+ <para-1-2>
+ + letter one
+
+ <para-2-2>
+ !
+
+ <addr-1-1>
+ <addr-1-2>
+ ! letter two
+ \endblockmode
+\unsetraw
+
+
+will produce the required form letter for each cluster of
+parameters. The general rules are as follows:
+
+{\parindent=1.5em
+\item{$\bullet$} If a line contains {\tt \string\endblockmode} or {\tt !}
+or {\tt +}, then everything else on that line is ignored and that
+line serves as an end/cluster/group marking line in the given
+priority order.
+
+\item{$\bullet$} Leading and trailing empty lines before or after
+a complete cluster will be ignored, unless \lq{\tt ;}\rqs is
+there to force the next (empty) line as a starting parameter.
+\par }
+
+Obviously {\tt \string\blockmarks} provides a more sensible
+delimiters for the {\tt blockmode}, under which we could have
+
+\setraw
+ \blockmarks\beginblockmode
+ ....... force next empty line active
+
+ <para-1-2>
+ ------- - mark end of 1st group
+
+ <para-2-2>
+ <para-2-3>
+ ======== end of cluster
+
+ <other clusters>
+ \endblockmode
+\unsetraw
+
+\medskip
+A simpler and perhaps more often encountered scenario is
+to use names and addresses only. In this case, there will be
+essentially only {\sl one} group of parameters for each cluster.
+Thus we may use empty lines to delimit the clusters, and use line
+by line mode for the individual parameters. This way, each
+block of consecutive nonempty lines in
+
+\setraw
+ \beginlinemode
+ <name-1>
+ <address-1-1>
+ <address-1-2>
+
+ <name-2>
+ <1st part of addr-2-1> %
+ <continued part of line addr-2-1>
+
+ <name-3> % letter three
+ \endlinemode
+\unsetraw
+
+
+will output a new complete letter, corresponding to the specified
+letter parameters.
+
+
+\medskip
+{\smooth
+Ideally, the name--address entries will be produced by a database
+utility. Since they often contain special characters such as \lq
+{\tt \#}\rqs and \lq{\tt \$}\rqs explicitly, we may wish to
+change such characters in the parameters to the normal printable
+ones. For this purpose, we could use correspondingly the pair
+{\tt \string\beginrawblockmode$\{$<token>$\}$} with {\tt
+\string\endrawblockmode} or the pair {\tt
+\string\beginrawlinemode$\{$<token>$\}$} with {\tt
+\string\endrawlinemode}. If {\tt <token>} is not empty, then we
+use {\tt <token>} in place of {\tt \string\endrawblockmode} or
+{\tt \string\endrawlinemode}. In other words, {\tt <token>} is
+the password to leave the raw text mode. Since database utility
+will in general produce a {\sl fixed} number of {\tt <m>} lines
+for each cluster of parameters, we may use {\tt
+\string\begindatamode[<token>]$\{$<m>$\}$} and {\tt
+\string\enddatamode} (or {\tt<token>}) in place of {\tt
+\string\beginrawlinemode} and {\tt\string\endrawlinemode} so that
+each {\tt<m>} raw text lines, including the empty ones, will eject
+a form letter.
+}
+
+
+\medskip
+
+It is often desirable that a letter form or format and the actual
+parameters be kept in different files: it will help in archiving
+and retrieving form letters. Furthermore, if a letter is quite
+long such that the \TeX\ can't hold it in the memory, then we
+{\sl have to} keep the letter content in a separate file.
+Essentially we need to save everything between
+{\tt\string\beginletter} and {\tt \string\endletter} into a
+separate file, say, {\tt letter.let}, then later on use
+{\tt\string\inputletter$\{$letter.let$\}$} to load in the letter
+format. Should one prefer to keep everything inside a {\sl single}
+file, however, he may use {\tt\string\beginfile [{\it
+password}]$\{${\it file.ext}$\}$} and {\tt\string\endfile} (or
+{\it password}) to create files such as {\tt letter.let}
+mentioned above as a temporary scratch file. We note that {\tt
+letter.let} will not contain {\tt\string\beginletter} and
+{\tt\string\endletter} as {\tt \string\inputletter} will add them
+properly for us. Also the extension {\tt .let} is preferred in
+this connection as it can indicate that this type of format file
+should not quite be regarded as the normal \TeX\ files.
+
+\medskip
+
+Likewise, it is also desirable to have a separate address or
+general letter parameter file. For the address file, we remark
+that we have to keep the pairing {\tt \string\beginlinemode} with
+{\tt \string\endlinemode} or {\tt\string\beginblockmode} with
+{\tt \string\endblockmode} inside the address file, if we are to
+use any of them for some content of that file. Moreover, an
+extension {\tt .adr} is recommended for such files. Thus for a
+letter format or template saved in {\tt letter.let}, we may
+choose {\tt letter.adr} as the name for the related address file.
+
+\medskip
+After a letter format is completed for sometime, one may have
+difficulty in recalling what those parameters should refer to
+when using the form letter again. For this purpose, we provide
+a simple mechanism with {\tt\string\paranames} and {\tt
+\string\showparas}. To be more precise, if one puts {\tt
+\string\paranames\ name-1-1; ...; <etc>!} at the very beginning of
+the letter format, then one can use {\tt\string\showparas}
+outside to output a letter with its parameters replaced by their
+names.
+
+\medskip
+
+An alternative way, or rather a way of highlighting the positions
+of the letter parameters is to use {\tt\string\preview}. Under
+{\tt\string\preview}, or {\tt \string\previewtrue}, all
+parameters given by {\tt\string\paras[<m>][<n>]} will be boxed
+with double borderlines, similar to {\tt \previewtrue
+\paras[3][2]}, the number {\tt<n>-<m>} inside (corresponding to
+{\tt 2-3} in the shown box) denotes the {\tt<m>}-th parameter of
+the {\tt <n>}-th group. However, the parameters given by
+{\tt\string\blockparas} or {\tt\string\addressparas} will be
+boxed with triple borderlines. Moreover, the macro parameters
+{\tt<pre>} and {\tt <post>} will also be displayed explicitly.
+Since {\tt\string\addressparas} is essentially a special way of
+using {\tt\string\blockparas}, it is highlighted via that for the
+{\tt\string\blockparas}. In particular,
+{\tt\string\blockparas[3][6][\string\x][\string\y]} for instance
+will display under {\tt \string\preview} the following box
+
+\smallskip
+{\previewtrue \blockparas[3][6][\x][\y]}
+
+
+\medskip
+
+Sometimes we may want to have each given {\sl empty} letter
+parameter automatically replaced by a particular {\sl default}
+parameter. This can be easily done by using {\tt
+\string\loaddefaultparas} inside your letter format, i.e.
+essentially between {\tt \string\beginletter} and {\tt
+\string\endletter}, before any calling of the letter parameters
+via {\tt \string\paras} etc. Of course, the effect of {\tt
+\string\loaddefaultparas} is nil unless a command {\tt
+\string\paradefaults} is issued inside or (better still) outside
+the letter format. We note that {\tt \string\paradefaults} takes
+the macro parameters in the exact way as {\tt \string\paranames}
+does. One note of caution: {\tt \string\paradefaults} and {\tt
+\string\paranames} always use the default delimiters \lq{\tt ; +
+!}\rqs no matter how you changed them via {\tt
+\string\delimiters}. This is to avoid unnecessary complications.
+
+\medskip
+
+We note that printing labels is no more than designing a special
+letter template. The mechanism provided in {\tt formlett} however
+is to pick a subblock of parameters as the address. Basically all
+the form letter output inside {\tt\string\beginlabels} and
+{\tt\string\endlabels} will produce labels instead, taking the
+first parameter group as the address by default (see Appendix for
+more details). Incidentally, labels can be printed in single or
+double columns depending upon the choice of label width.
+
+\medskip
+
+To conclude this section, we remark that if you want to put {\tt
+\string\input\ {\sl filename} } into a letter parameter, make
+sure that there is a {\sl nontrivial} space following the {\sl
+filename}. To be on the safe side, always use {\tt
+\string\inputfile $\{$\sl filename.ext$\}$} instead. Also {\tt
+<!>}, when output to screen, is an invitation to read the log
+file for a warning message.
+
+\bigskip
+{\lbold Example}
+
+
+\smallskip
+
+The following is an example. If you are running plain \TeX, add
+{\tt\string\input\ formlett} at the top. But if you are running
+\LaTeX, then just add at the top the line
+
+\linecount=1\relax
+\stt\beginrawlist[][][4][][][3.3in]{}
+ \documentstyle[formlett]{article}
+ \begin{document}
+\endrawlist
+\rm
+
+
+
+The line numbering on the right hand side is for reference only,
+as in the other occurrences later on. The example reads as
+follows.
+
+\medskip
+
+\stt\beginrawlist[][][4][][][3.3in]{}
+ \beginletter
+ \paranames % optional
+ \tt<<FULL NAME>>;%
+ \tt<<ADDRESS-etc>>;%
+ +\tt<<GIVEN NAME>>;%
+ \tt<<MISSING ITEM>>;%
+ \tt<<PHONE NUMBER>>!
+ \loaddefaultparas % optional
+
+ \NOPAGENUMBERS\parindent=0pt
+ \noindent{\it\paras[1]}\par
+ \blockparas[2]\par\bigskip
+
+ Dear \paras[1][2],\par\medskip
+ We have been looking for
+ \paras[2][2] for quite a while
+ without any luck, could you help
+ us out? If so, please ring
+ \paras[3][2]. \par\medskip
+ Cheers!\hfill Michael\vfill\eject
+ \endletter
+ \preview \showparas
+\endrawlist
+\rm
+
+
+\medskip
+
+%%%%%%%%%%%%
+% letter top
+%%%%%%%%%%%%
+
+ \beginletter
+\sl
+\hsize=3.1in\relax
+\medskip
+ \paranames % optional
+ \tt<<FULL NAME>>;%
+ \tt<<ADDRESS-etc>>;%
+ +\tt<<GIVEN NAME>>;%
+ \tt<<MISSING ITEM>>;%
+ \tt<<PHONE NUMBER>>!
+ \loaddefaultparas % optional
+
+ \NOPAGENUMBERS\parindent=0pt\overfullrule=0pt
+ \noindent{\it\paras[1]}\par
+ \blockparas[2]\par\medskip
+
+ Dear \paras[1][2],
+
+ \smallskip
+ We have been looking for
+ \paras[2][2] for quite a while
+ without any luck, could you help
+ us out? If so, please ring
+ \paras[3][2]. \par\medskip
+ Cheers!\hfill Michael\par %\vfill\eject
+\medskip
+ \endletter
+
+%%%%%%%%%%%%
+% letter end
+%%%%%%%%%%%%
+
+
+The above is a typical letter format or form letter. Command
+{\tt\string\preview} in the last line gives
+
+{\preview}
+
+and, the name of the parameters are displayed via
+{\tt\string\showparas} as follows
+
+\showparas
+
+
+\medskip
+
+In other words, we can have a good understanding about what a
+letter format does {\sl without} reading its source code, which
+will be very handy for archiving and retrieving letter templates.
+To provide defaults for letter parameters and output new letters
+via {\tt blockmode}, we may add \par
+
+\medskip
+\stt\beginrawlist[][][4][][][3.3in]{}
+ \paradefaults % optional
+ To whom this may concern
+ +Sir or Madam;something;%
+ 061-225-9905!
+
+ \blockmarks
+ \beginrawblockmode{}
+
+ Mrs L Stenson
+ #1-20 Sunset Street
+ Hillside, Norway
+ ------
+ Louise
+ a Bible
+ 220-8888
+ =========
+
+ ......
+
+ Above empty line active
+
+ \endrawblockmode
+\endrawlist
+\rm
+
+%%%%%%%%%%%%
+% 1st letter top
+%%%%%%%%%%%%
+\paradefaults % optional
+ To whom this may concern
++Sir or Madam;something;%
+ 061-225-9905!
+
+%%%%%%%%%%%%
+% 1st letter end
+%%%%%%%%%%%%
+
+\medskip
+We note the parameters contain special characters \#. That is
+the reason why we used {\tt\string\beginrawblockmode}. Now
+suppose we have to wrap a very long address line, we could use
+{\tt \string\addressbox} to control an {\sl individual}
+parameter. The following is a typical case
+
+\medskip
+\stt\beginrawlist[][][4][][][3.3in]{}
+ \defaultmarks
+ \moreletter
+ S Wales,;%
+ \addressbox[2in][1em]{%
+ University of Manchester Institute
+ of Science and Technology, This is
+ a long address line: it will be
+ wrapped up automatically.}%
+ +;a \TeX\ package \gstr\ manual and
+ many more (\cstr)!
+\endrawlist
+\rm
+
+\medskip
+which is manifested in the following output
+
+%%%%%%%%%%%%
+% 2nd letter top
+%%%%%%%%%%%%
+\defaultmarks
+\moreletter
+ S Wales,;%
+ \addressbox[2in][1em]{%
+ University of Manchester Institute
+ of Science and Technology, This is
+ a long address line: it will be
+ wrapped up automatically.}%
++;a \TeX\ package \gstr\ manual and
+ many more (\cstr)!
+%%%%%%%%%%%%
+% 2nd letter end
+%%%%%%%%%%%%
+
+
+\medskip
+
+Please note that the default parameters have been used there. In
+the case of putting {\sl only} name and address into a form
+letter, we may typically use {\tt linemode} via e.g.
+
+\medskip
+\stt\beginrawlist[][][4][][][3.3in]{}
+ \beginlinemode
+ Z Jiang
+ UNE, Arimdale
+
+ T Ribbons
+ UMIST, Manchester
+ \endlinemode
+ \end{document}
+\endrawlist
+\rm
+
+\medskip
+
+If one saves lines 4-22 to file {\tt myletter.let}, lines 25-63
+or simply lines 57-63 to file {\tt myletter.adr}, then we can for
+instance produce via \LaTeX\ the form letter for multiple
+receivers by
+
+\setraw
+ \documentstyle[formlett]{article}
+ \begin{document}
+ \inputletter{myletter.let}
+ \showparas \preview
+ \paradefaults To whom it may concern!
+ \inputfile{myletter.adr}
+ \beginlabels % 1st parameter group as address
+ \inputfile{myletter.adr} % for labels
+ \endlabels
+ \end{document}
+\unsetraw
+
+{\smooth
+
+If one puts commands {\tt\string\beginlables} and
+{\tt\string\endlabels} at e.g. immediately after line 2 and 63
+respectively, then one gets all the posting labels instead. If
+one puts commands {\tt\string\beginfile$\{$scratch.adr$\}$} and
+{\tt\string\endfile} there respectively, then by adding after
+{\tt\string\endfile} the commands
+
+\setraw
+ \inputfile{scratch.adr}
+ \beginlabels \inputfile{scratch.adr} \endlabels
+\unsetraw
+
+one gets both form letters and the labels. If one insists on not
+writing out auxiliary scratch files, then use {\tt \string\input
+\ formlett.sty \string\initstyle\ [{\it styles}]$\{${\tt
+article}$\}\{${\it preamble}$\}$} to replace {\tt
+\string\documentstyle\ [formlett, {\it styles}]$\{$article$\}$
+{\it preamble} \string\begin$\{$document$\}$}, which will be
+valid for \LaTeX\ but ignored for \TeX\ , and will enable one to
+use {\tt \string\labelsquit} at the end to read in the current
+document again with all the letters there converted into the
+corresponding labels. If you only want to execute certain
+commands the first time round (i.e. before {\tt
+\string\labelsquit} re-reads the file again), use {\tt
+\string\firstread$\{${\it commands}$\}$} for this purpose.
+
+}
+
+
+\bigskip
+{\lbold Macros}
+
+
+\smallskip
+
+One of the main technical features of this set of macros is the
+extensive use of arrays, both one dimensional and two
+dimensional. The one dimensional array {\tt STK} that we use is
+essentially an user-defined stack, while the two dimensional
+arrays {\tt LET} and {\tt DEF} are more like structure or record
+in other programming languages. First let us make clear that an
+array (or stack) of name, say {\tt ABC}, will contain elements
+{\tt \string\ABC\it m\tt\t} for one dimensional and {\tt
+\string\ABC\it m\tt*\it n\tt\t} for two dimensional case, where
+$m$ and $n$ are some non-negative integers representing row and
+column numbers respectively. The first element, if necessary,
+will be used to denote the length of that raw. Thus, {\tt
+\string\ABC1*0\t} for instance will denote the number of elements
+in the first raw of a two dimensional array {\tt ABC}.
+
+
+\medskip
+
+Let us now look at how a mechanism of defaulting {\sl macro}
+parameters is formulated. For this purpose, we first define a
+stack {\tt STK} and its stack pointer {\tt \string\STKcount} by
+
+\setraw
+ \def\make@STKcount{\csname newcount\endcsname
+ \STKcount\global\STKcount=0\relax}
+ \ifx\STKcount\undefined@\def\next{%
+ \make@STKcount}\else\def\next{}\fi\next
+ \long\def\push#1{\global
+ \advance\STKcount1\relax
+ \expandafter\gdef\csname STK\the
+ \STKcount\string~\endcsname{#1}}
+ \def\popnil{\expandafter\let
+ \expandafter\temp@macro\csname
+ STK\the\STKcount\string~\endcsname
+ \ifnum\STKcount>0\global\expandafter
+ \let\csname STK\the\STKcount
+ \string~\endcsname=\undefined@
+ \global\advance\STKcount-1%
+ \else
+ \def\temp@macro{}\global\STKcount=0%
+ \fi\relax }
+ \def\pop{\popnil\temp@macro}
+\unsetraw
+
+
+The first four lines of code will ensure that the stack pointer
+will not be flushed if this useful subset of macros is loaded
+again by for instance another style file in the middle of a \TeX
+\ document. With the above code, we can stack away anything by
+{\tt\string\push$\{anything\}$} and later use {\tt \string\pop}
+to recall them or {\tt \string\popnil} to remove one element from
+the stack.
+
+
+\medskip
+So, how can we make defaults for certain empty macro
+parameters? The simplest case is perhaps
+
+
+\setraw
+ \long\def\get@nepara[#1][#2]{{%
+ \def\next@{#2}%
+ \ifx\next@\empty\push{#1}\else
+ \push{#2}\fi}\ag@in}
+ \long\def\get@para\left@#1\right@{%
+ \def\check@{%
+ \ifx[\next@
+ \def\full@####1{\get@nepara[#1]####1}%
+ \else
+ \def\full@{\get@nepara[#1][#1]}\fi
+ \full@}%
+ \futurelet\next@\check@}
+\unsetraw
+
+
+
+Basically, {\tt\string\get@onepara[<A>][<B>]} will push the
+default {\tt <A>} to the stack {\tt STK} unless {\tt <B>} is
+nonempty. And {\tt\string \get@para\string \left@<A>\string
+\right@} will look at the next token to be read, if it is
+character \lq{\tt[}\rq, then reads in a macro parameter in the
+form of {\tt [<B>]} and then push {\tt <B>} to the stack {\tt
+STK}, otherwise push the default {\tt <A>} to that stack. For the
+more general case, we need to define
+
+
+\setraw
+ \long\def\do@nepara
+ \left@#1\right@#2\p@r@end{%
+ \gdef\p@r@data{#2}\global\advance
+ \p@r@count1\get@para\left@#1\right@}
+ \def\ag@in{\ifx\p@r@data\empty
+ \def\next@{\relax\getp@r@s\run@CMD}%
+ \else\def\next@{\expandafter\do@nepara
+ \p@r@data\p@r@end}%
+ \fi\next@}
+ \def\run@CMD{\csname STK\the\STKcount
+ \string~\endcsname}
+ \newcount\p@r@count
+ \long\def\st@ckparas#1\p@r@end{%
+ \global\p@r@count=0%
+ \gdef\p@r@data{#1}\ag@in}
+\unsetraw
+
+
+so that {\tt\string\st@ckparas \string\left@<A>\string\right@
+...\penalty -20 \string\left@<B>\string\right@ ...
+\string\p@r@end} will look for parameters enclosed in {\tt []}
+one by one, exhausting all the defaults paired by
+{\tt\string\left@} and {\tt \string\right@}. If future tokens
+inside {\tt []} are not found, or empty, the default tokens
+inside the corresponding pair {\tt\string\left@ \string\right@}
+will be used. The new or default tokens will be pushed to the
+general-purpose stack {\tt STK} for a later use, while {\tt
+\string\p@r@count} records the total number of the default macro
+parameters. We note that on exit of {\tt \string\st@ckparas}, the
+control is passed to {\tt\string\runCMD}.
+
+\medskip
+Once all macro parameters are pushed to the stack, we may
+transfer them to separate toks {\tt \string\p@r@one} to {\tt
+\string\p@r@nine} (an easier-to-use format) defined by
+
+\setraw
+ \newtoks\p@r@one\newtoks\p@r@two
+ \newtoks\p@r@three\newtoks\p@r@four
+ \newtoks\p@r@five \newtoks\p@r@six
+ \newtoks\p@r@seven\newtoks\p@r@eight
+ \newtoks\p@r@nine
+ \def\clrp@r@s{\global\p@r@one={}%
+ \global\p@r@two={}\global\p@r@three={}%
+ \global\p@r@four={}\global\p@r@five={}%
+ \global\p@r@six={}\global\p@r@seven={}%
+ \global\p@r@eight={}\global\p@r@nine={}}
+\unsetraw
+
+where {\tt\string\clrp@r@s} clears all the parameter toks. We can
+then retrieve parameters from the stack {\tt STK} to the
+parameter toks via {\tt\string \getp@r@s} with the following code
+
+
+\setraw
+ \newcount\temp@count
+ \def\getp@r@s{\temp@count=\p@r@count
+ {\loop
+ \ifnum\temp@count>0
+ \expandafter\let\expandafter
+ \t@macro\csname STK\the\STKcount
+ \string~\endcsname
+ \ifcase\temp@count
+ \or\global\p@r@one=\expandafter{\t@macro}%
+ \or\global\p@r@two=\expandafter{\t@macro}%
+ \or\global\p@r@three=\expandafter{\t@macro}%
+ \or\global\p@r@four=\expandafter{\t@macro}%
+ \or\global\p@r@five=\expandafter{\t@macro}%
+ \or\global\p@r@six=\expandafter{\t@macro}%
+ \or\global\p@r@seven=\expandafter{\t@macro}%
+ \or\global\p@r@eight=\expandafter{\t@macro}%
+ \or\global\p@r@nine=\expandafter{\t@macro}%
+ \else
+ \errmessage
+ {Parameter capacity exceeded.}%
+ \fi \global\expandafter\let
+ \csname STK\the\STKcount
+ \string~\endcsname=\undefined@%
+ \global\advance\STKcount-1%
+ \global\advance\temp@count-1\relax
+ \fi
+ \ifnum\temp@count>0\repeat}}
+\unsetraw
+
+
+
+\medskip
+We are now ready to use the above mechanism to default
+macro parameters for some already defined macros. Suppose we have
+already defined a macro {\tt \string\crudemac[<A>][<B>]} which
+takes two macro parameters {\tt <A>} and {\tt<B>}, and we want to
+define a new macro {\tt \string\smartmac} which behaves like {\tt
+\string\crudemac} but will default the macro parameters {\tt <A>}
+and {\tt <B>} to for instance 9 and 88 respectively. For this
+purpose, we may define {\tt \string\smartmac} via
+
+
+
+\setraw
+ \def\smartmac{\push{%
+ \edef\next@@{\noexpand
+ \crudemac[\the\p@r@one][\the\p@r@two]}%
+ \popnil\clrp@r@s\next@@}\st@ckparas
+ \left@9\right@\left@88\right@\p@r@end}
+\unsetraw
+
+This way, all the followings
+
+\setraw
+ \crudemac[9][88], \smartmac[9][88],
+ \smartmac, \smartmac[], \smartmac[][],
+ \smartmac[9], \smartmac[9][], \smartmac[][88]
+\unsetraw
+
+are the same under the assumption that we shall not use
+characters \lq{\tt[}\rqs and \lq{\tt]}\rqs for the macro
+parameters themselves, and that {\tt\string\crudemac} will not
+change any {\tt \string\catcode} inside. The reason for this
+latter condition lies in the fact that when {\tt\string\smartmac}
+looks at the next character, the character is in a sense already
+read. If {\tt \string\crudemac} changes the {\tt\string\catcode}
+of that particular character, then the one that is already read
+via {\tt\string\futurelet} will have a misleading
+{\tt\string\catcode}. If one has to change {\tt \string\catcode}
+inside but wants to avoid this possible misbehavior, always put
+full number of empty brackets \lq{\tt[]}\rqs for the defaults, or
+put a {\tt\string\relax} immediately afterwards. Better still,
+make the last parameter to appear in a mandatory \lq$\{\}$\rqs form
+rather than the \lq{\tt []}\rqs form via the {\tt \#$\{$} mechanism
+[1], so that those square brackets can be dropped off.
+
+
+\medskip
+
+
+For example, we as a by-product also defined a 100\%
+verbatim mode by
+
+{\stt
+\ \ \string\begin@@rawlist[$A$][$B$][$C$][$D$][$E$][$F$]$G$ }\par
+\setraw
+ <general text>
+ \endrawlist
+\unsetraw
+
+
+where, for the line numbering of the raw text, {\tt $A$}, ...,
+{\tt $G$} represent respectively the initial value, increment
+step, number of digits, font, horizontal position of text,
+horizontal shift of numbering, and the password to leave raw text
+mode. Incidentally, {\tt \string\linecount} records the current
+line numbering count. Our purpose is to define {\tt
+\string\beginrawlist} so that its format is
+
+{\stt
+\ \ \string\beginrawlist[$A$][$B$][$C$][$D$][$E$][$F$]$\{G\}$}\par
+
+in which $A$ to $F$ are {\sl optional} while $\{G\}$ is mandatory
+even though $G$ can be empty --- implying {\tt
+\string\endrawlist} is the password to leave the raw-text mode.
+For this purpose, we first define
+
+\setraw
+\def\begin@rawlist[#1][#2][#3][#4][#5][#6]#{%
+ \begin@@rawlist[#1][#2][#3][#4][#5][#6]}%
+\unsetraw
+
+to make \lq$\{\}$\rqs pair compulsory for {\tt \#7}, then we
+provide the defaults for {\tt $A$} to {$F$} as
+{\tt\string\linecount}, {\tt 1}, {\tt 0}, {\tt \string\tiny},
+{\tt 0pt} and {\tt 0pt} respectively via
+
+\setraw
+\def\beginrawlist{\push{%
+ \edef\next@@{\noexpand\begin@rawlist
+ [\the\p@r@one][\the\p@r@two][\the\p@r@three]%
+ [\the\p@r@four][\the\p@r@five][\the\p@r@six]}%
+ \popnil\clrp@r@s\next@@}% end of push
+ \font\tiny@rm=cmr5%
+ \edef\temp@macro{%
+ \noexpand\left@\the\linecount\noexpand\right@
+ \noexpand\left@1\noexpand\right@
+ \noexpand\left@0\noexpand\right@
+ \noexpand\left@\noexpand\tiny@rm
+ \noexpand\right@
+ \noexpand\left@0pt\noexpand\right@
+ \noexpand\left@0pt\noexpand\right@}%
+ \expandafter\st@ckparas\temp@macro\p@r@end}%
+\unsetraw
+
+\medskip
+
+{\smooth
+\relax Likewise, we could also similarly define {\tt \string\printfile
+[...]}$\{${\it filename.ext}$\}$ so that \lq{\tt [...]}\rqs takes
+a same defaulting scheme. }
+
+
+\medskip
+There are several tiny but very useful macros in {\tt formlett}
+which are used again and again. One of such macros is for testing
+if one string contains another string. The following {\tt
+\string\test@str} tests if string {\tt\#1} is contained in string
+{\tt\#2}
+
+
+\setraw
+ \newif\iftemp@if \newtoks\temp@toks
+ % return \temp@iftrue if yes,
+ % \first@half,\second@half are global
+ \long\def\test@str#1#2{%
+ \long\def\strip@endmark##1\s@fetymarkI
+ #1\s@fetymark{\gdef\second@half{##1}}%
+ \long\def\strip@markI##1\s@fetymarkI
+ \s@fetymark{\gdef\first@half{##1}}%
+ \long\def\p@rse##1#1##2\s@fetymark{%
+ \gdef\first@half{##1}%
+ \gdef\second@half{##2}%
+ \ifx\second@half\empty
+ \strip@markI##1\s@fetymark\temp@iffalse
+ \else
+ \strip@endmark##2\s@fetymark\temp@iftrue
+ \fi}%
+ \temp@toks={#2\s@fetymarkI#1\s@fetymark}%
+ \expandafter\p@rse\the\temp@toks }%
+\unsetraw
+
+
+The {\tt\string\first@half} will contain the tokens upto but
+excluding the substring {\tt\#1}, while the {\tt
+\string\second@half} will contain the tokens after the {\sl
+first} appearance of {\tt\#1}. Should {\tt\#2} not contain string
+{\tt\#1} at all, then {\tt \string\first@half} is the whole
+string {\tt\#2} whereas {\tt \string\second@half} is empty.
+
+\medskip
+
+The small macros such as the above one and the stack utilities,
+though built for the main purpose of {\tt formlett}, provide also
+a good \lq infrastructure\rqs for other house-keepings. One of
+the sidekicks of this type is our macro for commenting out blocks
+of text inside a \TeX\ file. Basically, {\tt
+\string\begincomment$\{$\it password$\}$} will set {\sl all}
+characters of code {\tt0} to {\tt \string\MAX@CHR@CODE}
+(={\tt255} by default) to catcode 11 or 12, and look for the {\it
+password}, or {\tt \string\endcomment} in the absence of a
+password, to quit the comment mode. In comparison to a very
+compact macro {\tt comment.sty} (currently at version 3.0)
+written by Victor Eijkhout, quitting comment mode via a password
+here seems more flexible.
+
+
+
+
+\medskip
+As for the other macros in {\tt formlett}, it is difficult to
+explain them without printing out all of them. So instead, we
+shall explain simply one of the strategies in parsing the letter
+parameters. Suppose $W$ is a list of parameters separated by
+\lq{\tt+}\rqs and ended by \lq{\tt!}\rq, i.e. $W$ is like
+{\tt<A>+<B>+...+<S>!}. Then it will be easy to parse all the
+parameters one by one (to a stack for instance) if we can know
+whether there is precisely one parameter left over. To detect it,
+we use
+
+
+
+\setraw
+ \newif\ifl@stline
+ \long\def\testl@stline
+ #1+#2!#3\s@fetymark{%
+ \def\next{#2}\ifx\next\empty
+ \l@stlinetrue\else\l@stlinefalse\fi
+ \def\next{#3}\def\nextsample{+!}%
+ \ifx\next\nextsample\l@stlinefalse\fi}
+\unsetraw
+
+
+
+{\smooth Then the command
+{\tt \string\testl@stline} {\tt $W$+!\string\s@fetymark }
+will set {\tt \string\l@stlinetrue} if
+there is only one parameter left in $W$, and will set {\tt
+\string\l@stlinefalse} if otherwise. }
+
+
+
+\medskip
+
+Finally, for those wizard users who want to do everything their own way,
+we just note that if for instance the 3rd letter parameter of the 2nd
+group of a cluster is given as {\tt<A>}, then {\tt \string\LET2*3\t}
+will contain {\tt \string\b@group \string\relax {\tt<A>}\string\e@group}
+right after a cluster is read in. {\tt \string\DEF2*3\string~}, on the
+other hand, contains the corresponding default parameter in the same
+fashion. Furthermore, the command
+{\tt\string\checkparas[$m$][$n$]$\{$LET$\}$} will copy the content of
+{\tt\string\paras[$m$][$n$]}, minus the `wrapping' extra tokens
+{\tt\string\b@group\string\relax} and {\tt\string\e@group}, to
+{\tt\string\cachedata} and set {\tt\string\ifemptyparas} to true or
+false depending on whether the content is empty or not. This way, a user
+may even change the characteristics of his letter template by first
+testing the content of the supplied individual parameters. However, we
+note that if {\tt\string \loaddefaultparas} is executed, then the {\tt
+LET} array, when some of its elements are not supplied, will contain the
+corresponding elements of the {\tt DEF} array. Hence care must be
+exercised under such circumstances, when interpreting the
+{\tt\string\cachedata} generated by
+{\tt\string\checkparas[$m$][$n$]$\{$LET$\}$}. If necessary, we may use
+{\tt\string\delparadefaults} to delete current default parameter array
+{\tt DEF} so as to conduct {\tt\string\checkparas$\{$LET$\}$} more
+precisely. So if anyone wants to manipulate furthermore letter
+parameters inside a letter template, he or she will now at least know
+where to look at.
+
+%\penalty -50
+\bigskip
+{\lbold References}
+
+\smallskip
+{\parindent=2em
+\item{[1].} Knuth D E, {\sl The \TeX book}, Reading, Mass.,
+Addison-Wesley, 1992. \par
+\item{[2].} Piff M, Text merges in \TeX\ and \LaTeX, {\sl TUGboad},
+13(4):518, 1993. \par
+\item{[3].} Damrau J and Wester M, Form letters with 3-across
+labels capacity, {\sl TUGboat}, 13(4):510, 1991.
+\par
+}
+
+
+\penalty -50\bigskip
+
+{\lbold Appendix}
+
+
+\smallskip
+
+
+In the followings, we give a brief summary of the new commands
+given by {\tt formlett} version 2.3.
+
+\medskip
+
+Let $m$ and $n$ be numbers, $p$, $q$ and $r$ be dimensions, $A$,
+$B$, $P$, $G$, $C$ and $T$ be tokens, and $X$ be a box.
+Furthermore, we shall denote by $R$ a full set of letter
+parameters ended by \lq{\tt !}\rq, with \lq{\tt;}\rqs separating
+parameters inside a same group and \lq{\tt+}\rqs separating
+different parameter groups. We moreover denote $R$ by $F$, when
+\lq{\tt ; + !}\rqs there can be replaced by \lq$P$ $G$ $C$\rqs
+respectively if {\tt \string\delimiters$\{P\}\{G\}\{C\}$} is
+issued. In the commands tabulated below, the macro parameters
+contained in squared brackets support default. In particular, the
+defaults are $m$={\tt 1}, $n$={\tt 1}, $p$={\tt 8truecm},
+$q$={\tt 1.5em}, $r$={\tt 3pt}, $A$={\tt\string\noindent},
+$B$={\tt\string\par}, {\tt\string\previewfalse},
+{\tt\string\localparastrue} and {\tt\string\nodefaultsfalse}.
+
+
+%\penalty-10000
+
+\vskip 0pt plus 5cm
+
+
+\newdimen\tempdimone
+\newdimen\tempdimtwo
+\tempdimone=\hsize
+\advance\tempdimone by-0.2pt
+\tempdimtwo=\hsize
+\advance\tempdimtwo by-1.8in
+\def\hruler{\hrule width \tempdimone}
+\long\def\entry#1#2{%
+\par\hbox to \tempdimone{\noindent
+ \vrule~\textbox[1.7in]{#1}~\hss
+ \vrule~\textbox[\tempdimtwo]{\raggedright#2}~\vrule}%
+ \par}
+
+\long\def\longentry#1#2#3{%
+\par\hbox to \tempdimone{\noindent
+ \vrule~\textbox[3in]{#1}~\hss~\vrule}\par
+ {\kern-8pt \advance\tempdimtwo0.10in
+ \vrule width1.7in height0pt \vrule width\tempdimtwo height 0.4pt \par
+ \kern-3pt}
+ \entry{#2}{#3}}
+
+\long\def\Longentry#1#2#3{%
+\par\hbox to \tempdimone{\noindent
+ \vrule~\textbox[3in]{#1}~\hss~\vrule}\par
+ {\advance\tempdimtwo0.08in\kern-1pt
+ \vrule~\hfill\vrule width \tempdimtwo height 0.4pt \vrule\par
+ \kern-2.5pt}%
+ \entry{#2}{#3}}
+
+
+
+\medskip \penalty-100
+{\eightpoint
+\nointerlineskip\parskip=0pt
+
+\hruler
+\entry{{\tt\string\paras[$m$][$n$]}}%
+ {$m^{th}$ parameter of $n^{th}$ group }%
+
+\entry{{\tt\string\blockparas[$m$][$n$][$A$][$B$]}}%
+ {$m^{th}$ to the last parameter of $n^{th}$ group, each
+preceded by $A$ and followed by $B$, wrapped by $\{$\penalty
+1000$\}$ if
+$B$={\tt\string\relax}}
+
+\entry{{\tt\string\addressparas[$m$][$n$][$p$][$q$]}}%
+ {$m^{th}$ to the last parameter of $n^{th}$ group, each put
+into a box of width $p$ with indent $q$ for wrapped portions}
+
+
+\entry{{\tt\string\loaddefaultparas}}%
+ {fill empty parameters with defaults}
+
+\hruler \penalty-1000
+\hruler
+
+
+\entry{{\tt\string\checkparas[$m$][$n$]$\{T\}$}}%
+ {$m^{th}$ parameter of $n^{th}$ group copied to {\tt\string\cachedata};
+ {\tt\string\ifemptyparas} is true if element is empty; $T$ is often
+ {\tt LET} or {\tt DEF}}%
+
+\hruler
+
+
+\entry{{\tt\string\moreletter\ $F$}}%
+ {use parameters $F$ to output a new letter}
+
+
+\entry{{\tt\string\paranames\ $R$}}%
+ {use $R$ as parameter names}
+
+\entry{{\tt\string\paradefaults\ $R$}}%
+ {use $R$ as default parameters}
+
+
+\entry{{\tt\string\delparadefaults}}%
+ {delete default parameters}
+
+%\hruler \penalty-1000
+\hruler
+
+
+\entry{{\tt\string\delimiters$\{P\}\{G\}\{C\}$}}%
+ {use $P$, $G$, $C$ as delimiters}
+
+
+\entry{{\tt\string\defaultmarks}}%
+ {use \lq{\tt ; + !}\rqs as delimiters}
+
+
+\entry{{\tt\string\blockmarks}}%
+ {use \lq{\tt ....}\rq, \lq{\tt ----}\rq, \lq{\tt ====}\rqs as delimiters}
+
+%\hruler \penalty -1000
+\hruler
+
+\entry{{\tt\string\preview}}%
+ {highlight parameter positions}
+
+\entry{{\tt\string\showparas}}%
+ {display parameter names, if any}
+
+\entry{{\tt\string\inputletter$\{file.ext\}$}}%
+ {input letter content}
+
+\entry{{\tt\string\inputfile$\{file.ext\}$}}%
+ {input $file.ext$}
+
+%\hruler \penalty -1000
+\hruler
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginletter}\cr
+\hbox{\tt\string\endletter~~}\cr}\right.$ }%
+ {delimiters for letter content (template)}
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginpilemode}\cr
+\hbox{\tt\string\endpilemode~~}\cr}\right.$ }%
+ {normal letter parameters cluster-wise}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginblockmode}\cr
+\hbox{\tt\string\endblockmode~~}\cr}\right.$ }%
+ {for line-by-line blocks of parameters, empty lines active
+within each cluster}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginlinemode}\cr
+\hbox{\tt\string\endlinemode~~}\cr}\right.$ }%
+ {for line-by-line parameters, empty lines delimit clusters}
+
+%\hruler \penalty-1000
+\hruler
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginrawblockmode$\{T\}$}\cr
+\hbox{\tt\string\endrawblockmode\ \ \ \ \ }\cr}\right.$ }%
+ {raw text mode; nonempty $T$ replaces {\tt\string\endrawblockmode}
+ to mark end}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginrawlinemode$\{T\}$}\cr
+\hbox{\tt\string\endrawlinemode\ \ \ \ \ \ }\cr}\right.$ }%
+ {raw text parameters and active spaces etc}
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\begindatamode[$T$]$\{m\}$}\cr
+\hbox{\tt\string\enddatamode\ \ \ \ \ \ \ \ }\cr}\right.$ }%
+ {$m$ raw text lines for one form letter}
+
+\hruler
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\begincolumns[$a$][$b$]}\cr
+\hbox{\tt\string\endcolumns\ \ \ \ \ \ \ }\cr}\right.$ }%
+ {$a$-columns separated by distance $b$}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\begincomment$\{T\}$}\cr
+\hbox{\tt\string\endcomment\ \ \ \ \ }\cr}\right.$\par
+ \ \ \ {\tiny }}%
+ {comment out lines, nonempty $T$ replaces {\tt
+\string\endcomment} to mark last {\sl full line} for comment}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginfile[$T$]$\{{\it
+file.ext}\}$}\cr
+\hbox{\tt\string\endfile\ \ \ \ \ \ \ \ \ \ \ \ \ }\cr}\right.$\par
+ \ \ \ {\tiny }}%
+ {write text verbatim to file {\it file.ext} (empty implies {\tt
+scr@tch@.tex}), nonempty $T$ replaces {\tt
+\string\endfile} to mark last full line}
+
+
+
+\hruler
+
+
+\entry{{\tt\string\PAGENO=1}}%
+ {page number reset to 1}
+
+
+\entry{{\tt\string\NOPAGENUMBERS}}%
+ {no page numbers}
+
+
+\entry{{\tt\string\textbox[$p$]$\{text\}$}}%
+ {$text$ into box of width $p$}
+
+
+\entry{{\tt\string\boxmore[$r$]$\{X\}$}}%
+ {add borderline to box $X$ at a distance $r$}
+
+
+\entry{{\tt\string\addressbox[$p$][$q$]$\{text\}$}}%
+ {$text$ into box of width $p$, with wrapped options indented
+by $q$}
+
+\hruler
+
+
+\entry{{\tt\string\previewfalse}}%
+ {given parameters instead of highlighted boxes will be shown}
+
+
+\entry{{\tt\string\localparastrue}}%
+ {letter parameters put into $\{\}$ before displayed}
+
+
+\entry{{\tt\string\nodefaultsfalse}}%
+ {take defaults for empty letter parameters}
+
+\hruler
+
+\entry{{\tt\string\previewtrue}}{{\it cf.} above}
+
+
+\entry{{\tt\string\localparasfalse}}{}
+
+
+\entry{{\tt\string\nodefaultstrue}}{}
+
+\hruler
+
+\vskip0pt plus 1cm
+~\hfill $\underline{\hbox{\sl Table continues in the next page}}$
+
+\penalty-5000
+\hruler
+
+
+\Longentry{%
+$\left\{\matrix{ \hbox{\tt\string\beginrawlist
+ [$a$][$b$][$c$][$d$][$e$][$f$]$\{g\}$}\cr
+ \hbox{\tt\string\endrawlist\hskip3.4cm}\cr}\right.$ }%
+ {\strut\par{\sl defaults:}\everypar={\hbox{\ \ \ }}\par\par
+ $a$={\tt\string\linecount},\par
+ $b$={\tt1}, $c$={\tt0},\par
+ $d$={\tt\string\tiny@rm}, \par
+ $e$={\tt0pt}, $f$={\tt0pt}, \par
+ $g$={\tt\string\endrawlist}}%
+{verbatim listing, line count from $a$, step $b$, digits $c$,
+font $d$, text position $e$, numbering shift $f$, end mark $g$}
+
+\hruler \vskip0.5pt
+\Longentry{%
+$\matrix{\hbox{\tt \string\printfile
+ [$a$][$b$][$c$][$d$][$e$][$f$]$\{$\it file.ext$\}$}\cr
+ \hbox{}\cr}$}%
+ {\strut\par{\sl defaults:} ~~$c$={\tt6} {\it etc}}%
+ {verbatim listing of {\it file.ext}}
+
+\hruler
+
+
+
+\Longentry{%
+$\left\{\matrix{ \hbox{\tt\string\beginlabels
+ [$a$][$b$][$c$][$d$][$e$][$f$]}\cr
+ \hbox{\tt\string\endlabels\hskip3cm}\cr}\right.$ }%
+ {\strut\par{\sl defaults:}\everypar={\hbox{\ \ \ }}\par\par
+ $a$={\tt 20pt}, \par $b$={\tt\string\tt\string\raggedright},
+ \par $c$={\tt1}, $d$={\tt1}, \par
+ $e$={\tt2.6in}, $f$={\tt2em}}%
+ {form letters become labels: address taken from $c^{th}$ to
+last parameter of $d^{th}$ group, with width $e$, indent
+$f$, borderspace $a$ and font toks $b$}
+
+\hruler
+
+
+\entry{{\tt\string\firstread$\{T\}$}}%
+ {toks $T$ will not be read if the file is re-read via {\tt
+ \string\labelsquit}}
+
+
+\entry{{\tt\string\initstyle[$a$]$\{b\}\{c\}$}}%
+ {initiation for {\tt\string\labelsquit},with styles $a$,
+ documentstyle $b$ and preamble $c$}
+
+\entry{{\tt\string\initclass[$a$][$o$]$\{b\}\{c\}$}}%
+ {similar to {\tt\string\initstyle} ($o$ is \LaTeX2e options),
+ but retains native \LaTeX2e when applicable}
+
+
+\hruler \vskip0.5pt
+\Longentry{%
+$\matrix{\hbox{\tt \string\labelsquit
+ [$a$][$b$][$c$][$d$][$e$][$f$]$\{$\it file.ext$\}$}\cr
+ \hbox{}\cr}$}%
+ {\strut\par{\sl defaults:}\everypar={\hbox{\ \ \ }}\par\par
+ see that for {\tt\string\beginlabels}}
+ {quit after converting letters to labels by reading the current
+ document or {\it file.ext}}
+
+\hruler
+
+
+
+\def\ABC{{\tt\esc@}{\it abc}}
+
+
+\entry{{\tt\string\newarray\ABC}}%
+ {make array named {\it abc} along with
+ {\tt\ABC} and {\tt\string\check{\it abc}}}
+
+
+\entry{{\tt\string\delarray\ABC}}%
+ {delete array named {\it abc}}
+
+
+\hruler
+
+
+\entry{{\tt\ABC($m$)=$\{T\}$}}%
+ {assign tokens $T$ to {\tt\ABC($m$)};
+ {\tt\ABC($m$)} $\equiv$
+ {\tt\ABC($m_1,...,m_k$)} for
+ $m$=$1+\sum_1^k (m_i-1)*\hbox{\tt\string\dataheight}^{k-i}$}
+
+
+\entry{{\tt\ABC($m$)}}{value of {\tt\ABC($m$)},
+ if not followed by `{\tt=}'}
+
+
+\entry{{\tt\string\dataheight}}{current array dimension: {\it cf.}
+ {\tt\ABC($m$)}}
+
+
+\entry{{\tt\string\readarray$\{N\}\{a_1 \hbox{\&}\, ..\, \hbox{\&} a_n\}$}}%
+ {equivalent to {\tt\esc@{\it N}(1)}=$a_1$, ..,
+ {\tt\esc@{\it N}($n$)}=$a_n$}
+
+
+
+\entry{{\tt\string\check{\it abc}($m$)}}%
+ {copy {\tt\ABC($m$)} to {\tt\string\cachedata};
+ set {\tt\string\ifemptydata} to true/false accordingly}
+
+
+\hruler
+
+\entry{{\tt\string\readstyles$\{f_1,...,f_n\}$}}%
+ {read files $f_1$ to $f_n$ with default extension {\tt .sty};
+ {\tt @}'s catcode set to {\tt 11} during input}
+
+\hruler
+
+
+}
+
+\footline={\lower5pt
+\hbox to \hsize
+ {{\rm Jiang Z ~~~{\sl Formlett: ~for letters to multiple receivers}
+ \hss {\sl $\bullet$End of Document$\bullet$}
+\hss \folio}}}
+
+\vskip 8in
+
+%\vfill\eject
+\endcolumns
+\vfill\eject
+
+
+
+%%%%%%%%%%%%%%%%%%
+% MAKE EXAMPLE1.TEX EXAMPLE2.TEX
+%%%%%%%%%%%%%%%%%%
+
+
+
+\message{Can I create <example1.tex> and <example2.tex> ? (y/n) }%
+\read-1 to \reply \def\nono{n }\def\Nono{N }\def\noNo{no }\def\NoNo{NO }%
+\def\next{\end{document}}%
+\ifx\reply\nono\else\ifx\reply\Nono\else\ifx\reply\noNo\else
+\ifx\reply\NoNo\else\let\next\relax
+\message{(=== YES ===)}\fi\fi\fi\fi \next
+
+
+
+
+\beginfile[EndOfExample1]{example1.tex}
+
+% Example1: EXAMPLE for using scratch files
+% under plain TeX or LaTeX
+%
+
+\input formlett.sty
+%
+%%%% MAKE scr@tch@.let
+%
+\beginfile{scr@tch@.let}
+
+% letter content
+\boxmore[10pt]{\hbox{\vbox{% BOX FOR BORDERLINE
+
+\parindent=0pt
+\blockparas
+
+\bigskip\bigskip
+
+Dear \paras,
+
+\bigskip
+
+This part is typically the letter content. Since we are using a
+scratch file for our main body of our letter, the letter can be
+arbitrarily long, in comparison to using {\tt \string\beginletter}
+and {\tt \string\endletter} mechanism. Using a scratch file enables
+us to keep everything inside one single file so that it won't be mixed
+up with other letters.
+
+\medskip
+
+The idea of scratch file can also be applied to creating the address
+file, so that the address file can be read for the form letters in the
+first time and for mailing labels in the second time. These features are
+the purpose of this particular example.
+
+\medskip
+Thanks for using {\tt formlett.sty}.
+
+}}} % END OF BOX FOR BORDERLINE
+\vfill\eject
+
+\endfile
+
+
+%
+%%%% MAKE scr@tch@.adr
+%
+\beginfile{scr@tch@.adr}
+% address file
+\beginlinemode
+\tt<name>
+address line one
+address line two
+etc
+
+\tt<NAME>
+ADDRESS LINE ONE
+ADDRESS LINE TWO
+ETC
+
+\endlinemode
+\endfile
+
+
+%
+%%% MAIN PROCESSING BODY
+%
+
+\hsize=5in
+\initstyle{}{}
+ % Above line is put here for being
+ % able to run this file under either TeX or LaTeX.
+ % It may be deleted for TeX. It may also be replaced
+ % under LaTeX by \documentstyle{article} \begin{article}
+ % for instance
+
+\inputletter{scr@tch@.let}
+\inputfile{scr@tch@.adr} % for form letters
+\beginlabels
+\inputfile{scr@tch@.adr} % for labels
+\endlabels
+
+\end{document}
+
+EndOfExample1
+% above is password
+
+
+
+
+
+
+\beginfile{example2.tex}%
+
+% Example2: EXAMPLE for self-read
+% under plain TeX or LaTeX
+%
+
+
+\input formlett.sty
+\hsize=3.2in % for plain TeX
+\initstyle[]{}{\textwidth=3.2in} % for LaTeX
+
+% MY LOGO
+%
+\catcode`\@=11\relax
+\def\UWS{{\vbadness=10000 \hbadness=10000 \hfuzz=\maxdimen
+ \vfuzz=\maxdimen \font\tiny=cmr5 \font\small=cmr7
+ \def\today{\number\day\space\ifcase\month\or January\or February\or
+ March\or April\or May\or June\or July\or August\or September\or
+ October\or November\or December\fi\space\number\year}%
+ \def\make@temp@box{\csname newbox\endcsname \temp@box\relax}%
+ \ifx\temp@box\undefined \def\next{\make@temp@box}\else\def\next{}\fi\next
+ \font\HUGE=cmss10 at 24.87999pt \noindent
+ \setbox\temp@box=\hbox{\vbox to 0pt{\hbox{\HUGE
+ U\hskip6pt W\hskip6pt S}}}%
+ \def\buffdim{65pt}%\wd\temp@box 61.588pt
+ \rlap{\copy\temp@box}%
+ \rlap{\hskip.4pt\copy\temp@box}%
+ \rlap{\hskip.8pt\copy\temp@box}%
+ \rlap{\hskip1.2pt\copy\temp@box}%
+ \rlap{\hskip1.6pt\copy\temp@box}%
+ \rlap{\hskip2pt\copy\temp@box}%
+ \rlap{\hskip2.4pt\copy\temp@box}%
+ \rlap{\hskip2.8pt\copy\temp@box}%
+ \rlap{\hskip6pt\copy\temp@box}%
+ \rlap{\lower23pt \hbox to \buffdim{\tiny \hskip4pt The ~~~University~~~ Of}}%
+ \rlap{\lower25pt \hbox{\hskip2pt
+ \hbox to \buffdim{\vrule width \buffdim depth .2pt}}}%
+ \rlap{\lower32pt \hbox to \buffdim{\small \hskip-1pt WESTERN SYDNEY}}%
+ \setbox\temp@box=\hbox{\vbox{\let\noindent=\hfill
+ \font\small=cmss8 \baselineskip=8pt %plus 0.5pt minus 0.5pt
+ \small \parskip=0pt
+ \noindent School of Computing and IT\par
+ \noindent University of Western Sydney\par
+ \noindent Victoria Road, Parramatta\par
+ \noindent NSW 2150, Australia\par
+ \medskip
+ \noindent Email: ~z.jiang@uws.edu.au\par
+ \noindent Tel: ~(INT-) 61- 2- 96859336\par
+ \noindent Fax: ~(INT-) 61- 2- 96859245\par
+ \medskip\bigskip
+ \noindent \tt\today}}%
+ \rlap{\lower3.0cm \hbox{\box\temp@box}}%
+}\par}\catcode`\@=12\relax
+%
+
+\beginletter
+\paranames % optional
+ \tt<<FULL NAME>>;%
+ \tt<<ADDRESS-etc>>;%
+ +\tt<<GIVEN NAME>>;%
+ \tt<<MISSING ITEM>>;%
+ \tt<<PHONE NUMBER>>!
+\loaddefaultparas % optional
+
+\NOPAGENUMBERS\parindent=0pt\overfullrule=0pt
+\UWS \par\bigskip\bigskip\bigskip
+\noindent{\it\paras[1]}\par
+\blockparas[2]\par\bigskip
+
+Dear \paras[1][2],\par\medskip
+We have been looking for
+\paras[2][2] for quite a while
+without any luck, could you help
+us out? If so, please ring
+\paras[3][2]. \par\medskip
+Cheers!\hfill Zhuhan\vfill\eject
+\endletter
+\preview \showparas
+\eject % \eject here is purely for better labels
+
+
+\paradefaults % optional
+ To whom this may concern
+ +Sir or Madam;something;%
+ 061-225-9905!
+
+
+\blockmarks
+\beginblockmode
+
+Mrs L Stenson
+\#1-20 Sunset Street
+Hillside, Norway
+------ separate groups
+Louise
+a Bible
+220-8888
+========= separate cluster
+
+...... force entry next line
+
+Above empty line active
+
+\endblockmode comment ignored
+
+\defaultmarks
+\moreletter
+ S Wales,;%
+ \addressbox[2in][1em]{University of Manchester Institute
+ of Science and Technology, This is
+ a long address line: it will be
+ wrapped up automatically.}
+ +;a \TeX\ package \gstr\ manual and
+ many more (\cstr)!
+
+\beginlinemode
+ S Pan
+ UNE, Arimdale
+
+ T Ribbons
+ UMIST, Manchester
+\endlinemode
+
+\beginpilemode
+
+ C Anderson;42nd Street;USA+Christine;your service invoice!
+
+ D Holmes;Flat \#2, Finneybank Rd;London+David;the tax receipt;%
+ 071-902 7799!
+
+\endpilemode
+
+\begindatamode{3} % strictly 3 lines for one letter
+data-#1
+data-#2
+data-#3
+data-#4
+data-#5
+\enddatamode
+
+\ifISLATEX \firstread{\global\textwidth=6in}
+\else \firstread{\hsize=6in}\fi % make labels double columns
+
+\labelsquit{}
+\end{document} % redundant
+\endfile
+
+
+
+\message{Now go and TeX or LaTeX <example1.tex> and <example2.tex>}%
+
+
+\end{document}
+%
+%
+%
+%ENDDOCUMENT
+
+
+
diff --git a/macros/generic/formlett/user_manual.pdf b/macros/generic/formlett/user_manual.pdf
new file mode 100644
index 0000000000..e23ef4bd2b
--- /dev/null
+++ b/macros/generic/formlett/user_manual.pdf
Binary files differ
diff --git a/macros/generic/formlett/user_manual.tex b/macros/generic/formlett/user_manual.tex
new file mode 100644
index 0000000000..b317848477
--- /dev/null
+++ b/macros/generic/formlett/user_manual.tex
@@ -0,0 +1,1113 @@
+% USER MANUAL in Plain TeX
+
+\input formlett.sty
+
+% FONTS
+\font\hbold=cmbx10 at 17.28pt
+\font\lbold=cmbx10 at 14.4pt
+\font\bbold=cmbx10 at 12pt
+\font\small=cmr8
+\font\tiny=cmr5
+\font\stt=cmtt9
+\catcode`\@=11\relax
+%
+%
+%
+% OTHER MACROS
+%
+\catcode`\~=11\relax \def\t{{\tt ~}}
+\catcode`\~=\active\relax
+\catcode`\!=0\relax !catcode`!\=11!relax
+!def!esc{\}!def!escs{\! }
+!catcode`!\=0!relax \catcode`\!=12\relax
+\def\rqs{\rq\ }
+\def\LaTeX{{\rm L\kern-.36em\raise.3ex\hbox{\font\sc=cmcsc10\sc a}\kern-.15em
+ T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
+
+% makeshift macro
+\catcode`\^^M=13\relax%
+\def\setraw{\bgroup\rm@ligature\set@space\set@tab%
+\set@cr\stt\raw@chars[11][13][13][13][13]\def^^M{\strut\par}\setraw@@}%
+\edef\temp@macro{%
+ \noexpand\long\noexpand\def\noexpand\setraw@@\noexpand##1^^M##2%
+ \esc@ unsetraw{##1##2\noexpand\egroup}}\temp@macro %
+\catcode`\^^M=5\relax%
+
+
+\font\ninerm=cmr9 \font\eightrm=cmr8
+\font\ninei=cmmi9 \font\eighti=cmmi8
+\font\ninesy=cmsy9 \font\eightsy=cmsy8
+\font\ninebf=cmbx9 \font\eightbf=cmbx8
+\font\ninett=cmtt9 \font\eighttt=cmtt8
+\font\nineit=cmti9 \font\eightit=cmti8
+\font\ninesl=cmsl9 \font\eightsl=cmsl8
+
+\font\sixrm=cmr6
+\font\sixi=cmmi6
+\font\sixsy=cmsy6
+\font\sixbf=cmbx6
+
+\skewchar\ninei='177 \skewchar\eighti='177 \skewchar\sixi='177
+\skewchar\ninesy='60 \skewchar\eightsy='60 \skewchar\sixsy='60
+\hyphenchar\ninett=-1 \hyphenchar\eighttt=-1 \hyphenchar\tentt=-1
+
+\font\tentex=cmtex10
+\font\inchhigh=cminch
+\font\titlefont=cmssdc10 at 40pt % titles in chapter openings
+\font\eightss=cmssq8 % quotations in chapter closings
+\font\eightssi=cmssqi8 % ditto, slanted
+\font\tenu=cmu10 % unslanted te~t italic
+\font\manual=manfnt % METAFONT logo and special symbols
+\font\magnifiedfiverm=cmr5 at 10pt % to demonstrate magnification
+
+\newskip\ttglue
+\def\eightpoint{\def\rm{\fam0\eightrm}% switch to 8-point type
+ \textfont0=\eightrm \scriptfont0=\sixrm \scriptscriptfont0=\fiverm
+ \textfont1=\eighti \scriptfont1=\sixi \scriptscriptfont1=\fivei
+ \textfont2=\eightsy \scriptfont2=\sixsy \scriptscriptfont2=\fivesy
+ \textfont3=\tenex \scriptfont3=\tenex \scriptscriptfont3=\tenex
+ \textfont\itfam=\eightit \def\it{\fam\itfam\eightit}%
+ \textfont\slfam=\eightsl \def\sl{\fam\slfam\eightsl}%
+ \textfont\ttfam=\eighttt \def\tt{\fam\ttfam\eighttt}%
+ \textfont\bffam=\eightbf \scriptfont\bffam=\sixbf
+ \scriptscriptfont\bffam=\fivebf \def\bf{\fam\bffam\eightbf}%,
+ \tt \ttglue=.5em plus.25em minus.15em
+ \normalbaselineskip=9pt
+ \setbox\strutbox=\hbox{\vrule height7pt depth2pt width0pt}%
+ \let\sc=\sixrm \let\big=\eightbig \normalbaselines\rm}
+
+
+%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%
+%
+% END OF EXTRA MACROS AND FONTS
+%
+%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%
+
+
+
+
+\catcode`\@=11\relax
+\PAGENO=1
+\voffset=-0.3in
+
+
+\ifx\pageno\undefined
+\errmessage{Please run TeX if you want this article on how to use
+<formlett.sty> to be processed as well!}
+\fi
+
+
+\parindent=0pt
+\hsize=469.75499pt % the default
+\vsize=9.6in %8.83in
+
+\def\makefootline{\baselineskip=24pt \line{\the\footline}}
+\footline={\lower5pt
+\hbox to \hsize
+ {{\tenrm Jiang Z ~~~{\tensl Mail merge with the use of formlett.sty}
+\hss \folio}}}
+
+\leftline{\hbold Mail merge with the use of formlett.sty}
+\bigskip
+
+
+{\advance\leftskip by13mm \overfullrule=0pt
+\advance\rightskip by 20mm %28mm
+\sl
+\noindent Zhuhan JIANG\par
+\noindent School of Computing and Information Technology,
+ University of Western Sydney, Victoria Road, Parramatta NSW 2150, Australia.
+{\sl ~~Email}:~z.jiang@uws.edu.au\par
+\medskip
+\rm\smooth
+\noindent (Last updated on 26 May 2003)\par
+\medskip
+
+\noindent
+In this article, the author explains how to use a form-letter or mail
+merge style {\tt formlett.sty}, designed for plain \TeX\space and
+\LaTeX\space or \LaTeX2e. {\tt formlett.sty} supports different
+parameter input methods, parameter naming and defaulting mechanism, as
+well as facilities for previewing parameter positions and printing
+labels. It is written for the purpose of being powerful, robust and
+above all easy to use.\par }
+
+
+\begincolumns
+
+{\lbold Introduction}
+
+\smallskip
+
+Our purpose here is to describe a comprehensive implementation of a
+macro system, handling form letters or mail merge under plain \TeX\space
+or \LaTeX\space2.09 or \LaTeX2e. The main objective is to provide an
+easy way to output many form letters with their own parameters, with or
+without the use of multiple files. There will be a coherent and simple
+format for putting parameters inside a form letter, with a number of
+helping facilities for such as naming parameters and previewing their
+positions. A minimum support for printing mailing labels is also
+provided.
+
+
+\medskip
+
+The concept of macros [1] for form letters is not new: there already
+exist macros in this connection such as {\tt merge}, {\tt textmerg} and
+{\tt address} to name a few, see [2,3] for further details. Our stress
+here is therefore laid on the ease to use, along with the power and the
+robustness of the macros.
+
+\bigskip
+
+
+{\lbold Basic format}
+
+
+%%%%%%%%%%%%
+% letter top
+%%%%%%%%%%%%
+
+ \beginletter
+\sl
+\hsize=3.1in\relax
+\medskip
+ \paranames % optional
+ \tt<<FULL NAME>>;%
+ \tt<<ADDRESS-01>>;%
+ \tt<<ADDRESS-02>>;%
+ \tt<<GIVEN NAME>>;%
+ \tt<<MISSING ITEM>>;%
+ \tt<<PHONE NUMBER>>!
+ \loaddefaultparas % optional
+
+ \NOPAGENUMBERS\parindent=0pt\overfullrule=0pt
+ \paras[1]\par\paras[2]\par\paras[3]\par\medskip
+
+ Dear \paras[4],
+
+ \smallskip
+ We have been looking for
+ \paras[5] for quite a while
+ without any luck, could you help
+ us out? If so, please ring
+ \paras[6]. \par\medskip
+ Cheers!\hfill Michael\par %\vfill\eject
+\medskip
+ \endletter
+
+%%%%%%%%%%%%
+% letter end
+%%%%%%%%%%%%
+
+
+Suppose we would like to write a form letter for mail merge in the
+following form
+
+\showparas
+
+where the text inside the double arrow brackets are to be replaced by
+the parameters specific to each individual letter. If we number these
+parameters one by one in a single group, then the letter template will
+be organised as
+
+\preview
+
+and we need just 6 parameters to personalise an individual letter. A
+simplest example of supplying a set or a {\sl cluster} of these
+parameters to output a merged form letter is to use
+
+\setraw
+\moreletter
+ Mrs L Stenson;\#1-20 Sunset Street;%
+ Hills, Norway;Louise;a Bible;220-8888!
+\unsetraw
+
+For more letters to be merged this way, just use again the
+command {\tt\string\moreletter} in the above format, in which each
+parameter is separated by a semicolon `{\tt ;}' and the whole parameter
+cluster is ended by an exclamation mark `{\tt !}'. The actual code in
+\LaTeX\space for making the above form letter, along with an extra
+merged letter, may read as follows
+
+
+\edef\setrawcount{\stt\noexpand
+ \beginrawlist[][][4][][][3.3in]{\esc@ unsetraw}}
+
+\linecount=1\relax
+\setrawcount
+ \documentstyle[formlett]{article}
+ \begin{document}
+ \beginletter
+ \NOPAGENUMBERS\parindent=0pt
+ \paras[1]\par\paras[2]\par
+ \paras[3]\par\medskip
+ Dear \paras[4], \par\medskip
+ We have been looking for
+ \paras[5] for quite a while
+ without any luck, could you help
+ us out? If so, please ring
+ \paras[6]. \par\medskip
+ Cheers!\hfill Michael\vfill\eject
+ \endletter
+
+ \moreletter % letter one
+ Mrs L Stenson;\#1-20 Sunset Street;%
+ Hills, Norway;Louise;a Bible;220-8888!
+ \moreletter % letter two
+ S Wales;UMIST;Manchester;Sir or Madam;%
+ a \TeX\ package{+}manual;225-9905!
+ \end{document}
+\unsetraw
+\rm
+
+The line numbers in the above and later on are for quick reference only:
+they are not a part of the program code. The letter template in lines
+4-13 is defined by the {\tt\string\beginletter} and {\tt\string\endletter}
+pair in line 3 and line 14, with each use of {\tt\string\moreletter}
+generating a new merged letter. We note that command {\tt \string\paras[{\it
+m}]} represents the $m^{th}$ merged parameter (of the first group, see
+later), and the command {\tt\string\NOPAGENUMBERS}
+will remove the page numbering for both \LaTeX\space and plain
+\TeX. We also note that if one replaces lines 1-2 by
+{\tt\string\input\space formlett.sty}, then the program will be
+compilable under plain \TeX\space as well.
+
+
+\medskip
+
+Although the mail merge mechanism in the above will be sufficient for
+most simple applications, {\tt formlett} provides in fact many more
+features. We shall thus in the followings introduce the main features
+one by one, from the most useful to the less likely encountered.
+
+\medskip
+
+To start with, we notice that in the above example there are exactly two
+parameters to be used for the address. This is inconvenient to say the
+least, even if we allocate say three more extra parameters for the
+purpose. This naturally calls for the separation of the whole {\sl
+cluster} of parameters into several {\sl groups}, so that the numbering
+of the parameters in every group will be resynchronised. We thus use
+{\tt\string\paras[{\it m}][{\it n}]} to denote the $m^{th}$ parameter of
+the $n^{th}$ group of a whole cluster of merging parameters. In fact we
+may use {\tt\string\blockparas[{\it m}][{\it n}][{\it pre}][{\it post}]}
+to represent parameters in the $n^{th}$ group, from the $m^{th}$ to the
+last parameter of that group, where the tokens denoted by {\it pre} and
+{\it post} are those to be added in front and behind respectively each
+of the legitimate parameters. The defaults for {\it pre} and {\it post}
+are {\tt\string\noindent} and {\tt\string\par} respectively. It is
+therefore more sensible to specify the merging parameters of the earlier
+example via
+
+
+%%%%%%%%%%%%
+% letter top
+%%%%%%%%%%%%
+
+ \beginletter
+\sl
+\hsize=3.1in\relax
+\medskip
+ \paranames % optional
+ \tt<<FULL NAME>>\hfill
+ \tiny\fillzeros[4]\linecount\global\advance\linecount1\relax\par;%
+ \tt<<ADDRESS-etc>>\hfill
+ \tiny\fillzeros[4]\linecount\global\advance\linecount1\relax\par;%
+ +\tt<<GIVEN NAME>>;%
+ \tt<<MISSING ITEM>>;%
+ \tt<<PHONE NUMBER>>!
+ \loaddefaultparas % optional
+
+ \NOPAGENUMBERS\parindent=0pt\overfullrule=0pt
+ \noindent{\it\paras[1]}\par
+ \blockparas[2]\par\medskip
+
+ Dear \paras[1][2],
+
+ \smallskip
+ We have been looking for
+ \paras[2][2] for quite a while
+ without any luck, could you help
+ us out? If so, please ring
+ \paras[3][2]. \par\medskip
+ Cheers!\hfill Michael\par %\vfill\eject
+\medskip
+ \endletter
+
+%%%%%%%%%%%%
+% letter end
+%%%%%%%%%%%%
+
+\showparas
+
+where {\tt <<ADDRESS-etc>>} will be produced by
+{\tt\string\blockparas[2][1]}, i.e. all the parameters of the first
+group, starting from the 2nd parameter. We note that the missing
+square-bracketed macro parameters for {\tt\string\blockparas} are
+automatically provided: in fact macro parameters in {\tt formlett} are
+systematically defaulted. Hence for example, {\tt \string\paras[1][1]}
+is equivalent to any of the following commands
+
+\setraw
+ \paras, \paras[1], \paras[][1],
+ \paras[1][], \paras[][]
+\unsetraw
+
+As for the more precise position of the merging parameters, they can
+always be viewed via the command {\tt\string\preview}, which in this
+case gives the following positioning
+
+\preview
+
+This way, the mail merge for the above letter template can also be done
+(in plain \TeX) in the following more flexible way
+
+\setrawcount
+ \input formlett.sty
+ \beginletter
+ \NOPAGENUMBERS\parindent=0pt
+ \noindent{\it\paras[1]}\par
+ \blockparas[2]\par\bigskip
+ Dear \paras[1][2],\par\medskip
+ We have been looking for
+ \paras[2][2] for quite a while
+ without any luck, could you help
+ us out? If so, please ring
+ \paras[3][2]. \par\medskip
+ Cheers!\hfill Michael\vfill\eject
+ \endletter \preview
+
+ \beginpilemode
+ Mrs L Stenson;\#1-20 Sunset Street
+ Hills, Norway+Louise;a Bible;220-8888!
+
+ S Wales;UMIST;Manchester+%
+ Sir or Madam;a \TeX\space
+ package{+}manual;225-9905!
+ \endpilemode
+ \end
+\unsetraw
+\rm
+
+
+We note that by default we used plus sign `{\tt +}' to separate
+different groups inside a cluster of parameters, and each cluster inside
+a {\tt\string\beginpilemode} and {\tt\string\endpilemode} pair will
+output a merged letter, as if it were produced by command
+{\tt\string\moreletter} followed by that cluster of parameters.
+The output of the first merged letter in fact reads
+
+\moreletter
+ Mrs L Stenson;\#1-20 Sunset Street
+ Hills, Norway+Louise;a Bible;220-8888!
+
+
+\medskip
+
+It is often desirable to supply parameters line by line, i.e. one line
+as one parameter. Hence the two merged letters produced by lines 25-47
+can also be made by replacing the content included in the
+{\tt\string\beginpilemode} and {\tt\string\endpilemode} pair (lines
+39-46) by the following new code
+
+\setrawcount
+\blockmarks
+\beginblockmode
+Mrs L Stenson
+\#1-20 Sunset Street
+Hills, Norway
+-----
+Louise
+a Bible
+220-8888
+======
+
+S Wales
+UMIST
+Manchester
+----
+Sir or Madam
+a \TeX\ package+manual
+225-9905
+====
+\endblockmode
+\defaultmarks
+\unsetraw
+\rm
+
+where obviously we have used lines with `{\tt----}' to separate groups
+and used lines with `{\tt====}' to end a cluster of parameters. This was
+done by the use of {\tt\string\blockmarks} which changes the group
+delimiter `{\tt +}' and cluster delimiter `{\tt !}' into the above two
+new ones, with the {\tt\string\defaultmarks} at the end setting them
+back. If the whole cluster of parameters are categorised into a single
+(first) group, then we may even use a block of consecutive nonempty
+lines to provide the merging parameters. This is done by the use of
+command pair {\tt\string\beginlinemode} and {\tt\string\endlinemode}.
+Hence we may also conduct the above mail merge in for instance \LaTeX2e
+by
+
+
+\setrawcount
+\documentclass{article}
+\usepackage{formlett}
+\begin{document}
+ \beginletter
+ \NOPAGENUMBERS\parindent=0pt
+ \paras[4]\par\blockparas[5]
+ \par\medskip
+ Dear \paras[1], \par\medskip
+ We have been looking for
+ \paras[2] for quite a while
+ without any luck, could you help
+ us out? If so, please ring
+ \paras[3]. \par\medskip
+ Cheers!\hfill Michael\vfill\eject
+ \endletter
+
+\beginlinemode
+Louise
+a Bible
+220-8888
+Mrs L Stenson
+\#1-20 Sunset Street
+Hills, Norway
+
+Sir or Madam
+a \TeX\ package+manual
+225-9905
+S Wales
+UMIST
+Manchester
+\endlinemode
+\end{document}
+\unsetraw
+\rm
+
+Notice that we have changed the numbering order of the parameters so
+that the number of address lines output by {\tt\string\blockparas} is
+more flexible.
+
+
+\bigskip
+{\lbold Advanced features}
+
+The advanced features to be discussed below are mainly for the purpose
+of (i) writing {\sl long} form letter; (ii) making {\sl many} different
+form letters; (iii) reading mail merge parameters that are in {\sl
+crude} ASCII form; and (iv) generating mail labels.
+
+\medskip
+
+It is in general better to keep the letter template, i.e. the content
+between {\tt\string\beginletter} and {\tt\string\endletter} like those
+in lines 4-13, in a separate file, say {\tt myletter.let}, and use
+{\tt\string\inputletter$\{$myletter.let$\}$} to load in the letter
+template. The advantage of this over the previously used method is that
+the letter template can now be arbitrarily large without any risks of
+causing computer memory problem.
+
+\medskip
+
+Suppose we have a collection of letter templates, we may wish to remind
+ourselves what each parameter represents. For this purpose, we may add
+at the top of the letter template a command {\tt\string\paranames} {\it
+cluster}{\tt !}, where {\it cluster} is a cluster of parameters each
+giving a name to the corresponding parameter. Command
+{\tt\string\paranames} takes its macro parameters in the same way
+{\tt\string\moreletter} does. After a letter template is read in,
+command {\tt\string\showparas} will output a form letter with its
+parameters replaced by the corresponding names. The mainly italic
+passage containing lines 23-24, for instance, is the output of
+{\tt\string\showparas} for the letter template in lines 102-109 given
+explicitly later on.
+
+\medskip
+
+We may also use {\tt\string\paradefaults} {\it cluster}{\tt !} to
+provide default parameters, i.e. the parameters to replace the empty or
+not entered ones, and use {\tt\string \loaddefaultparas} inside letter
+template to activate the parameter defaulting. We note that in general
+commands {\tt\string\paranames} and {\tt\string\loaddefaultparas}, if
+present, should be at the top of the letter template, with
+{\tt\string\loaddefaultparas} below the command {\tt\string\paranames}.
+Hence for our previous mail merge, we may re-do it via
+
+
+\setrawcount
+ \input formlett.sty
+ \beginletter
+ \paranames % optional
+ \tt<<FULL NAME>>;\tt<<ADDRESS-etc>>;%
+ +\tt<<GIVEN NAME>>;\tt<<MISSING ITEM>>;%
+ \tt<<PHONE NUMBER>>!
+ \loaddefaultparas % optional
+\unsetraw
+
+\ \ \ {\it $\{$letter details given in lines 27-36$\}$}
+\hfill{\tiny\fillzeros[4]\linecount\global\advance\linecount1\relax}
+
+\setrawcount
+ \endletter
+ \preview \showparas
+
+ \paradefaults % optional
+ To whom this may concern
+ +Sir or Madam;something;%
+ 061-225-9905!
+
+\blockmarks
+\beginrawblockmode{}
+Mrs L Stenson
+#1-20 Sunset Street
+Hills, Norway
+------
+Louise
+a Bible
+220-8888
+=========
+
+......
+
+Above empty line active
+\endrawblockmode
+\defaultmarks
+\end{document}
+\unsetraw
+\rm
+
+We note that in {\sl blockmode} with {\tt\string\blockmarks}, a line
+with `{\tt ....}' marks the immediate start of a parameter block,
+whether or not the lines immediately following it are empty or not. Also
+that in {\it rawblockmode} enclosed by {\tt\string \beginrawblockmode}
+and {\tt\string\endrawblockmode}, all characters are input in their
+original ASCII form. In other words, the special characters for
+\TeX\space will be ignored here.
+
+\medskip
+
+If the merging parameters are given by exactly $m$ lines per cluster, as
+is often the case when they are produced by a database utility, then we
+may use the {\tt\string\begindatamode} and {\tt\string\enddatamode} pair
+to mark the beginning and the end of the merging parameters. For more
+details, see the Appendix at the end.
+
+\medskip
+
+We may keep the letter template and the merging parameters in two
+separate files. For instance, if we save lines 103-108 to file {\tt
+myletter.let}, lines 39-46 or lines 48-68 to file {\tt myletter.adr},
+then we can produce via \LaTeX\ the mail merge by
+
+\setrawcount
+ \documentstyle[formlett]{article}
+ \begin{document}
+ \inputletter{myletter.let}
+ \showparas \preview % utility demo
+ \paradefaults To whom it may concern!
+ \inputfile{myletter.adr}
+ \beginlabels % 1st group as address
+ \inputfile{myletter.adr} % for labels
+ \endlabels
+ \end{document}
+\unsetraw
+\rm
+
+where the lines 140-142 will generate the address labels using the first
+group (as is intended here) of parameters. More precise format of
+{\tt\string\beginlabels} and etc can be found in the Appendix.
+
+\medskip
+
+Another way of making labels, if no separate files for the parameters
+are present, is to re-read the document itself and make labels instead
+of merged form letters in the second reading. We may thus use {\tt
+\string\input \ formlett.sty \string\initstyle\ [{\it styles}]$\{${\tt
+article}$\}\{${\it preamble}$\}$} to replace {\tt \string\documentstyle\
+[formlett, {\it styles}]$\{$article$\}$ {\it preamble}
+\string\begin$\{$document$\}$}, which will be valid for \LaTeX\ but
+ignored for \TeX\ , and will enable one to use {\tt \string\labelsquit}
+at the end to read in the current document again with all the letters
+there converted into the corresponding labels. Though
+{\tt\string\initstyle} is valid for plain \TeX, \LaTeX2.09 as well as
+\LaTeX2e, {\tt\string\initclass} will generate
+{\tt\string\documentclass} instead of {\tt\string\documentstyle} when
+\LaTeX2e is the processing environment. If you only want to execute
+certain commands the first time round (i.e. before {\tt
+\string\labelsquit} re-reads the file again), use {\tt
+\string\firstread$\{${\it commands}$\}$} for this purpose. For more
+detailed use and examples, read the {\sl programmer's document} attached
+to the style file {\tt formlett.sty} and the example files it generates.
+In fact, many details and extra features that are not contained in this
+article may be found there.
+
+\medskip
+
+We already noted that if a form letter is large, we have to use
+{\tt\string\inputletter} to load in the template. However, it is often
+still desirable to keep everything inside a single file, while allowing
+it to make new (scratch) files when it is being compiled. We may thus
+use for example
+
+\setraw
+ \beginfile{myletter.let}
+\unsetraw
+
+\ \ \ {\it $\{$letter template of lines 103-108$\}$}
+
+\setraw
+ \endfile
+\unsetraw
+\rm
+
+to create a letter template file {\tt myletter.let}. Likewise, the
+merging parameters can be saved to another run-time created file {\tt
+myletter.adr}.
+
+
+\medskip
+
+We have so far only used the default delimiters `{\tt ;}', `{\tt +}' and
+`{\tt !}' to separate single, group and cluster of parameters, with
+temporary change via {\tt\string\blockmarks} to `{\tt ....}', `{\tt
+----}' and `{\tt ====}' respectively. However we may change the
+delimiters to any characters by {\tt
+\string\delimiters$\{S\}\{G\}\{C\}$}, where $S$, $G$ and $C$ are the
+tokens to delimit single, group and cluster of parameters respectively,
+and change the delimiters back to the default by
+{\tt\string\defaultmarks} or equivalently by
+{\tt\string\delimiters$\{$;$\}\{$+$\}\{$!$\}$}.
+
+\medskip
+
+
+To conclude this section, let us finally look below at an `ideal' and
+`finished' mail merge application code,. It is currently in a form
+compilable under \LaTeX2e, and is also valid for plain \TeX\space if the
+first three lines (lines 144-146) are removed.
+
+\setrawcount
+\documentclass{article}
+\usepackage{formlett} % LaTeX2e
+\begin{document}
+
+%%%% MAKE file scr@tch@.let
+\beginfile{scr@tch@.let} % letter content
+\paranames <<name>>;<<address>>+<<items>>!
+\loaddefaultparas
+\parindent=0pt\blockparas\bigskip\bigskip
+Dear \paras, \par\bigskip
+This part is typically the letter content.
+It now displays all the items in the 2nd
+parameter group. They are \par
+\blockparas[][2] \vfill\eject
+\endfile
+
+%%%% MAKE file scr@tch@.adr
+\beginfile{scr@tch@.adr} % address file
+\blockmarks
+\beginblockmode
+T Teng
+UMIST
+Manchester M60 1QD
+=====
+
+Z Jiang
+UNE
+Armidale NSW 2351
+Australia
+------
+Email: zhuhan@neumann.une.edu.au
+=====
+\endblockmode
+\defaultmarks
+\endfile
+
+% MAIN BODY
+\paradefaults To Whom It May Concern
+ +No further info available{!}!
+\inputletter{scr@tch@.let}
+\inputfile{scr@tch@.adr}% for letters
+\beginlabels
+\inputfile{scr@tch@.adr}% for labels
+\endlabels
+\end{document}
+\unsetraw
+\rm
+
+We note that if we replace lines 144-146 by {\tt\string\input\space
+formlett.sty \string\initstyle$\{\}\{\}$}, then the mail merge can be
+processed by either plain \TeX\space or \LaTeX\space (including
+\LaTeX2e). It is likewise if {\tt\string\initstyle} in the replaced
+line is replaced furthermore by {\tt\string\initclass}, except that now
+the native \LaTeX2e environment is preserved, when applicable, rather
+than turning it into the compatibility mode of \LaTeX2.09.
+
+\bigskip
+{\lbold Programmer's tips}
+
+\smallskip
+
+First we note that all the macro parameters that are to appear inside
+square brackets of {\tt formlett}'s commands are defaulted, just like
+how {\tt\string\paras[$m$][$n$]} is defaulted earlier on. The actual
+default values can be found in the Appendix.
+
+\medskip
+
+For those wizard users who want to do everything their own way, we point
+out that if for instance the 3rd letter parameter of the 2nd group of a
+cluster is given as {\tt<A>}, then {\tt \string\LET2*3\t} will contain
+{\tt \string\b@group \string\relax {\tt<A>}\string\e@group} right after
+a cluster is read in. {\tt \string\DEF2*3\string~}, on the other hand,
+contains the corresponding default parameter in the same fashion.
+Furthermore, the command {\tt\string\checkparas[$m$][$n$]$\{$LET$\}$}
+will copy the content of {\tt\string\paras[$m$][$n$]}, minus the
+`wrapping' extra tokens {\tt\string\b@group\string\relax} and
+{\tt\string\e@group}, to {\tt\string\cachedata} and set
+{\tt\string\ifemptyparas} to true or false depending on whether the
+content is empty or not. This way, a user may even change the
+characteristics of his letter template by first testing the content of
+the supplied individual parameters. However, we note that if {\tt\string
+\loaddefaultparas} is executed, then the {\tt LET} array, when some of
+its elements are not supplied, will contain the corresponding elements
+of the {\tt DEF} array. Hence care must be exercised under such
+circumstances, when interpreting the {\tt\string\cachedata} generated by
+{\tt\string\checkparas[$m$][$n$]$\{$LET$\}$}. If necessary, we may use
+{\tt\string\delparadefaults} to delete current default parameter array
+{\tt DEF} so as to conduct {\tt\string\checkparas$\{$LET$\}$} more
+precisely.
+
+\medskip
+
+There are also a number of generic macro utilities in {\tt formlett},
+including a user stack and a multi-dimensional array mechanism.
+
+\medskip
+
+{\tt formlett} was written for all \TeX\space dialects, its format is
+thus more close to that of plain \TeX. In fact, we deliberately avoided
+mixing up {\tt formlett} with the standard letter environment of \LaTeX.
+This is largely due to the fact that the limited facilities of
+\LaTeX\space letter environment are easy to come by anyway, and are not
+really worth writing buckled code to make {\tt formlett} a type of
+extension of the environment. Nevertheless, one can still use the letter
+environment of \LaTeX\space inside the form letter template. Besides,
+the applicability of {\tt formlett} is not restricted for making form
+{\sl letters}; it can also be used to merge other type of articles or
+passages.
+
+
+
+
+\bigskip
+{\lbold References}
+
+\smallskip
+{\parindent=2em
+\item{[1].} Knuth D E, {\sl The \TeX book}, Reading, Mass.,
+Addison-Wesley, 1992. \par
+\item{[2].} Piff M, Text merges in \TeX\ and \LaTeX, {\sl TUGboad},
+13(4):518, 1993. \par
+\item{[3].} Damrau J and Wester M, Form letters with 3-across
+labels capacity, {\sl TUGboat}, 13(4):510, 1991.
+\par
+}
+
+
+
+
+\penalty -50\bigskip
+
+{\lbold Appendix}
+
+
+
+\smallskip
+
+
+In the followings, we give a brief summary of the main commands given by
+{\tt formlett} version 2.1.
+
+\medskip
+
+Let $m$ and $n$ be numbers, $p$, $q$ and $r$ be dimensions, $A$,
+$B$, $S$, $G$, $C$ and $T$ be tokens, and $X$ be a box.
+Furthermore, we shall denote by $R$ a full set of letter
+parameters ended by \lq{\tt !}\rq, with \lq{\tt;}\rqs separating
+parameters inside a same group and \lq{\tt+}\rqs separating
+different parameter groups. We moreover denote $R$ by $F$, when
+\lq{\tt ; + !}\rqs there can be replaced by \lq$S$ $G$ $C$\rqs
+respectively if {\tt \string\delimiters$\{S\}\{G\}\{C\}$} is
+issued. In the commands tabulated below, the macro parameters
+contained in squared brackets support default. In particular, the
+defaults are $m$={\tt 1}, $n$={\tt 1}, $p$={\tt 8truecm},
+$q$={\tt 1.5em}, $r$={\tt 3pt}, $A$={\tt\string\noindent} and
+$B$={\tt\string\par}.
+
+
+
+\newdimen\tempdimone
+\newdimen\tempdimtwo
+\tempdimone=\hsize
+\advance\tempdimone by-0.2pt
+\tempdimtwo=\hsize
+\advance\tempdimtwo by-1.8in
+\def\hruler{\hrule width \tempdimone}
+\long\def\entry#1#2{%
+\par\hbox to \tempdimone{\noindent
+ \vrule~\textbox[1.7in]{#1}~\hss
+ \vrule~\textbox[\tempdimtwo]{\raggedright#2}~\vrule}%
+ \par}
+
+\long\def\longentry#1#2#3{%
+\par\hbox to \tempdimone{\noindent
+ \vrule~\textbox[3in]{#1}~\hss~\vrule}\par
+ {\kern-8pt \advance\tempdimtwo0.10in
+ \vrule width1.7in height0pt \vrule width\tempdimtwo height 0.4pt \par
+ \kern-3pt}
+ \entry{#2}{#3}}
+
+\long\def\Longentry#1#2#3{%
+\par\hbox to \tempdimone{\noindent
+ \vrule~\textbox[3in]{#1}~\hss~\vrule}\par
+ {\advance\tempdimtwo0.08in\kern-1pt
+ \vrule~\hfill\vrule width \tempdimtwo height 0.4pt \vrule\par
+ \kern-2.5pt}%
+ \entry{#2}{#3}}
+
+
+
+\bigskip %\bigskip
+\penalty-1000 \vskip 0pt plus4in
+
+{\eightpoint
+\nointerlineskip\parskip=0pt
+
+\hruler
+\entry{{\tt\string\paras[$m$][$n$]}}%
+ {$m^{th}$ parameter of $n^{th}$ group }%
+
+\entry{{\tt\string\blockparas[$m$][$n$][$A$][$B$]}}%
+ {$m^{th}$ to the last parameter of $n^{th}$ group, each
+preceded by $A$ and followed by $B$, wrapped by $\{$\penalty
+1000$\}$ if
+$B$={\tt\string\relax}}
+
+\entry{{\tt\string\addressparas[$m$][$n$][$p$][$q$]}}%
+ {$m^{th}$ to the last parameter of $n^{th}$ group, each put
+into a box of width $p$ with indent $q$ for wrapped portions}
+
+
+\entry{{\tt\string\loaddefaultparas}}%
+ {fill empty parameters with defaults}
+
+%\hruler \penalty-1000
+\hruler
+
+
+\entry{{\tt\string\checkparas[$m$][$n$]$\{T\}$}}%
+ {$m^{th}$ parameter of $n^{th}$ group copied to {\tt\string\cachedata};
+ {\tt\string\ifemptyparas} is true if element is empty; $T$ is often
+ {\tt LET} or {\tt DEF}}%
+
+
+\hruler
+
+
+\entry{{\tt\string\moreletter\ $F$}}%
+ {use parameters $F$ to output a new letter}
+
+
+\entry{{\tt\string\paranames\ $R$}}%
+ {use $R$ as parameter names}
+
+\entry{{\tt\string\paradefaults\ $R$}}%
+ {use $R$ as default parameters}
+
+\entry{{\tt\string\delparadefaults}}%
+ {delete default parameters}
+
+\hruler
+
+
+\entry{{\tt\string\delimiters$\{S\}\{G\}\{C\}$}}%
+ {use $S$, $G$, $C$ as delimiters}
+
+
+\entry{{\tt\string\defaultmarks}}%
+ {use \lq{\tt ; + !}\rqs as delimiters}
+
+
+\entry{{\tt\string\blockmarks}}%
+ {use \lq{\tt ....}\rq, \lq{\tt ----}\rq, \lq{\tt ====}\rqs as delimiters}
+
+%\hruler \penalty -1000
+\hruler
+
+\entry{{\tt\string\preview}}%
+ {highlight parameter positions}
+
+\entry{{\tt\string\showparas}}%
+ {display parameter names, if any}
+
+\hruler
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginfile[$T$]$\{{\it
+file.ext}\}$}\cr
+\hbox{\tt\string\endfile\ \ \ \ \ \ \ \ \ \ \ \ \ }\cr}\right.$\par
+ \ \ \ {\tiny }}%
+ {write text verbatim to file {\it file.ext} (empty implies {\tt
+scr@tch@.tex}), nonempty $T$ replaces {\tt
+\string\endfile} to mark last full line}
+
+
+
+\entry{{\tt\string\inputletter$\{file.ext\}$}}%
+ {input letter content}
+
+\entry{{\tt\string\inputfile$\{file.ext\}$}}%
+ {input $file.ext$}
+
+\hruler \penalty -5000 %\vskip0pt plus 1cm
+\hruler
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginletter}\cr
+\hbox{\tt\string\endletter~~}\cr}\right.$ }%
+ {delimiters for letter content (template)}
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginpilemode}\cr
+\hbox{\tt\string\endpilemode~~}\cr}\right.$ }%
+ {normal letter parameters cluster-wise}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginblockmode}\cr
+\hbox{\tt\string\endblockmode~~}\cr}\right.$ }%
+ {for line-by-line blocks of parameters, empty lines active
+within each cluster}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginlinemode}\cr
+\hbox{\tt\string\endlinemode~~}\cr}\right.$ }%
+ {for line-by-line parameters, empty lines delimit clusters}
+
+\hruler \penalty-1000
+%\hruler
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginrawblockmode$\{T\}$}\cr
+\hbox{\tt\string\endrawblockmode\ \ \ \ \ }\cr}\right.$ }%
+ {raw text mode; nonempty $T$ replaces {\tt\string\endrawblockmode}
+ to mark end}
+
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\beginrawlinemode$\{T\}$}\cr
+\hbox{\tt\string\endrawlinemode\ \ \ \ \ \ }\cr}\right.$ }%
+ {raw text parameters and active spaces etc}
+
+\entry{%
+$\left\{\matrix{ \hbox{\tt\string\begindatamode[$T$]$\{m\}$}\cr
+\hbox{\tt\string\enddatamode\ \ \ \ \ \ \ \ }\cr}\right.$ }%
+ {$m$ raw text lines for one form letter}
+
+
+%\hruler \penalty-2000
+\hruler
+
+
+\entry{{\tt\string\PAGENO=1}}%
+ {page number reset to 1}
+
+
+\entry{{\tt\string\NOPAGENUMBERS}}%
+ {no page numbers}
+
+
+\entry{{\tt\string\textbox[$p$]$\{text\}$}}%
+ {$text$ into box of width $p$}
+
+
+\entry{{\tt\string\boxmore[$r$]$\{X\}$}}%
+ {add borderline to box $X$ at a distance $r$}
+
+
+\entry{{\tt\string\addressbox[$p$][$q$]$\{text\}$}}%
+ {$text$ into box of width $p$, with wrapped options indented
+by $q$}
+
+
+\hruler
+
+\Longentry{%
+$\left\{\matrix{ \hbox{\tt\string\beginlabels
+ [$a$][$b$][$c$][$d$][$e$][$f$]}\cr
+ \hbox{\tt\string\endlabels\hskip3cm}\cr}\right.$ }%
+ {\strut\par{\sl defaults:}\everypar={\hbox{\ \ \ }}\par\par
+ $a$={\tt 20pt}, \par $b$={\tt\string\tt\string\raggedright},
+ \par $c$={\tt1}, $d$={\tt1}, \par
+ $e$={\tt2.6in}, $f$={\tt2em}}%
+ {form letters become labels: address taken from $c^{th}$ to
+last parameter of $d^{th}$ group, with width $e$, indent
+$f$, borderspace $a$ and font toks $b$}
+
+\hruler
+
+
+\entry{{\tt\string\firstread$\{T\}$}}%
+ {toks $T$ will not be read if the file is re-read via {\tt
+ \string\labelsquit}}
+
+
+\entry{{\tt\string\initstyle[$a$]$\{b\}\{c\}$}}%
+ {initiation for {\tt\string\labelsquit},with styles $a$,
+ documentstyle $b$ and preamble $c$}
+
+
+\entry{{\tt\string\initclass[$a$][$o$]$\{b\}\{c\}$}}%
+ {similar to {\tt\string\initstyle} ($o$ is \LaTeX2e options),
+ but retains native \LaTeX2e when applicable}
+
+
+\hruler \vskip0.5pt
+\Longentry{%
+$\matrix{\hbox{\tt \string\labelsquit
+ [$a$][$b$][$c$][$d$][$e$][$f$]$\{$\it file.ext$\}$}\cr
+ \hbox{}\cr}$}%
+ {\strut\par{\sl defaults:}\everypar={\hbox{\ \ \ }}\par\par
+ see that for {\tt\string\beginlabels}}
+ {quit after converting letters to labels by reading the current
+ document or {\it file.ext}}
+
+\hruler
+
+}
+
+\footline={\lower5pt
+\hbox to \hsize
+ {{\rm Jiang Z ~~~{\sl Mail merge with the use of formlett.sty}
+ \hss {\sl $\bullet$End of Document$\bullet$}
+\hss \folio}}}
+
+
+\vrule height2.9in width0pt depth0pt
+\endcolumns
+\vfill\eject
+
+
+
+\end{document}
+
+
+
+