% This macro source file is from the four volume series % "TeX in Practice" by Stephan von Bechtolsheim, published % 1993 by Springer-Verlag, New York. % Copyright 1993 Stephan von Bechtolsheim. % No warranty or liability is assumed. % This macro may be copied freely if no fees other than % media cost or shipping charges are charged and as long % as this copyright and the following source code itself % is not changed. Please see the series for further information. % % Version: 1.0 % Date: May 1, 1993 % % % This source code is documented in 37.2.7.1, p. IV-170. % Original source in file "o4.TEX", starting line 461. \wlog{L: "out-ds.tip" ["o4.TEX," l. 461, p. IV-170]}% % This file DOES NOT belong to format "texip." \InputD{box-mac.tip} \InputD{rangetst.tip} \InputD{maxmindi.tip} \InputD{prot.tip} \InputD{vtbox.tip} \InputD{nathd.tip} \InputD{shiftudb.tip} \catcode`\@ = 11 \newdimen\@PageWidth \newdimen\@ColWidth \newdimen\@ColIndent \newdimen\@PageHeight \newcount\@DSCCurNumberOfColumns \newcount\@PageLayoutCodeDSC \newcount\@DSCDebugging \def\SetUpDSC #1#2#3#4#5#6{% \@DSCDebugging = #6 \CheckZeroOneRange{\@DSCDebugging}% {\string\SetUpDSC: debugging code wrong} \ifnum\@DSCDebugging = 0 \ProtWritefalse \else \ProtWritetrue \fi \InitProtWrite \WriteProtocol{0}{\string\SetUpDSC: begin}% \@PageWidth = #1% \@ColWidth = #2% \@ColIndent = #3% \@PageHeight = #4% \@PageLayoutCodeDSC = #5% \CheckZeroOneRange{\@PageLayoutCodeDSC}% {\string\SetUpDSC: page layout code wrong}% \hsize = \@PageWidth \dimen0 = 2\@ColIndent \advance\dimen0 by 2\@ColWidth \ifdim\dimen0 > \hsize \errmessage{\string\SetUpDSC: Initial values of \string\hsize, \noexpand\@ColWidth and \noexpand\@ColIndent do not make sense.}% \fi \vsize = \@PageHeight \@DSCCurNumberOfColumns = 1 \@SetSingleColumnOutput{As part of \string\SetUpDSC}% \ifcase \@PageLayoutCodeDSC \topskip = 10pt % Top / bottom flush \or \topskip = 10pt plus 50pt % Ragged bottom \else \errmessage{\string\SetUpDSC: illegal page layout parameter.}% \fi \WriteProtocol{0}{\string\SetUpDSC: end}% } \def\UnDoDSC{% \global\output = {\plainoutput}% } \newbox\@BoxOfPageSoFar \newbox\@DSCLeftColumnBox \newdimen\@DSCLeftNaturalHeight \newbox\@DSCRightColumnBox \newdimen\@DSCRightNaturalHeight \newbox\@DSCTempBox \def\@EliminateRulesConditional{% \ifnum\@DSCDebugging = 0 \EliminateRuledBoxes \fi } \newif\if@CaseCPageBreak \def\@EjectPenalty{-10000 } \def\eject{\penalty\@EjectPenalty} \def\@BalancePenalty{-10001 } \def\@PageLine{\hbox to \@PageWidth} \def\@PageLineR{\HboxR to \@PageWidth} \def\@ProtDSC #1{ \WriteProtocol{1}{\string\@ProtDSC: Begin (page \the\pageno)} \WriteProtocol{2}{"#1", number of cols: \the\@DSCCurNumberOfColumns} \WriteProtocol{2}{\string\vsize: \the\vsize, \string\pagetotal: \the\pagetotal, \string\pagegoal: \the\pagegoal} \BoxToProtocol{2}{\@BoxOfPageSoFar}{} \WriteProtocol{2}{\string\dimen0: \the\dimen0, \string\outputpenalty: \the\outputpenalty} \WriteProtocol{1}{\string\@ProtDSC: End} } \def\@CaseReport #1{% \WriteProtocol{0}{CASE #1}% \message{CASE #1.}% } \def\@SetOutputRoutine #1#2#3{% #1\output = {#2}% \WriteProtocol{0}{\string\@SetOutputRoutine:}% \WriteProtocol{1}{#3}% } \def\@SingleColumnOutputRoutine{% \@EliminateRulesConditional \WriteProtocol{0}{\noexpand\@SingleColumnOutputRoutine called, \noexpand\outputpenalty is \the\outputpenalty} \WriteProtocol{1}{Page number is \the\pageno} \showboxdepth = 2 \showboxbreadth = 1000 \@ProtDSC{\string\@SingleColumnOutputRoutine: begin}% \BoxToProtocol{1}{255}{}% \@CheckNumberOfColumns{1}{\@SingleColumnOutputRoutine}% \@ShipAPageBox{% \ifnum\@PageLayoutCodeDSC = 0 \vbox to \@PageHeight{\unvbox 255}% \else \vbox to \@PageHeight{\unvbox 255 \vfill}% \fi }% } \def\@SetSingleColumnOutput #1{% \WriteProtocol{0}{\string\@SetSingleColumnOutput: set to single column output!}% \global\@DSCCurNumberOfColumns = 1 \@SetOutputRoutine{\global}{\@SingleColumnOutputRoutine}{#1}% \global\vsize = \@PageHeight \global\pagegoal = \@PageHeight } \def\@SaveCurrentPageOutputRoutine{% \global\setbox\@BoxOfPageSoFar = \vbox{\unvbox 255}% \BoxToProtocol{0}{\@BoxOfPageSoFar}% {\string\@SaveCurrentPageOutputRoutine} } \newcount\@VsizeFactor \def\@ComputeVsizeForDoubleColumns{% \vsize = \@PageHeight \advance\vsize by -\ht\@BoxOfPageSoFar \advance\vsize by -\dp\@BoxOfPageSoFar \multiply\vsize by 2 \@VsizeFactor = \vsize \divide\@VsizeFactor by \baselineskip \ifodd\@VsizeFactor \advance\@VsizeFactor by -1 \fi \global\vsize = \@VsizeFactor \baselineskip \@ProtDSC{\string\@ComputeVsizeForDoubleColumns}% } \newdimen\@HalfVsize \def\@ComputeHalfVsize{% \@HalfVsize = \vsize \divide\@HalfVsize by 2 } \def\BeginDoubleColumns{% \par \WriteProtocol{0}{\string\BeginDoubleColumns: begin} \@CheckNumberOfColumns{1}{\BeginDoubleOfColumns}% \global\@DSCCurNumberOfColumns = 2 \begingroup \@CaseCPageBreakfalse \@EliminateRulesConditional \WriteProtocol{1}{\string\BeginDoubleColumns: put rest of page into \string\@BoxOfPageSoFar}% \@SetOutputRoutine{}{\@SaveCurrentPageOutputRoutine}% {\string\BeginDoubleColumns: save page built up to now.}% \eject \@ProtDSC{\string\BeginDoubleColumns: 2}% \@SetOutputRoutine{}{\@DoubleColumnOutputRoutine}% {Double column output set up by \string\BeginDoubleColumns}% \hsize = \@ColWidth \@ComputeVsizeForDoubleColumns \@ProtDSC{\string\BeginDoubleColumns: 3}% } \def\EndDoubleColumns{% \par \WriteProtocol{0}{\string\EndDoubleColumns: begin} \@CheckNumberOfColumns{2}{\EndDoubleOfColumns} \@ProtDSC{In \string\EndDoubleColumns} \@CaseReport{A} \penalty\@BalancePenalty \@BuildPageSoFar \@SetSingleColumnOutput{\string\EndDoubleColumns} \endgroup } \def\@DoubleColumnOutputRoutine{% \@EliminateRulesConditional \WriteProtocol{0}{\string\@DoubleColumnOutputRoutineput: begin (penalty: \the\outputpenalty)} \if@CaseCPageBreak \@CaseReport{D/E}% \ifvoid\@DSCLeftColumnBox \errmessage{\string\@DoubleColumnOutputRoutine: missing left column!}% \else \ifvoid\@DSCRightColumnBox \global\setbox\@DSCRightColumnBox = \vbox{\unvbox 255}% \global\@DSCRightNaturalHeight = \ht\@DSCRightColumnBox \ifnum\outputpenalty = \@EjectPenalty \errmessage{\string\@DoubleColumnOutput: \noexpand\eject in right column illegal.}% \@CaseReport{D} \MaxDimen{\dimen0}{\@DSCRightNaturalHeight}% {\@DSCLeftNaturalHeight}{}% \else \ifnum\outputpenalty = \@BalancePenalty \@CaseReport{E} \MaxDimen{\dimen0}{\@DSCRightNaturalHeight} {\@DSCLeftNaturalHeight}{}% \else \@CaseReport{D}% \dimen0 = \vsize \fi \fi \@SetColumnBox{\@DSCLeftColumnBox}{}% \@SetColumnBox{\@DSCRightColumnBox}{}% \Vtbox{\@DSCRightColumnBox}{\global}% \ShiftRefPointUpOrDown{\@DSCRightColumnBox}{12pt}% \Vtbox{\@DSCLeftColumnBox}{\global}% \ShiftRefPointUpOrDown{\@DSCLeftColumnBox}{12pt}% \ifnum\outputpenalty > -10000 \@ShipAPageBox{% \ifnum\@PageLayoutCodeDSC = 0 \vbox to \@PageHeight{\@BuildPageSoFar}% \else \vbox to \@PageHeight{\@BuildPageSoFar \vfill}% \fi }% \else % It's \EndDoubleColumns! \fi \global\@CaseCPageBreakfalse \@ComputeVsizeForDoubleColumns \global\pagegoal = \vsize \else \errmessage{\string\@DoubleColumnOutputRoutine: left / right columns messed up.} \fi \fi \else \ifnum\outputpenalty = \@EjectPenalty \@CaseReport{C} \WriteProtocol{1}{\string\@DoubleColumnOutputRoutineput: penalty \@EjectPenalty call.} \global\@CaseCPageBreaktrue \ifvoid\@DSCLeftColumnBox \global\setbox\@DSCLeftColumnBox = \vbox{\unvbox 255} \global\@DSCLeftNaturalHeight = \ht\@DSCLeftColumnBox \@ComputeHalfVsize \WriteProtocol{2}{*\string\vsize/2 is \the\@HalfVsize}% \dimen1 = \ht\@DSCLeftColumnBox \advance\dimen1 by \dp\@DSCLeftColumnBox \ifdim\dimen1 > \@HalfVsize \message{WARNING: column is to long!}% \fi \global\pagegoal = \@HalfVsize \global\vsize = \@HalfVsize \else \errmessage{\string\@DoubleColumnOutputRoutine: left column box already loaded!}% \fi \else \@StandardBalanceColumns \ifnum\outputpenalty = \@BalancePenalty \@CaseReport{A}% \else \@CaseReport{B}% \@ShipAPageBox{% \ifnum\@PageLayoutCodeDSC = 0 \vbox to \@PageHeight{\@BuildPageSoFar}% \else \vbox to \@PageHeight{\@BuildPageSoFar \vfill}% \fi }% \@ComputeVsizeForDoubleColumns \global\pagegoal = \vsize \fi \fi \fi } \newcount\@EmptyBoxesBuildPageCount \def\@BuildPageSoFar{% \@EmptyBoxesBuildPageCount = 0 \ifvoid\@BoxOfPageSoFar \advance\@EmptyBoxesBuildPageCount by 1 \fi \ifvoid\@DSCLeftColumnBox \advance\@EmptyBoxesBuildPageCount by 1 \fi \ifvoid\@DSCRightColumnBox \advance\@EmptyBoxesBuildPageCount by 1 \fi \WriteProtocol{1}{\string\@BuildPageSoFar: begin (\noexpand\@EmptyBoxesBuildPageCount is \the\@EmptyBoxesBuildPageCount)} \ifnum\@EmptyBoxesBuildPageCount < 3 \BoxToProtocol{2}{\@BoxOfPageSoFar}{} \BoxToProtocol{2}{\@DSCLeftColumnBox}{} \BoxToProtocol{2}{\@DSCRightColumnBox}{} \unvbox\@BoxOfPageSoFar % May be empty. \wd\@DSCLeftColumnBox = \@ColWidth % Left column. \wd\@DSCRightColumnBox = \@ColWidth % Right column. \@PageLine{% \hskip\@ColIndent \BoxR\@DSCLeftColumnBox \hfil \BoxR\@DSCRightColumnBox \hskip\@ColIndent } \smallskip \fi \WriteProtocol{1}{\string\@BuildPageSoFar: end} } \def\@SetColumnBox #1#2{% \global\setbox#1 = \vbox to \dimen0{\unvbox#1 #2}% \Vtbox{#1}{\global}% \ShiftRefPointUpOrDown{#1}{12pt}% } \def\@StandardBalanceColumns{% \setbox\@DSCTempBox = \vbox{\unvcopy 255} \dimen0 = \ht\@DSCTempBox \advance\dimen0 by \dp\@DSCTempBox \advance\dimen0 by \topskip \divide\dimen0 by 2 \WriteProtocol{1}{\string\@StandardBalanceColumns: \noexpand\dimen0 is \the\dimen0, page \the\pageno.} \@BalanceColumns{\dimen0}% } \def\@BalanceColumns #1{% \@ProtDSC{\string\@BalanceColumns: Start}% \@EliminateRulesConditional \ifvoid\@DSCLeftColumnBox\else \errmessage{\string\@BalanceColumns: left column box not empty.}% \fi \ifvoid\@DSCRightColumnBox\else \errmessage{\string\@BalanceColumns: right column box not empty.}% \fi \ifvoid 255 \errmessage{\string\@BalanceColumns: box 255 is void.}% \fi \setbox\@DSCTempBox = \vbox{\unvbox 255} \dimen0 = #1 \splittopskip = \topskip \BoxToProtocol{0}{\@DSCTempBox}{Before \noexpand\vsplit loop}% {% \vbadness = 10000 % Don't report underfull boxes. \loop \global\setbox\@DSCRightColumnBox = \copy\@DSCTempBox \global\setbox\@DSCLeftColumnBox = \vsplit\@DSCRightColumnBox to \dimen0 \WriteProtocol{1}{\string\dimen0: \the\dimen0}% \BoxToProtocol{1}{\@DSCLeftColumnBox}% {[1] (left column) in \noexpand\vsplit loop}% \BoxToProtocol{1}{\@DSCRightColumnBox}% {[2] (right column) in \noexpand\vsplit loop}% \NaturalHeight{\dimen3}{\@DSCLeftColumnBox}% \NaturalHeight{\dimen4}{\@DSCRightColumnBox}% \WriteProtocol{3}{\string\dimen3: \the\dimen3}% \WriteProtocol{3}{\string\dimen4: \the\dimen4}% \advance\dimen3 by 1sp \ifdim\dimen4 > \dimen3 \global\advance\dimen0 by 1pt \repeat } \setbox\@DSCLeftColumnBox = \vbox{\unvbox\@DSCLeftColumnBox}% \setbox\@DSCRightColumnBox = \vbox{\unvbox\@DSCRightColumnBox}% \MaxDimen{\dimen0}{\ht\@DSCLeftColumnBox}% {\ht\@DSCRightColumnBox}{}% \ifcase\@PageLayoutCodeDSC \@SetColumnBox{\@DSCLeftColumnBox}{}% \@SetColumnBox{\@DSCRightColumnBox}{}% \or \@SetColumnBox{\@DSCLeftColumnBox}{\vfill}% \@SetColumnBox{\@DSCRightColumnBox}{\vfill}% \fi \WriteProtocol{1}{\string\@BalanceColumns: balancing done.}% } \def\DSCHeader{% \@PageLineR{% \bf Header \hfil \tt \the\pageno }% } \def\DSCFooter{% % \@PageLineR{% % \vrule width \@PageWidth height 1pt depth 2pt % }% \@PageLineR{% \bf FOOTER \hfil \tt \the\pageno }% } \def\@ShipAPageBox #1{% \WriteProtocol{0}{\string\@ShipAPageBox: called (page \the\pageno)}% \shipout\vbox{% \@EliminateRulesConditional \DSCHeader \vskip 12pt #1 \vskip 12pt \DSCFooter } \WriteProtocol{0}% {\string\@ShipAPageBox: done (page \the\pageno)}% \advancepageno } \def\@CheckNumberOfColumns #1#2{% \ifnum \@DSCCurNumberOfColumns = #1\relax \else \errmessage{\string\@CheckNumberOfColumns: [\string#2]: currently \the\@DSCCurNumberOfColumns\space columns, should be #1.} \fi } \def\bye{} \def\bye{% \@CheckNumberOfColumns{1}{\string\bye: Still in double column mode, forgotten a \string\EndDoubleColumns?}% \vfill\supereject \end } \catcode`\@ = 12