% \ProvidesFile{envlab.dtx}[1996/07/15 v1.1 Envelopes and Labels] % \iffalse %% Copyright Boris Veytsman 1996 % \fi %% % \CheckSum{1057} %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} % \iffalse % % \section{Documentation driver} % % Nothing interesting here\dots % \begin{macrocode} %<*driver> \documentclass{ltxdoc} \DoNotIndex{\@Alph,\@alph,\@arabic,\@badmath} \DoNotIndex{\@centercr} \DoNotIndex{\@empty,\@ignoretrue} \DoNotIndex{\@ixpt} \DoNotIndex{\@M,\@minus,\@ne,\@plus} \DoNotIndex{\\,\addtolength} \DoNotIndex{\advance} \DoNotIndex{\ast,\begin,\begingroup,\bfseries,\bgroup,\box} \DoNotIndex{\bullet} \DoNotIndex{\cdot,\cr,\day,\DeclareOption} \DoNotIndex{\def,\DocInput,\documentclass} \DoNotIndex{\DoNotIndex,\egroup,\ifx,\else,\fi,\endtrivlist} \DoNotIndex{\EnableCrossrefs,\end,\end@dblfloat,\end@float,\endgroup} \DoNotIndex{\endlist,\everycr,\ExecuteOptions} \DoNotIndex{\filedate,\filename,\fileversion} \DoNotIndex{\global,\halign,\hangindent,\hbox,\hfil,\hfill,\hrule} \DoNotIndex{\hsize,\hskip,\hspace,\hss,\ifcase,\or,\fi} \DoNotIndex{\ifvmode,\fi,\ifnum,\fi,\input} \DoNotIndex{\kern,\leavevmode,\let,\leftmark} \DoNotIndex{\list,\llap,\long,\m@ne,\m@th,\mark} \DoNotIndex{\month,\newcommand,\newcounter,\newenvironment} \DoNotIndex{\NeedsTeXFormat,\newdimen} \DoNotIndex{\newpage,\nobreak,\noindent,\number} \DoNotIndex{\p@} \DoNotIndex{\pagestyle,\par} \DoNotIndex{\penalty,\PrintChanges,\PrintIndex,\ProcessOptions} \DoNotIndex{\protect,\ProvidesClass,\raggedbottom,\raggedright} \DoNotIndex{\refstepcounter,\relax,\renewcommand,\reset@font} \DoNotIndex{\rightmargin,\rlap,\rmfamily} \DoNotIndex{\setbox,\setcounter,\setlength} \DoNotIndex{\skip,\slshape,\space} \DoNotIndex{\trivlist,\typeout,\tw@} \DoNotIndex{\vskip,\vspace,\year,\z@} % \DoNotIndex{\@ptsize,\@sptoken,\addtocounter,\afterassignment} \DoNotIndex{\AtEndOfPackage,\baselineskip,\boxmaxdepth,\clearpage} \DoNotIndex{\clubpenalty,\csname,\CurrentOption,\DeclareRobustCommand} \DoNotIndex{\eject,\endcsname,\evensidemargin,\expandafter} \DoNotIndex{\footnotesize,\footskip,\fromaddress,\futurelet} \DoNotIndex{\headheight,\headsep,\hfuzz,\ignorespaces} \DoNotIndex{\InputIfFileExists,\large,\lineskip,\loop} \DoNotIndex{\MakeUppercase,\MessageBreak,\mbox,\multiply} \DoNotIndex{\newcount,\newif,\newlength,\newtoks,\nolinebreak} \DoNotIndex{\nopagebreak,\normalfont,\normalsize,\null,\newline} \DoNotIndex{\oddsidemargin,\PackageError,\PackageInfo} \DoNotIndex{\paperheight,\paperwidth,\parbox,\parindent} \DoNotIndex{\PassOptionsToPackage,\ProvidesPackage,\RequirePackage} \DoNotIndex{\rule,\selectfont,\sffamily,\sloppy,\small,\spaceskip} \DoNotIndex{\stepcounter,\textheight,\textwidth,\the,\topmargin} \DoNotIndex{\unhbox,\voidb@x,\vsize,\vfuzz,\widowpenalty,\xspaceskip} \usepackage{enumerate} \CodelineIndex \RecordChanges \EnableCrossrefs \begin{document} \DocInput{envlab.dtx} \end{document} % % \end{macrocode} % % \fi % % \changes{v0.9}{5/31/1996}{Beta version} % \changes{v0.91}{5/31/1996}{Added new option---"alwaysbarcodes"} % \changes{v1.0}{6/9/1996}{First released version} % \changes{v1.1}{07/08/1996}{Fixed typos in "elold.ins"} % \changes{v1.1}{07/08/1996}{Updated User Guide} % % \newcommand{\EL}{\textsl{EnvLab}} % % % \GetFileInfo{envlab.dtx} % % \title{Printing Envelopes and Labels in \LaTeXe: \EL\ Package % \thanks{This file % has version number \fileversion, last % revised \filedate.} % \thanks{\copyright Boris Veytsman, 1996} % } % \author{Boris Veytsman} % \date{\filedate} % \maketitle % % \tableofcontents % % % \section{Introduction} % \MakeShortVerb{\"} % The standard "\makelabels" command in the \LaTeXe\ "letter.cls" % documentclass typesets labels on Avery 5352 sheets. A typical user % may want more. \EL\ redefines "\makelabels" in\footnote{hopefully} % a more useful and customizable way % % The detailed usage of the package is described in the file % "elguide.tex". Here we just comment the macros. % % \StopEventually % % \section{Identification} % % First, we must say ``Hello world.'' % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{envlab}[1996/07/15 v1.1 Envelopes and Labels] % % \end{macrocode} % % \begin{macro}{\envlab@ok} % \begin{macro}{\envlab@oops} % Now let us check whether we in the letter documentclass. Actually we % will accept any class that has "\makelabels" defined (custom letter % classes, etc.) % \begin{macrocode} %<*package> \def\envlab@oops{% \PackageError{envlab}% {Envlab is used outside of \MessageBreak% a letter-compatible documentclass}% {You are trying to use Envelopes & Labels\MessageBreak% package, but your documentclass does not\MessageBreak% understand address formatting commands.\MessageBreak% Try standard document class letter\MessageBreak}} \def\envlab@ok{% \PackageInfo{envlab}% {Envelopes & Labels package: found makelabels...\MessageBreak% Seems everything is OK. Good luck.}} \expandafter\ifx\csname makelabels\endcsname \relax % \envlab@oops\else\envlab@ok\fi % % \end{macrocode} % \end{macro}\end{macro} % \section{Preliminary code} % % \subsection{Switches, etc.} % % % \DescribeMacro{\if@envelope} % First, we must say whether we want to print out envelopes (default) or labels. % The differences are: % \begin{itemize} % \item Envelopes are printed on separate pages, labels are printed % several per page % \item Envelopes might have return address, labels might not % \item Envelopes are rotated by default, labels are never rotated % \end{itemize} % \begin{macrocode} %<*package> \newif\if@envelope \@envelopetrue % % \end{macrocode} % % \DescribeMacro{\if@rotateenvelopes} % \DescribeMacro{\if@printreturnaddress} % Now we must determine whether we want to rotate envelopes and % whether to include return address (both yes by default). % \begin{macrocode} %<*package> \newif\if@rotateenvelopes \@rotateenvelopestrue \newif\if@printreturnaddress \@printreturnaddresstrue % % \end{macrocode} % % \DescribeMacro{\@envelopeposition} % Now let us decide how to print envelopes. They can be either centered % (default) \emph{or} shifted to the left or to the right of the paper % tray. The % counter "\@envelopeposition" can be, correspondingly, either 0 or 1 % or 2. The value of % 3 corresponds to the ``custom placing'', when the user sets % "\EnvelopeLeftMargin" manually. % % \begin{macrocode} %<*package> \newcount\@envelopeposition \@envelopeposition=0\relax % % \end{macrocode} % % \changes{v1.1}{7/8/96}{Added \cs{if@pswait}} % \DescribeMacro{\if@pswait} % The switch "\if@pswait" controls optional manual feeding of envelopes % and labels in \textsl{Postscript} printers (see Section~\ref{sec:Print} % for details). % \begin{macrocode} %<*package> \newif\if@pswait \@pswaitfalse % % \end{macrocode} % % \DescribeMacro{\if@barcodes} % \DescribeMacro{\if@alwaysbarcodes} % We can either print bar codes (default) or not. The second switch % forces to print barcodes even if they are not last in the address % (like "Pa 16801\\USA") % \begin{macrocode} %<*package> \newif\if@barcodes \newif\if@alwaysbarcodes \@barcodestrue \@alwaysbarcodesfalse % % \end{macrocode} % % % % % \DescribeMacro{\if@capitalizeaddress} % Also, we can either capitalize the address (default) or not. % \begin{macrocode} %<*package> \newif\if@capitalizeaddress \@capitalizeaddresstrue % % \end{macrocode} % % \subsection{Lengths and numbers} % % We want all lengths to be user settable, so no "@" in the names. % % % \DescribeMacro{\EnvelopeWidth} % \DescribeMacro{\EnvelopeHeight} % \DescribeMacro{\EnvelopeTopMargin} % \DescribeMacro{\EnvelopeLeftMargin} % An envelope has four basic lengths. % The first two are self-evident. The third is the distance between the % edge of the paper and the leading edge of the envelope. All % pre-defined envelope sizes set this to zero. The fourth is the distance % between the left edge of the paper and the envelope. Its value depends % on the value of the "\@envelopeposition" variable. We will preset it to % zero % \begin{macrocode} %<*package> \newlength{\EnvelopeWidth} \newlength{\EnvelopeHeight} \newlength{\EnvelopeTopMargin} \newlength{\EnvelopeLeftMargin} \setlength{\EnvelopeLeftMargin}{0pt} % % \end{macrocode} % % % \DescribeMacro{\LabelWidth} % \DescribeMacro{\LabelHeight} % \DescribeMacro{\LabelTopMargin} % \DescribeMacro{\LabelLeftMargin} % \DescribeMacro{\LabelRightMargin} % A label has more parameters. % The first two are the same as for the envelopes. The next two define the % distances from the paper edges to the beginning of the labels. The % last one describes the distance between the labels. % \begin{macrocode} %<*package> \newlength{\LabelWidth} \newlength{\LabelHeight} \newlength{\LabelTopMargin} \newlength{\LabelLeftMargin} \newlength{\LabelRightMargin} % % \end{macrocode} % % \DescribeMacro{LabelMaxCol} % \DescribeMacro{LabelMaxRow} % The following numbers define, how many labels are in each row and how % many rows are on each page % \begin{macrocode} %<*package> \newcounter{LabelMaxCol} \newcounter{LabelMaxRow} % % \end{macrocode} % % The lengths above are \emph{external} parameters that determine an % envelope or a label. Now we will describe \emph{internal} lengths. We % define them here because the commands "\SetEnvelope" and "\SetLabel" % determine them basing on the given envelope or label type. % % % \DescribeMacro{\FromAddressTopMargin} % \DescribeMacro{\FromAddressLeftMargin} % \DescribeMacro{\FromAddressHeight} % \DescribeMacro{\FromAddressWidth} % \DescribeMacro{\ToAddressTopMargin} % \DescribeMacro{\ToAddressLeftMargin} % \DescribeMacro{\ToAddressWidth} % The following lengths are self-evident. % \begin{macrocode} %<*package> \newlength{\FromAddressTopMargin} \newlength{\FromAddressLeftMargin} \newlength{\FromAddressHeight} \newlength{\FromAddressWidth} \newlength{\ToAddressTopMargin} \newlength{\ToAddressLeftMargin} \newlength{\ToAddressWidth} % % \end{macrocode} % % \subsection{Main setting commands} % % OK, we are ready to set up envelopes and labels. % % \DescribeMacro{\SetEnvelope} % The command "\SetEnvelope" has three parameters: optional top Margin, % width and height of the envelope. % \begin{macrocode} %<*package> \DeclareRobustCommand{\SetEnvelope}[3][0pt]{% \@envelopetrue% \setlength{\EnvelopeTopMargin}{#1}% \setlength{\EnvelopeWidth}{#2}% \setlength{\EnvelopeHeight}{#3}% \setlength{\FromAddressTopMargin}{0.5in}% \setlength{\FromAddressLeftMargin}{0.5in}% \setlength{\FromAddressHeight}{0.33\EnvelopeHeight}% \setlength{\FromAddressWidth}{0.5\EnvelopeWidth}% \setlength{\ToAddressTopMargin}{0.5in}% \setlength{\ToAddressLeftMargin}{0.5in}% \setlength{\ToAddressWidth}{3in}} % % \end{macrocode} % % \DescribeMacro{\SetLabel} % The command "\SetLabel" has seven parameters: five lengths and two % numbers. All are mandatory: % \begin{macrocode} %<*package> \DeclareRobustCommand{\SetLabel}[7]{% \@envelopefalse% \setlength{\LabelWidth}{#1}% \setlength{\LabelHeight}{#2}% \setlength{\LabelTopMargin}{#3}% \setlength{\LabelLeftMargin}{#4}% \setlength{\LabelRightMargin}{#5}% \setcounter{LabelMaxCol}{#6}% \setcounter{LabelMaxRow}{#7}% \setlength{\ToAddressTopMargin}{0.1in}% \setlength{\ToAddressLeftMargin}{0.2in}% \setlength{\ToAddressWidth}{\LabelWidth}% \addtolength{\ToAddressWidth}{-\ToAddressLeftMargin}% \addtolength{\ToAddressWidth}{-\LabelRightMargin}} % % \end{macrocode} % % \section{Defining options} % % \subsection{Envelope Sizes} % % \begin{macrocode} %<*package> \DeclareOption{businessenvelope}{\SetEnvelope{9.5in}{4.125in}} \DeclareOption{executiveenvelope}{\SetEnvelope{7.5in}{3.875in}} \DeclareOption{bookletenvelope}{\SetEnvelope{10.5in}{7.5in}} \DeclareOption{personalenvelope}{\SetEnvelope{6.5in}{3.625in}} \DeclareOption{c6envelope}{\SetEnvelope{162mm}{114mm}} \DeclareOption{c65envelope}{\SetEnvelope{224mm}{114mm}} \DeclareOption{c5envelope}{\SetEnvelope{229mm}{162mm}} % % \end{macrocode} % % \subsection{Labels sizes} % % \begin{macrocode} %<*package> \DeclareOption{avery5160label}{% \SetLabel{2.75in}{1in}{0.5in}{0.19in}{0.12in}{3}{10}} \DeclareOption{avery5161label}{% \SetLabel{4.19in}{1in}{0.5in}{0.16in}{0.19in}{2}{10}} \DeclareOption{avery5162label}{% \SetLabel{4.19in}{1.33in}{0.83in}{0.16in}{0.19in}{2}{7}} \DeclareOption{avery5163label}{% \SetLabel{4.19in}{2in}{0.5in}{0.16in}{0.19in}{2}{5}} \DeclareOption{avery5164label}{% \SetLabel{4.19in}{3.33in}{0.5in}{0.16in}{0.19in}{2}{3}} % % \end{macrocode} % % \subsection{Optional switches} % % \changes{v1.1}{7/8/96}{Added new options: "printreturnaddress", % "noprintreturnaddress"} % \changes{v1.1}{7/8/96}{Added new options: "pswait", % "nopswait"} % All this should be evident\dots % % \begin{macrocode} %<*package> \DeclareOption{rotateenvelopes}{\@rotateenvelopestrue} \DeclareOption{norotateenvelopes}{\@rotateenvelopesfalse} \DeclareOption{centerenvelopes}{\@envelopeposition=0\relax} \DeclareOption{leftenvelopes}{\@envelopeposition=1\relax} \DeclareOption{rightenvelopes}{\@envelopeposition=2\relax} \DeclareOption{customenvelopes}{\@envelopeposition=3\relax} \DeclareOption{printbarcodes}{\@barcodestrue} \DeclareOption{noprintbarcodes}{\@barcodesfalse\@alwaysbarcodesfalse} \DeclareOption{alwaysbarcodes}{\@alwaysbarcodestrue\@barcodestrue} \DeclareOption{noalwaysbarcodes}{\@alwaysbarcodesfalse} \DeclareOption{capaddress}{\@capitalizeaddresstrue} \DeclareOption{nocapaddress}{\@capitalizeaddressfalse} \DeclareOption{printreturnaddress}{\@printreturnaddresstrue} \DeclareOption{noprintreturnaddress}{\@printreturnaddressfalse} \DeclareOption{pswait}{\@pswaittrue} \DeclareOption{nopswait}{\@pswaitfalse} % % \end{macrocode} % % \subsection{Unknown options} % % All options we did not declare above are probably the options for the % "graphics" package; let us send them there. % \begin{macrocode} %<*package> \DeclareOption*{\PassOptionsToPackage{\CurrentOption}{graphics}} % % \end{macrocode} % % \subsection{Default options}\label{sec:DefOpt} % % \changes{v1.1}{07/08/1996}{Fixed typo in "businessenvelope" option} % \changes{v1.1}{07/09/1986}{Added default options: "nopswait", % "printreturnaddress"} % % \begin{macrocode} %<*package> \ExecuteOptions{businessenvelope,rotateenvelopes,centerenvelopes} \ExecuteOptions{printbarcodes,capaddress} \ExecuteOptions{nopswait,printreturnaddress} % % \end{macrocode} % % \section{Configuration file} % % At this point we will look for the configuration file. This file is % named "envlab.cfg". The options declared in this file will supersede % the ones declared in Section~\ref{sec:DefOpt}, but will be in their % turn be superseded by the options explicitly defined when the package % is loaded. % \begin{macrocode} %<*package> \InputIfFileExists{envlab.cfg}{% \typeout{Loading configuration file envlab.cfg}}{% \typeout{Configuration file envlab.cfg is not found}} % % \end{macrocode} % % Now let us discuss the structure of the configuration file. We want it % to contain default options, and therefore to be loaded before the % "\ProcessOptions" command. On the other hand we want it to contain % some definitions that \emph{supersede} the ones in this package. The % hook "\AtEndOfPackage" helps to do this: we will just delay all % definitions until later. % % OK, let's construct an example of "envlab.cfg" file. The commands here % essentially repeat Section~\ref{sec:DefOpt}, but we want to be % foolproof\dots % \begin{macrocode} %<*cfg> %% %% The default options go here %% \ExecuteOptions{businessenvelope,rotateenvelopes,centerenvelopes} \ExecuteOptions{printbarcodes,capaddress} \ExecuteOptions{nopswait,printreturnaddress} %% \AtEndOfPackage{\relax % Customization goes here } % % \end{macrocode} % % \section{Processing options and loading packages} % \changes{v0.92}{06/06/1996}{Added \cs{IfFileExists} when loading packages} % \begin{macrocode} %<*package> \ProcessOptions \IfFileExists{graphics.sty}{% \RequirePackage{graphics}}{% \PackageWarning{envlab}{% You don't have the graphics package!\MessageBreak Probably you will not be able to print\MessageBreak envelopes sidewise. \MessageBreak}} % % \end{macrocode} % % \section{Document layout} % % \subsection{Printer specific commands} % \label{sec:Print} % % \DescribeMacro{\@beginlabelshook} % \changes{v1.1}{07/09/1996}{Replaced \cs{@printpreamble} with % \cs{@beginlabelshook}} % The command "\@beginlabelshook" is called at the beginning of the % printing of envelopes and labels. We define it to be a no-op, but it % is possible to introduce some printer-specific commands (like paper % change). % \begin{macrocode} %<*package> \def\@beginlabelshook{\relax} % % \end{macrocode} % % \DescribeMacro{\@beginlabelpagehook} % \changes{v1.1}{07/09/1996}{Introduced new command % \cs{@beginlabelpagehook}} % The command "\@beginlabelpagehook" is like "\@beginlabelshook", but is % called at the beginning of each \emph{page} % of envelopes and labels. % \begin{macrocode} %<*package> \def\@beginlabelpagehook{\relax} % % \end{macrocode} % % \begin{macro}{\AtBeginLabels} % \changes{v1.1}{07/08/1996}{Made \cs{AtBeginLabels} cumulative} % \begin{macro}{\AtBeginLabelPage} % \changes{v1.1}{07/09/1996}{Introduced \cs{AtBeginLabelPage}} % The hooks "\AtBeginLabels" and "\AtBeginLabelPage" redefine % "\@beginlabelshook" and "\@beginlabelpagehook". They are built like % the standard \LaTeXe\ hooks % "\AtBeginDocument", "\AtBeginDvi", etc. In the implementation we use the % \emph{internal} \LaTeXe\ command "\g@addto@macro". In the current % (June~1996) \LaTeXe\ release it is defined as: % \DescribeMacro{\g@addto@macro} % \begin{verbatim} % \long\def\g@addto@macro#1#2{{% % \toks@\expandafter{#1#2}% % \xdef#1{\the\toks@}}} % \end{verbatim} % We quote this definition in case \emph{They} change Their minds\dots\ % \begin{macrocode} %<*package> \def\AtBeginLabels{\g@addto@macro\@beginlabelshook} \def\AtBeginLabelPage{\g@addto@macro\@beginlabelpagehook} % % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\PSwait} % \changes{v1.1}{07/09/1996}{Put William Slough's code in a separate macro} % \textsl{PostScript} printers can be switched to the manual feeding mode % with the following code by \emph{William Slough} "". % \begin{macrocode} %<*package> \def\PSwait{\special{ps: clear grestore @manualfeed 0 0 bop}} % % \end{macrocode} % The author explains his code in the following way: % \begin{quotation} % Here is a possible explanation: % % The clear removes operands from the PostScript stack, which has the % effect of reversing some actions from the *previous* bop. Unfortunately, % it reverses other important actions too (such as font size), but the % grestore seems to get these back. Then the desired @manualfeed, followed % by the ``bop'' for the beginning of page. The pair of 0's are used for % bop and are completely bogus. However, from what I could detect, 0's are % as good as anything. The values that DVIPS provides for bop seem to be % related to DVI page numbers. % % I make no guarantee about the reliability of this solution, but initial % tests indicate it will work for my environment. % \end{quotation} % \end{macro} % % \changes{v1.1}{07/08/1996}{Added implementation of the "pswait" option} % \changes{v1.1}{07/09/1996}{Moved \cs{PSwait} code to \cs{AtBeginLabelPage}} % \changes{v1.1}{07/15/1996}{Moved \cs{PSwait} code to \cs{AtBeginLabels}} % The option "pswait" puts the "\PSwait" code in the beginning of each page. % \begin{macrocode} %<*package> \if@pswait \AtBeginLabels{\PSwait}% \fi % % \end{macrocode} % % % \subsection{Some useful counters for labels} % % % % \DescribeMacro{LabelCountCol} % \DescribeMacro{LabelCountRow} % These counters store the position of the currently printed label: % \begin{macrocode} %<*package> \newcounter{LabelCountCol} \newcounter{LabelCountRow} % % \end{macrocode} % % % \DescribeMacro{LabelOffsetCol} % \DescribeMacro{LabelOffsetRow} % And these counters provide the offset for the label printed on a % partially used sheet: % \begin{macrocode} %<*package> \newcounter{LabelOffsetCol} \newcounter{LabelOffsetRow} \setcounter{LabelOffsetCol}{1} \setcounter{LabelOffsetRow}{1} % % \end{macrocode} % % \macro{\FirstLabel} % \changes{v1.1}{7/8/96}{Introduced new command \cs{FirstLabel}} % The command "\FirstLabel"\marg{Row}\marg{Col} sets the counters % "LabelOffsetRow" and "LabelOffsetCol". % \begin{macrocode} %<*package> \DeclareRobustCommand{\FirstLabel}[2]{% \setcounter{LabelOffsetRow}{#1}% \setcounter{LabelOffsetCol}{#2}} % % \end{macrocode} % % \subsection{Envelope Placement} % % Now we can calculate "\EnvelopeLeftMargin" % \begin{macrocode} %<*package> \ifcase\the\@envelopeposition \setlength{\EnvelopeLeftMargin}{\paperwidth} \if@rotateenvelopes \addtolength{\EnvelopeLeftMargin}{-\EnvelopeHeight} \else \addtolength{\EnvelopeLeftMargin}{-\EnvelopeWidth} \fi \setlength{\EnvelopeLeftMargin}{0.5\EnvelopeLeftMargin} \or \setlength{\EnvelopeLeftMargin}{0pt} \or \setlength{\EnvelopeLeftMargin}{\paperwidth} \if@rotateenvelopes \addtolength{\EnvelopeLeftMargin}{-\EnvelopeHeight} \else \addtolength{\EnvelopeLeftMargin}{-\EnvelopeWidth} \fi \else \relax \fi % % \end{macrocode} % % \subsection{Fonts} % % % \begin{macro}{\@toaddressfont} % \begin{macro}{\@fromaddressfont} % \changes{v1.1}{7/8/96}{Fixed documentation about \cs{@fromaddressfont}} % We want the address to be printed in \textsf{\large 12pt sans serif} % font. The return address will be printed in 10pt normal font. % \begin{macrocode} %<*package> \def\@toaddressfont{% \ifcase\@ptsize \large\or\normalsize\or\small\fi% \sffamily\selectfont} \def\@fromaddressfont{% \ifcase\@ptsize \normalsize\or\small\or\footnotesize\fi% \normalfont} % % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Return address} % % \DescribeMacro{\returnaddress} % The standard letter class defines "\returnaddress" to be null. This % is sensible if we are printing labels, but not so good if we are % printing \emph{envelopes}. Therefore let us redefine it: % \begin{macrocode} %<*package> \def\returnaddress{\if@envelope \fromaddress\else\relax\fi} % % \end{macrocode} % % % \subsection{Margins, page styles, etc.} % % % \begin{macro}{\startlabels} % The command "\startlabels" is the internal command that prepares % the paper for labels or envelopes, resets the internal counters and % calls "\@beginlabelshook". % \begin{macrocode} %<*package> \def\startlabels{% \pagestyle{empty} \setlength{\topmargin}{-1.0in} \if@envelope \addtolength{\topmargin}{\EnvelopeTopMargin} \else \addtolength{\topmargin}{\LabelTopMargin} \fi \setlength{\headheight}{0pt} \setlength{\headsep}{0pt} \setlength{\footskip}{0pt} \setlength{\textheight}{200in} \setlength\paperheight{\textheight} \global\vsize=200in\relax \addtolength{\textheight}{-\topmargin} \addtolength{\textheight}{-1.0in} \setlength{\oddsidemargin}{-1.0in} \setlength{\evensidemargin}{\oddsidemargin} \setlength{\textwidth}{20in} \hsize=20in \baselineskip=0pt \lineskip=0pt \parindent=0pt \if@envelope \relax \else \setcounter{LabelCountCol}{\theLabelOffsetCol} \setcounter{LabelCountRow}{\theLabelOffsetRow} \ifnum\theLabelOffsetRow>1 \null \loop \vspace*{\LabelHeight} \addtocounter{LabelOffsetRow}{-1} \ifnum\theLabelOffsetRow>1 \repeat \fi \ifnum\theLabelOffsetCol>1 \loop \hspace*{\LabelWidth}\nolinebreak \addtocounter{LabelOffsetCol}{-1} \ifnum\theLabelOffsetCol>1 \repeat \fi \nopagebreak \fi \spaceskip 0pt\relax \xspaceskip 0pt\relax \clubpenalty=0 \widowpenalty=0 \raggedbottom \sloppy \setlength\hfuzz{5in} \setlength\vfuzz{5in} \ignorespaces \@beginlabelshook \@beginlabelpagehook \nopagebreak} % % \end{macrocode} % \end{macro} % % \subsection{Printing of the addresses} % % \DescribeMacro{\PrintReturnAddress} % This macro uses the text as an argument and prints it according to % the conventions. % \begin{macrocode} %<*package> \newcommand{\PrintReturnAddress}[1]{% \vspace*{\FromAddressTopMargin} \null\hspace{\FromAddressLeftMargin} \parbox[t][\FromAddressHeight]{\FromAddressWidth}% {\@fromaddressfont \lineskip=1pt \if@printreturnaddress #1\else\relax\fi}} % % \end{macrocode} % % \DescribeMacro{\PrintAddress} % This macro works like "\PrintReturnAddress", with several important % differences: it prints barcodes if necessary \emph{and} % capitalizes the address. % \begin{macrocode} %<*package> \newcommand{\PrintAddress}[1]{% \vspace*{\ToAddressTopMargin} \leavevmode \null\hspace*{\ToAddressLeftMargin} \parbox[t]{\ToAddressWidth}{% \lineskip=1pt \if@barcodes \PrintBarCode{#1} \fi \@toaddressfont \if@capitalizeaddress \@make@capitalize{#1} \else #1 \fi}} % % \end{macrocode} % % \subsection{Label setup} % % \DescribeMacro{\PrintLabel} % This macro prints a label in a parbox % \begin{macrocode} %<*package> \newcommand{\PrintLabel}[1]{% \parbox[t][\LabelHeight]{\LabelWidth}{% \PrintAddress{#1}}} % % \end{macrocode} % % \subsection{Envelope setup} % % Labels include one box per label, so their setup is simple. The % situation with envelopes is different: they contain several boxes, and % could be rotated, centered, etc. % % \DescribeMacro{\PrintEnvelope} % This macro makes a minipage with addresses on it. % \begin{macrocode} %<*package> \newcommand{\PrintEnvelope}[2]{% \begin{minipage}[t][\EnvelopeHeight]{\EnvelopeWidth} \baselineskip=0pt \lineskip=0pt \parindent=0pt \PrintReturnAddress{#1}\\ \begin{center} \PrintAddress{#2} \end{center} \end{minipage}} % % \end{macrocode} % % \DescribeMacro{\@PrintEnvelope} % The following macro checks for rotation: % \begin{macrocode} %<*package> \newcommand{\@PrintEnvelope}[2]{% \if@rotateenvelopes\rotatebox{90}{\PrintEnvelope{#1}{#2}} \else\PrintEnvelope{#1}{#2} \fi} % % \end{macrocode} % % \section{Printing of envelopes and labels} % % \subsection{Main Command} % % \begin{macro}{\mlabel} % Now we are prepared to print actual envelopes and labels. It is done by % the "\mlabel" command. It has two forms: for labels and envelopes. % \begin{macrocode} %<*package> \renewcommand{\mlabel}[2]{\ignorespaces% \spaceskip 0pt\relax% \xspaceskip 0pt\relax% % % \end{macrocode} % % \subsection{Printing of one envelope} % \changes{v1.1}{07/09/1996}{Put \cs{@beginlabelpagehook} in the envelope % printing} % \begin{macrocode} %<*package> \if@envelope% \leavevmode% \hspace*{\EnvelopeLeftMargin}% \@PrintEnvelope{#1}{#2}% \clearpage% \@beginlabelpagehook% % % \end{macrocode} % % \subsection{Printing of one label} % \changes{v1.1}{07/09/1996}{Put \cs{@beginlabelpagehook} in the label % printing} % \begin{macrocode} %<*package> \else% \ignorespaces% \ifnum\theLabelCountCol>\theLabelMaxCol% \\\nopagebreak% \stepcounter{LabelCountRow}% \setcounter{LabelCountCol}{1}% \fi% \ifnum\theLabelCountRow>\theLabelMaxRow% \vfill\eject\@beginlabelpagehook% \setcounter{LabelCountRow}{1}% \setcounter{LabelCountCol}{1}% \fi% \PrintLabel{#2}\ignorespaces\nolinebreak% \stepcounter{LabelCountCol}% \fi} % % \end{macrocode} % \end{macro} % % \subsection{Printing of return labels} % % We print only mailing addresses on labels. The user is supposed to have % preprinted return labels. Here we describe a utility for printing them. % This utility should be used in a separate document. % % \DescribeMacro{\@numreturnlabels} % The counter "\@numreturnlabels" stores the number of return labels to % be printed. Note that it is a \TeX\ counter, not a \LaTeX\ one. % \begin{macrocode} %<*package> \newcount\@numreturnlabels % % \end{macrocode} % % \DescribeMacro{\printreturnlabels} % This macro has two parameters: the number of labels to be printed and % the text that is printed. It is the same on all labels. % \begin{macrocode} %<*package> \newcommand{\printreturnlabels}[2]{% \@numreturnlabels=#1 \def\@toaddressfont{\@fromaddressfont} \@capitalizeaddressfalse \@barcodesfalse \startlabels \loop \mlabel{\relax}{#2} \advance\@numreturnlabels by -1 \ifnum\@numreturnlabels>0\repeat} % % \end{macrocode} % % \section{Barcodes} % % \subsection{Main command} % % The USPS Postnet codes are printed accordingly to the specifications % Ref.~\cite{Pub25}. The scanning algorithm % is stolen from David Carlisle's \textsf{enumerate} package~\cite{Enum}. % % \DescribeMacro{\PrintBarCode} % First, we extract barcodes by the command "\@extractbarcode". Then % we print them by "\@printbarcode". % \begin{macrocode} %<*package> \newcommand{\PrintBarCode}[1]{% \@extractbarcode{#1} \@printbarcode} % % \end{macrocode} % % \subsection{Extraction of barcodes}\label{sec:Extract} % % We define zipcode as a sequence of digits (0--9) that: % \begin{itemize} % \item Has no characters other than digits and dashes (-) inside it % \item Has no bracketed groups inside it and is not bracketed itself % \item Is the last in the address field unless "\if@alwaysbarcodes=true" % \end{itemize} % % We print this sequence plus the \emph{control character}. % The latter is defined as minus sum of digits of the % zip code % modulo 10 (that is, the complement of the sum of digits to a % multiple of 10). % % First, some internal registers. % \DescribeMacro{\@zipcode} % \DescribeMacro{\@zipcodesum} % \DescribeMacro{\@zipcodefound} % The token list "\@zipcode" contains barcode found so far. The register % "\@zipcodesum" first contains the sum of digits of the barcode, and % then the control character. The % switch "\@zipcodefound" shows whether we found zip code so far. % \begin{macrocode} %<*package> \newtoks\@zipcode \newcount\@zipcodesum \newif\if@zipcodefound % % \end{macrocode} % % % % There are two modes for gobbling tokens: % \begin{enumerate}[{State} A:] % \item We are outside a potential zipcode sequence % ("\if@zipcodefound=false")\label{state:notfound} % \item We are inside a potential zipcode sequence % ("\if@zipcodefound=true")\label{state:found} % \end{enumerate} % % \begin{itemize} % % \item \DescribeMacro{\@endaddress} \DescribeMacro{\@finishzipcode} % If we meet in any state the special token "\@endaddress", we % gobble it and finish the loop. % \begin{macrocode} %<*package> \long\def\@finishzipcode#1{} % % \end{macrocode} % % \item \DescribeMacro{\@firstzipcode} If we meet a number (0--9) in % state~\ref{state:notfound}, we initialize registers, process the % token and go to state~\ref{state:found} % \begin{macrocode} %<*package> \long\def\@firstzipcode#1{% \global\@zipcode{#1} \global\@zipcodesum=#1\relax \global\@zipcodefoundtrue \@zipcodeloop} % % \end{macrocode} % % \item \DescribeMacro{\@continuezipcode} If we meet a number (0--9) % in state~\ref{state:found}, we just process it. % \begin{macrocode} %<*package> \long\def\@continuezipcode#1{% \global\@zipcode=\expandafter{\the\@zipcode#1} \global\advance\@zipcodesum by #1 \@zipcodeloop} % % \end{macrocode} % % \item \DescribeMacro{\@dashzipcode} If we meet a dash in % state~\ref{state:found}, we gobble it. % \begin{macrocode} %<*package> \long\def\@dashzipcode#1{\@zipcodeloop} % % \end{macrocode} % % \item \DescribeMacro{\@spacezipcode} If we meet a space in any % state, we gobble it and go to the state~\ref{state:notfound}. The % trick is from Carlisle's \textsf{enumerate} package. % \begin{macrocode} %<*package> \def\@spacezipcode{% \global\@zipcodefoundfalse \afterassignment\@zipcodeloop\let\@temp= } % % \end{macrocode} % % \item \DescribeMacro{\@abortzipcode} If we meet anything else in any % mode, we gobble it and go to state~\ref{state:notfound} % \begin{macrocode} %<*package> \long\def\@abortzipcode#1{% \global\@zipcodefoundfalse \@zipcodeloop} % % \end{macrocode} % % \end{itemize} % % % \DescribeMacro{\@zipcodeloop} % \DescribeMacro{\@temp} % This macro is simple. We just put the next token into "\@temp" and % process it through "\@zipcodeloop@". % \begin{macrocode} %<*package> \def\@zipcodeloop{\futurelet\@temp\@zipcodeloop@} % % \end{macrocode} % % \DescribeMacro{\@zipcodeloop@} % \DescribeMacro{\@tempa} % This macro performs actual processing\dots We put the command % that gobbles the next token into "\@tempa" % \begin{macrocode} %<*package> \def\@zipcodeloop@{% \ifx \@endaddress\@temp \def\@tempa{\@finishzipcode} \else \ifx 0\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 1\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 2\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 3\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 4\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 5\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 6\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 7\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 8\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx 9\@temp \if@zipcodefound \def\@tempa{\@continuezipcode} \else \def\@tempa{\@firstzipcode} \fi \else \ifx -\@temp \if@zipcodefound \def\@tempa{\@dashzipcode} \else \def\@tempa{\@abortzipcode} \fi \else \ifx \@sptoken\@temp \def\@tempa{\@spacezipcode} \else \def\@tempa{\@abortzipcode} \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \@tempa} % % \end{macrocode} % % \DescribeMacro{\@extractbarcode} % The command "\@extractbarcode" puts barcode into the "\@zipcode", % and calculates the control character (10 minus sum of the digits % of the barcode). % \begin{macrocode} %<*package> \long\def\@extractbarcode#1{% \@zipcodefoundfalse \@zipcodeloop#1\@endaddress \if@alwaysbarcodes \@zipcodefoundtrue \fi \if@zipcodefound \ifnum\the\@zipcodesum>0 \loop \global\advance \@zipcodesum by -10 \ifnum\the\@zipcodesum>0 \repeat \fi \global\multiply\@zipcodesum by -1 \fi} % % \end{macrocode} % % \subsection{Printing barcodes} % % \DescribeMacro{\@barcodewidth} % \DescribeMacro{\@barcodeLheight} % \DescribeMacro{\@barcodeSheight} % \DescribeMacro{\@barcodeskip} % First, some lengths. ``L'' and ``S'' below refer to ``long'' and % ``short'' bars correspondingly. % \begin{macrocode} %<*package> \newlength{\@barcodewidth} \newlength{\@barcodeLheight} \newlength{\@barcodeSheight} \newlength{\@barcodeskip} \setlength{\@barcodewidth}{0.020in} \setlength{\@barcodeLheight}{0.125in} \setlength{\@barcodeSheight}{0.050in} \setlength{\@barcodeskip}{0.026in} % % \end{macrocode} % % \DescribeMacro{\@barL} % \DescribeMacro{\@barS} % The following macros print long and short bars. % \begin{macrocode} %<*package> \DeclareRobustCommand{\@barL}{% \rule{\@barcodewidth}{\@barcodeLheight}\hspace{\@barcodeskip}} \DeclareRobustCommand{\@barS}{% \rule{\@barcodewidth}{\@barcodeSheight}\hspace{\@barcodeskip}} % % \end{macrocode} % % \DescribeMacro{\@printonezip} % \DescribeMacro{\@printbarcode} % The scanning of "\@zipcode" is simpler than the scanning of the address: % the only tokens we can meet are digits. Well, we will add an end marking % token to the list. Let it be the letter ``S'' (from ``Stop''). % \begin{macrocode} %<*package> \def\@printonezip#1{% \ifx1#1\@barS\@barS\@barS\@barL\@barL\else \ifx2#1\@barS\@barS\@barL\@barS\@barL\else \ifx3#1\@barS\@barS\@barL\@barL\@barS\else \ifx4#1\@barS\@barL\@barS\@barS\@barL\else \ifx5#1\@barS\@barL\@barS\@barL\@barS\else \ifx6#1\@barS\@barL\@barL\@barS\@barS\else \ifx7#1\@barL\@barS\@barS\@barS\@barL\else \ifx8#1\@barL\@barS\@barS\@barL\@barS\else \ifx9#1\@barL\@barS\@barL\@barS\@barS\else \ifx0#1\@barL\@barL\@barS\@barS\@barS\else \ifx S#1\def\@tempa{\relax}% \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi% \@tempa} \def\@printbarcode{% \if@zipcodefound \mbox{% \@barL% \def\@tempa{\@printonezip}% \expandafter\@tempa\the\@zipcode S% \def\@tempa{\@printonezip}% \expandafter\@tempa\the\@zipcodesum S% \@barL} \\[1ex] \fi} % % \end{macrocode} % % % % \section{Capitalization} % % % % % % These macros process the address (actually, any string) according to the % USPS recommendations. Specifically, they: % \begin{itemize} % \item Strip dots (.) and commas (,) from the address unless they are % enclosed in brackets % \item Make all letters uppercase % \item Add 1pt space between letters % \item Add 1em space between words % \end{itemize} % An interesting question is whether we should de-accent accented % letters. USPS says nothing about it. In the present version accents % are \emph{not} stripped. However due to the scanning algorithm they % should be enclosed by brackets, like this: % "{\u S}andor {\c C}edi". % % % % \DescribeMacro{\@addr@cap} % We store the capitalized address in the token list "\@addr@cap". % \begin{macrocode} %<*package> \newtoks\@addr@cap % % \end{macrocode} % % The following macros process the tokens one by one. % % \DescribeMacro{\@finishaddrcap} % If we meet the special token "\@endaddress", we gobble it and stop. % \begin{macrocode} %<*package> \long\def\@finishaddrcap#1{} % % \end{macrocode} % % \DescribeMacro{\@dotcommaaddrcap} % If we meet comma or dot, we gobble it and do \emph{not} stop. This macro % is also useful for gobbling \LaTeXe\ \textsf{letter} commands like % "\voidb@x" and "\unhbox". % \begin{macrocode} %<*package> \long\def\@dotcommaaddrcap#1{% \@addrcaploop} % % \end{macrocode} % % \DescribeMacro{\@newlineaddrcap} % If we meet "\\", we add it to the list % \begin{macrocode} %<*package> \long\def\@newlineaddrcap#1{% \global\@addr@cap=\expandafter{\the\@addr@cap #1} \@addrcaploop} % % \end{macrocode} % % \DescribeMacro{\@bgroupaddrcap} % If we meet "\bgroup", we add it to the list the complete group (uppercase) % \begin{macrocode} %<*package> \long\def\@bgroupaddrcap#1{% \global\@addr@cap=\expandafter{\the\@addr@cap {\MakeUppercase{#1}}} \@addrcaploop} % % \end{macrocode} % % \DescribeMacro{\@spaceaddrcap} % If we meet a space we gobble it (oh-oh) and add it to the list. % \begin{macrocode} %<*package> \def\@spaceaddrcap{% \global\@addr@cap=\expandafter{\the\@addr@cap\hspace{0.6em}} \afterassignment\@addrcaploop\let\@temp= } % % \end{macrocode} % % \DescribeMacro{\@otheraddrcap} % And if we meet anything else, we make it uppercase and add to the % list % \begin{macrocode} %<*package> \def\@otheraddrcap#1{% \global\@addr@cap=\expandafter{\the\@addr@cap% \MakeUppercase{#1}\kern1pt\relax} \@addrcaploop} % % \end{macrocode} % % % \DescribeMacro{\@addrcaploop} % This macro is simple. We just put the next token into "\@temp" and % process it through "\@addrcaploop@". % \begin{macrocode} %<*package> \def\@addrcaploop{\futurelet\@temp\@addrcaploop@} % % \end{macrocode} % % \DescribeMacro{\@addrcaploop@} % This macro performs actual processing\dots % \begin{macrocode} %<*package> \def\@addrcaploop@{% \ifx \@endaddress\@temp \def\@tempa{\@finishaddrcap} \else \ifx .\@temp \def\@tempa{\@dotcommaaddrcap} \else \ifx ,\@temp \def\@tempa{\@dotcommaaddrcap} \else \ifx \voidb@x\@temp \def\@tempa{\@dotcommaaddrcap} \else \ifx \unhbox\@temp \def\@tempa{\@dotcommaaddrcap} \else \ifx \\\@temp \def\@tempa{\@newlineaddrcap} \else \ifx \bgroup\@temp \def\@tempa{\@bgroupaddrcap} \else \ifx \@sptoken\@temp \def\@tempa{\@spaceaddrcap} \else \def\@tempa{\@otheraddrcap} \fi\fi\fi\fi\fi\fi\fi\fi \@tempa} % % \end{macrocode} % % \DescribeMacro{\@make@capitalize} % \begin{macrocode} %<*package> \long\def\@make@capitalize#1{% \global\@addr@cap={\relax} \@addrcaploop#1\@endaddress \the\@addr@cap} %<*package> % \end{macrocode} % % \Finale % % \clearpage % \addcontentsline{toc}{section}{\protect\refname} % \begin{thebibliography}{1} % \bibitem{Enum} % David Carlisle. % \newblock {\em The \textsf{enumerate} package}. % \newblock {CTAN}, v2.02, January 1994. % \bibitem{Pub25} % USPS. % \newblock {\em Designing Business Letter Mail (Pub 25)}, August 1995. % \end{thebibliography} % % \clearpage % \addcontentsline{toc}{section}{Change History} % \PrintChanges % % \clearpage % \addcontentsline{toc}{section}{Index} % \PrintIndex % \endinput