%% %% $Id: 2up.tex 1180 2020-05-09 10:02:00Z herbert $ %% %% COPYRIGHT 1992/2010, by Timothy Van Zandt, tvz@Princeton.EDU %% COPYRIGHT 2010-2020, by Herbert Voss, hvoss@tug.org %% %% Copyright: %% This program can be redistributed and/or modified under the terms %% of the LaTeX Project Public License Distributed from CTAN archives %% in directory macros/latex/base/lppl.txt. %% %% DESCRIPTION: %% 2up.tex/2up.sty provides two-up printing for Generic TeX or LaTeX (e.g., %% Plain, LaTeX, xetex, xelatex, AmSTeX and AmS-LaTeX). It produces a standard (x)dvi file, %% and does not involve an additional dvi or PostScript filter. It has a %% flexible interface for specifying paper size and layout. %% % \def\fileversion{1.3a} \def\filedate{2020/05/09} % \csname TwoUpLoaded\endcsname \let\TwoUpLoaded\endinput % \edef\TheAtCode{\the\catcode`\@} \catcode`\@=11\relax \message{\space\space v\fileversion\space\space \filedate\space\space } % % Parameter registers: \newdimen\@targetwidth \newdimen\@targetheight \newdimen\@sourcewidth \newdimen\@sourceheight \newdimen\pageseplength \newdimen\pagesepwidth \newdimen\pagesepoffset \newif\if@sidebyside \@sidebysidetrue \newif\if@twosided % % Registers used by output routine. \newif\if@leftpage \@leftpagetrue \newbox\@leftpage \newbox\@rightpage \newcount\@physicalpage % % Since pages are shipped out half as often: \multiply\maxdeadcycles by 2 % % Registers used only for booklet layout: \begingroup \let\newcount\relax \gdef\booklet@registers{% \newcount\bookletpage \bookletpage=0 \newcount\leftpagenumber \newcount\rightpagenumber \multiply\maxdeadcycles by 20} \endgroup % % A useful extension of the \magstep macro. \def\magstepminus#1{% \ifcase#1 \@m\or 833\or 694\or 579\or 482\or 401\fi\relax} % % \@targetwidth and \@targetheight are set to the *unmagnified* dimensions % of the target page. \inv@targetmag is the inverse of the target % magnification. {\catcode`\p=12\catcode`\t=12\gdef\@@inv@@mag#1pt#2{\def#2{#1}}} \def\target#1#2#3{% \mag #1\relax \@targetwidth=1000pt \divide\@targetwidth by #1\relax \expandafter\@@inv@@mag\the\@targetwidth\inv@targetmag \@targetwidth=#2\relax \@targetwidth=\inv@targetmag\@targetwidth \@targetheight=#3\relax \@targetheight=\inv@targetmag\@targetheight} % % Like \target, but for the source: \def\source#1#2#3{% \@sourcewidth=1000pt \divide\@sourcewidth by #1\relax \expandafter\@@inv@@mag\the\@sourcewidth\inv@sourcemag \@sourcewidth=#2\relax \@sourcewidth=\inv@sourcemag\@sourcewidth \@sourceheight=#3\relax \@sourceheight=\inv@sourcemag\@sourceheight} % % \targetlayout does a loop that reads the comma separated arguments. % There can be no extraneous spaces. \def\targetlayout#1{\process@targetlayout#1,stop,} \def\process@targetlayout#1,{% \expandafter\let\expandafter\next\csname target@#1\endcsname \ifx\next\relax \begingroup \errhelp{Valid target layouts are "topbottom", "twosided", "booklet", "Booklet" and "dvidvi".}% \errmessage{`#1' is invalid 2up target layout - ignored.}% \endgroup \expandafter\process@targetlayout \else \next \fi} \def\target@stop{} \def\target@booklet{% \booklet@registers \def\ship@@@leftpage{\save@booklet\@leftpage}% \def\ship@@@rightpage{\save@booklet\@rightpage}% \@leftpagefalse \def\twoup@eject{\twoup@eject@booklet}% \expandafter\process@targetlayout} \def\target@Booklet{% \def\booklet@@loop{\Booklet@@loop}% \target@booklet} \def\target@twosided{% \@twosidedtrue \expandafter\process@targetlayout} \def\target@topbottom{% \def\make@@halfpage{\make@@halftopbottom}% \def\make@fullpage{\make@fulltopbottom}% \@sidebysidefalse \expandafter\process@targetlayout} \def\target@dvidvi{% \def\ship@@@leftpage{\ship@dvidvi\@leftpage}% \def\ship@@@rightpage{\ship@dvidvi\@rightpage}% \expandafter\process@targetlayout} % % TeX's \shipout primitive is saved as \&normal@shipout, and then \shipout % is defined to save each page to \@leftpage or \@rightpage and to print out % every two. With the twosided layout, filler pages are added when needed. \expandafter\let\csname &normal@shipout\endcsname\shipout \def\shipout{% \if@leftpage \global\@leftpagefalse \def\next{\afterassignment\ship@leftpage\global\setbox\@leftpage=}% \if@twosided \ifodd\count\z@ \global\setbox\@leftpage=\hbox{}% \make@@halfpage\@leftpage\ship@@@leftpage \def\next{\shipout}% \fi \fi \else \global\@leftpagetrue \def\next{\afterassignment\ship@rightpage\global\setbox\@rightpage=}% \if@twosided \ifodd\count\z@ \else \global\setbox\@rightpage=\hbox{}% \make@@halfpage\@rightpage\ship@@@rightpage \def\next{\shipout}% \fi \fi \fi \next} % % The job of \ship@leftpage and \ship@rightpage is to invoke \ship@@leftpage % or \ship@@rightpage at the right time. \shipout is followed either % (i) by an \hbox, \vbox or \vtop, in which case \ship@leftpage is invoked % after the opening {. \@leftpage is void, and \ship@leftpage invokes % \ship@@leftpage after the closing }, or % (ii) by a \box or \copy, in which case \ship@leftpage is invoked after % the full assignment. \@leftpage is not voide, and \ship@leftpage invokes % \ship@@leftpage immediately. \def\ship@leftpage{% \ifvoid\@leftpage\aftergroup\ship@@leftpage\else\ship@@leftpage\fi} \def\ship@rightpage{% \ifvoid\@rightpage\aftergroup\ship@@rightpage\else\ship@@rightpage\fi} % % \ship@@leftpage/\ship@@rightpage take the output box, and first make it % into a fully-size source page (with \make@halfpage) and then this is % centered horizontally and vertically in half of a target page (with % \make@@halfpage). Then they are shipped individually or together. \def\ship@@leftpage{\make@halfpage\@leftpage\ship@@@leftpage} \def\ship@@rightpage{\make@halfpage\@rightpage\ship@@@rightpage} \def\make@halfpage#1{% \dp#1=\z@ \setbox#1=\vbox to\@sourceheight{% \vskip \inv@sourcemag in \vskip \voffset \hbox to\@sourcewidth{\hskip\inv@sourcemag in\hskip\hoffset\box#1\hss}% \vss}% \make@@halfpage#1} % % The definition of \make@@halfpage depends on the target layout. \def\make@@halfsidebyside#1{% \global\setbox#1=\vbox to\@targetheight{\vss \hbox to.5\@targetwidth{\hss\box#1\hss}\vss}} \def\make@@halftopbottom#1{% \global\setbox#1=\vbox to.5\@targetheight{\vss \hbox to\@targetwidth{\hss\box#1\hss}\vss}} \def\make@@halfpage{\make@@halfsidebyside} % % The pages are generaly shipped in pairs: \def\ship@twoup{% \begingroup \voffset=-\inv@targetmag in \hoffset=\voffset \global\advance\@physicalpage by 1 \count\z@=\@physicalpage \csname &normal@shipout\endcsname\make@fullpage \endgroup} \let\ship@@@leftpage\relax \def\ship@@@rightpage{\ship@twoup} % % The definition of \make@fullpage depends on the layout: \def\make@fullsidebyside{% \hbox{\box\@leftpage\pagesep@sidebyside\box\@rightpage}} \def\make@fulltopbottom{% \vbox{\offinterlineskip\box\@leftpage\pagesep@topbottom\box\@rightpage}} \def\make@fullpage{\make@fullsidebyside} % % A vertical or horizontal rule can be inserted. These can be redefined % for other tricks: \def\pagesep@sidebyside{% \begingroup \advance\pageseplength by \pagesepoffset \pagesepwidth=\inv@targetmag\pagesepwidth \kern -.5\pagesepwidth \vrule height \inv@targetmag\pageseplength depth -\inv@targetmag\pagesepoffset width \pagesepwidth \kern -.5\pagesepwidth \endgroup} \def\pagesep@topbottom{% \begingroup \pagesepwidth=\inv@targetmag\pagesepwidth \vskip -.5\pagesepwidth \moveright\inv@targetmag\pagesepoffset\hbox{% \vrule height\pagesepwidth width\inv@targetmag\pageseplength}% \vskip -.5\pagesepwidth \endgroup} % % With the dvidvi layout, the pages are shipped individually: \def\ship@dvidvi#1{% \begingroup \voffset=-\inv@targetmag in \hoffset=\voffset \csname &normal@shipout\endcsname\box#1% \endgroup} % % With the booklet or Booklet layout, the pages are saved rather than % shipped. \begingroup \let\newbox\relax \gdef\save@booklet#1{% \begingroup \globaldefs=1 \advance\bookletpage by 1 \expandafter\newbox\csname bookletbox\the\bookletpage\endcsname \expandafter\setbox\csname bookletbox\the\bookletpage\endcsname\box#1% \endgroup} \endgroup % % The pages are then printed at the end with the following macros: \def\make@bookletpage#1{% \setbox\ifodd#1\@rightpage\else\@leftpage\fi=% \expandafter\box\csname bookletbox\the#1\endcsname} \def\booklet@loop{% \count\z@\rightpagenumber \make@bookletpage\leftpagenumber \make@bookletpage\rightpagenumber \ship@twoup \booklet@@loop} \def\booklet@@loop{% \advance\rightpagenumber by 2 \advance\leftpagenumber by -2 \ifnum\leftpagenumber<1\else\expandafter\booklet@loop\fi} \def\Booklet@@loop{% \advance\rightpagenumber by 1 \advance\leftpagenumber by -1 \ifnum\leftpagenumber<\rightpagenumber\else\expandafter\booklet@loop\fi} % % This one is easy: \def\twoupemptypage{\shipout\hbox{}} % % This clears a whole target page if there is a saved left page. Note that % this does not invoke the output routine; i.e., it is not like \clearpage % or \supereject. See \twoupclearpage and \twoupeject below. \def\twoup@eject{% \if@leftpage\else \global\setbox\@rightpage\hbox{}% \make@@halfpage\@rightpage\ship@@@rightpage \global\@leftpagetrue \fi} % % This is the definition of \twoup@eject with the booklet option: \def\twoup@eject@booklet{% \leftpagenumber\bookletpage \advance\leftpagenumber by 3 \divide\leftpagenumber by 4 \multiply\leftpagenumber by 4 \rightpagenumber=1 \ifnum\leftpagenumber>\bookletpage \setbox\@leftpage\hbox{}% \make@@halfpage\@leftpage \loop \setbox\@rightpage\copy\@leftpage \save@booklet\@rightpage \ifnum\leftpagenumber>\bookletpage \repeat \fi \booklet@loop} % % This modification is needed for \LaTeX in order to get the last page % printed out if the final page is a left page (the catcode business is % because \enddocument is \let to \bye in amstex): \begingroup \expandafter\ifx\csname @latexerr\endcsname\relax \catcode`\>=14\else\catcode`\>=9\fi\relax >>\gdef\twoupclearpage{\clearpage\twoup@eject} >>\expandafter\@temptokena\expandafter{\enddocument} >>\xdef\enddocument{\noexpand\twoupclearpage\the\@temptokena} \endgroup % % For most other macro packages we could just leave be and all pages would % always be printed because of the way the \end primitive works (except that % TeX will go bonkers with the booklet layout). However, % sometimes a blank filler page would be printed *with* headings. We prefer % the filler page to be truly blank. To achieve this, we hack the definition % of \end. This may cause problems with some macros. \expandafter\ifx\csname @latexerr\endcsname\relax \let\twoup@@@end\end \def\end{\twoup@eject\twoup@@@end} \def\twoupeject{\par\vfil\supereject\twoup@eject} \fi % % This is one workaround for the page cross-references problem \def\TwoupWrites{% \let\TwoupSaved@write\write \let\TwoupSaved@read\read \let\TwoupSaved@openout\openout \let\TwoupSaved@closeout\closeout \def\write{\TwoupSaved@write-1{}\immediate\TwoupSaved@write}% \def\read{\TwoupSaved@write-1{}\immediate\TwoupSaved@read}% \def\openout{\TwoupSaved@write-1{}\immediate\TwoupSaved@openout}% \def\closeout{\TwoupSaved@write-1{}\immediate\TwoupSaved@closeout}% \let\TwoupWrites\relax} % % Defaults: \def\twouparticle{% \target{\magstepminus1}{11in}{8.5in}% \source{\magstep0}{8.5in}{11in}} \def\twoupplain{% \target{\magstepminus2}{11in}{8.5in}% \source{\magstep0}{8.5in}{11in}} \def\twouplegaltarget{% \target{\magstepminus1}{14in}{8.5in}% \source{\magstep0}{8.5in}{11in}}% \def\twouplandscape{% \target{\magstepminus2}{8.5in}{11in}% \source{\magstep0}{11in}{8.5in}% \targetlayout{topbottom}} \expandafter\ifx\csname @latexerr\endcsname\relax \twoupplain\else\twouparticle\fi \pagesepwidth 0pt \pageseplength 6.5in \pagesepoffset 1in % \expandafter\catcode`\@=\TheAtCode\relax \endinput %% END 2up.tex/2up.sty