% Copyright 2004-2024, Alexander Shibakov % This file is part of SPLinT % % SPLinT is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % SPLinT is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with SPLinT. If not, see . % multicolumn output: % the general layout of the page is similar to the following, where % the number of columns and the location and the number of `footnote' % columns can be adjusted. %%%%%%%%%%% %%%%%%%%%%% %%%%%%%%%%% %%column1%% %%column2%% %%column3%% %%%%%%%%%%% ----------- %%%%%%%%%%% %%%%%%%%%%% %footnotes% %%%%%%%%%%% \newskip\realfootins \newskip\footglue \newskip\adjskip % skip to improve \vboxes \newcount\linecount \newcount\noofcolumns \newcount\fnotesstart \newcount\fnotesspan \newdimen\columnwidth \newdimen\icgap \newdimen\pagewidth \newdimen\pageheight \newdimen\longvsize % the height of all the columns combined \newdimen\fnoteboxwidth \newdimen\footvboxht % holds the previous value of the height of the % box of footnotes \newbox\partialpage \newbox\currentcolumn \newbox\foothbox % holds the footnotes `in one line' \newbox\foothhbox % holds every footnote in a separate \hbox \newbox\migrantbox {\setbox\migrantbox=\box\migrantbox} \newcount\remaindergaps % the number of gaps between columns after the % first `footnote column' \newcount\remaindernonfoots % the number of columns without footnotes % after the columns with footnotes \newif\ifoutputnow \newif\iflastpageup \maxdeadcycles=600 % this should be approximately half the \pageheight in points % to handle the case when \enddoublecols is called before the % last doublecolumn page is full % setup the page length and the column count \linecount=53 % number of lines in a page \fnotesstart=1 % start footnotes under the first column \fnotesspan=2 % footnotes span two columns \noofcolumns=2 \realfootins=12pt plus 1pt minus 1pt \footglue=1em plus.2em minus.1em \adjskip=0pt plus 6pt %\topskip=9pt %\normalbottom % one of these must accompany the use of the macros below % so that the columns are aligned % \def\setmcparams{% \columnwidth=\hsize \advance\columnwidth-\noofcolumns\icgap \advance\columnwidth\icgap \divide\columnwidth by\noofcolumns % \advance\linecount\m@ne % \vsize=\baselineskip % \multiply\vsize by \linecount % \advance\vsize by \topskip % \advance\linecount\@ne % \longvsize=\vsize \advance\longvsize by-\topskip \advance\longvsize by\baselineskip \divide\longvsize\baselineskip \multiply\longvsize\baselineskip \count\@cclv\noofcolumns \multiply\longvsize by \count\@cclv \advance\longvsize-\baselineskip \advance\longvsize\topskip } \setmcparams \skip\footins=\realfootins \count\footins=\@m % 1000 \pagewidth=\hsize \pageheight=\vsize % some debugging tools (rather primitive) \def\onpage#1#2{% {% \yystringempty{#1}{#2}% {% \ifnum#1=\pageno\relax \showboxbreadth=1000 \showboxdepth=1000 #2% \fi }% }% } \def\onpageg#1#2{% make global assignments possible \yystringempty{#1}{#2}% {% \ifnum#1=\pageno\relax \showboxbreadth=1000 \showboxdepth=1000 #2% \fi }% } \ifx\testpageno\UNDEFINED \def\testpageno{-\@M} \fi \def\footnote#1{% \edef\@sf{\spacefactor\the\spacefactor}\setfnmark \@sf \insert\footins{\floatingpenalty\@MM % 20000 \setbox\z@=\hbox{\fnfsize\strut\fnmark\localfn\nobreak \enskip{#1}\penalty-10\hskip\footglue}% \setfootnoteheight \box\z@ }% } \def\setfnoteparams{% \fnfsize % \emergencystretch=10pt \hbadness\@M % 10000 \hyphenpenalty\z@ \doublehyphendemerits\z@ \exhyphenpenalty\z@ \finalhyphendemerits\z@ \righthyphenmin\z@ \lefthyphenmin=\tw@ \leftskip\z@\rightskip\z@ \adjdemerits\z@ \uchyph=\@ne \pretolerance=-1 } \let\fnfsize\eightpoint \def\setfootnoteheight{ \global\setbox\foothbox=\hbox{\unhbox\foothbox\unhcopy\z@}% \setbox\@ne=\vbox{ \hsize=\fnoteboxwidth \setfnoteparams \noindent\unhcopy\foothbox \par }% \dimen\z@=\ht\@ne \advance\dimen\z@ by -\footvboxht \global\footvboxht=\ht\@ne \ht\z@=\dimen\z@ \dp\z@=\z@ \global\setbox\foothhbox=\hbox{\copy\z@\unhbox\foothhbox}} \def\makefootnoteparagraph{ \count\@cclv=\z@ \unvbox\footins \makehboxofhboxes \cleanupfootbuffer\readjustfoots \setbox\z@=\hbox{\unhbox\z@ \removehboxes} \setfnoteparams \noindent\unhbox\z@\par } \def\makehboxofhboxes{% \setbox\z@=\hbox{}% \loop \setbox\tw@=\lastbox \ifhbox\tw@ \advance\count\@cclv\@ne \setbox\z@=\hbox{\box\tw@\unhbox\z@}% \repeat } % the macro below admittedly stretches \TeX's stack capacity but it is rather efficient % at removing the \hbox packaging in the correct order. \def\removehboxes{\setbox\z@=\lastbox \ifhbox\z@{\removehboxes}\unhbox\z@ \fi} \def\cleanupfootbuffer{% remove the footnotes that made it to the page % form the buffer \global\setbox\foothhbox=\hbox{\unhbox\foothhbox\cleanupf@otbuffer}} \def\cleanupf@otbuffer{% \ifnum\count\@cclv>\z@ \setbox\z@=\lastbox \advance\count\@cclv\m@ne \let\next=\cleanupf@otbuffer \else \let\next=\relax \fi \next} \def\readjustfoots{% \setbox\@ne=\copy\foothhbox % keep the footnotes that did not make it % in the buffer \setbox3=\vbox{}% \global\setbox\foothbox=\hbox{}% \setbox\@ne=\hbox{\unhbox\@ne\readjustf@ots}% } \def\readjustf@ots{% \setbox\tw@=\lastbox \ifvoid\tw@ \let\next=\readjustf@@ts \else \global\setbox\foothbox=\hbox{\unhbox\foothbox\unhcopy\tw@}% \setbox3=\vbox{\box2\unvbox3}% \let\next=\readjustf@ots \fi \next } \def\readjustf@@ts{% \setbox\tw@=\vbox{ \hsize=\fnoteboxwidth \setfnoteparams \noindent\unhcopy\foothbox\par } \global\footvboxht=\ht\tw@ \dimen\z@=\ht\tw@ \advance\dimen\tw@ by -\ht3 \ifnum\dimen\z@=\z@ \else \global\setbox\footins=\vbox{}% \advance\dimen\z@ by \m@ne sp \ht\footins=\dimen\z@ \dp\footins=\@ne sp % to indicate that this is an % adjustment box for inner (i.e. the ones inserted by \footblock rathar than % as part of the main output routine) footnotes (looked at by the output routine); % if the height of the already contributed footnotes needs to be % adjusted, adjust the height of the \box\footins by that amount \fi } \fnoteboxwidth=\pagewidth % footnotes will spread across the whole page \newskip\dsskip \dsskip\smallskipamount \def\begindoublecols{% \begingroup %\normalbottom \r@ggedbottomfalse % \normalbottom changes \topskip which we do not want \parindent=0pt \count\footins=\@m \multiply\count\footins by\fnotesspan \skip\footins=\fnotesspan\realfootins \remaindergaps=\noofcolumns \advance\remaindergaps by -\fnotesstart \remaindernonfoots=\remaindergaps \advance\remaindernonfoots by -\fnotesspan \advance\remaindernonfoots\@ne \ifnum\noofcolumns>\@ne % typesetting in one column is an exception, % otherwise ... % first, calculate the intercolumn skip ... \dimen\z@=\pagewidth \dimen\@ne=\columnwidth \multiply\dimen\@ne by\noofcolumns \advance\dimen\z@ by-\dimen\@ne \count\@cclv=\noofcolumns \advance\count\@cclv\m@ne \divide\dimen\z@ by\count\@cclv \count\@cclv=\fnotesspan \advance\count\@cclv\m@ne \dimen\@ne=\columnwidth \multiply\dimen\@ne by\fnotesspan \advance\dimen\@ne by \count\@cclv\dimen\z@ % ... to get the width of the footnote box \fnoteboxwidth=\dimen\@ne \fi % this final modification is needed due to the fact that the whole % page is put in \hbox to\hsize{...; without the modification the % width of the footnote box is not going to match the width of the % page, and when the footnotes span all the columns there will be no % `\hfill' to compensate for arithmetic imprecision \ifnum\fnotesspan=\noofcolumns \fnoteboxwidth=\pagewidth \fi % \output={ \settopmark % save the \topmark if this is the top of the page \ifvoid\partialpage \else % this is a border case: too much material has been contributed, this routine will be called twice % so output the full page now \normaloutput{\unvbox\partialpage}\lheader\rheader \fi \global\setbox\partialpage=\vbox{\unvbox\@cclv\vskip\dsskip}% \dimen\z@=\longvsize \advance\dimen\z@ by -\noofcolumns\ht\partialpage \ifnum\dimen\z@<\z@ % the amount of material contributed to the current page is more than the % required \vsize (so that \pageshrink would have to be involved); % output the page normally \normaloutput{\unvbox\partialpage}\lheader\rheader \else % move the footnotes into the buffer, recalculate their size \migratefootnotes \fi }% \eject \def\footnoterule{\kern -3\p@ \hrule width \fnoteboxwidth \kern 2.6\p@}% \outputnowfalse % not ready for immediate output, play with dimensions first \lastpageupfalse % not the final page yet \holdinginserts=\@ne \let\thepage\pagesofar \hsize=\columnwidth \output={\multcolumnout} \mco@computevsize \ifvoid\migrantbox \else \insert\footins{\box\migrantbox}% \fi } \def\mco@computevsize{% \global\vsize=\pageheight% \global\advance\vsize by-\ht\partialpage% \global\divide\vsize\baselineskip \global\multiply\vsize\baselineskip \global\multiply\vsize\noofcolumns% \global\advance\vsize by-\noofcolumns\topskip \global\advance\vsize by\topskip \global\advance\vsize by\noofcolumns\baselineskip \global\advance\vsize by-\baselineskip } \newif\ifpenultimatepage \newif\ifp@nultimatepage \def\enddoublecols{\par % fire the page buidling routine \ifnum\pagetotal>\pagegoal \global\penultimatepagetrue \eject % if the multicolumn output ended just barely after accumulating a full page \fi % but before the page is shipped out, output the page with the standard multicolumn output \dimen7 =\pagegoal \vsize=\longvsize % now recalculate all the dimensions assuming that the footnotes stretch across the whole page \ifnum\footvboxht>\z@ \advance\vsize by \fnotesspan\footvboxht \advance\dimen7 by \fnotesspan\footvboxht \advance\vsize by -\noofcolumns\realfootins \advance\vsize by \fnotesspan\realfootins \advance\dimen7 by -\noofcolumns\realfootins \advance\dimen7 by \fnotesspan\realfootins \fi \fnotesspan=\noofcolumns \fnotesstart=\@ne \remaindergaps=\noofcolumns \advance\remaindergaps by -\fnotesstart \remaindernonfoots=\z@ \fnoteboxwidth=\pagewidth \setbox\z@=\hbox{}\setfootnoteheight % calculate and adjust the height of the footnotes; this introduces an extra \hbox to \foothhbox % remember this when in the output routine for the last page! \advance\vsize by -\noofcolumns\footvboxht \advance\dimen7 by -\noofcolumns\footvboxht \pagegoal=\dimen7 % \lastpageuptrue \ifp@nultimatepage % everything has been output already \global\penultimatepagefalse \global\p@nultimatepagefalse \else \global\penultimatepagefalse \eject \fi \endgroup \holdinginserts=\z@ \global\pagegoal=\pageheight \global\vsize=\pageheight} \def\migratefootnotes{% \ifvoid\footins \else \ifdim\dp\footins=\z@ % it is not a correction \setbox\@ne=\vbox{\unvbox\footins % similar to \makehboxofhboxes \setbox\z@=\hbox{}% \loop \setbox\tw@=\lastbox \ifhbox\tw@ \setbox\z@=\hbox{\unhbox\tw@\unhbox\z@}% \repeat % ... \setbox\foothbox=\hbox{}% \setbox\foothhbox=\hbox{}% \footvboxht=\z@ \setfootnoteheight\global\setbox\migrantbox=\box\z@ } \else {\global\setbox\footins=\box\footins}% \fi \fi } \def\multcolumnout{% \settopmark % save the \topmark if this is the top of the page \splittopskip=\topskip \splitmaxdepth=\maxdepth \dimen\z@=\pageheight \advance\dimen\z@ by-\ht\partialpage \advance\dimen\z@ by-\dp\partialpage \ifnum\dimen\z@<\baselineskip % another extreme case: at most one line will fit, so % the adjustments to \vsize will not change the page layout % quickly enough resulting in an infinite \deadcycles loop \normaloutput{\unvbox\partialpage}\lheader\rheader \unvbox\@cclv \penalty\lastpenalty \mco@computevsize \else \multcolumnout@split \fi } \newtoks\fromword % save the marks \newtoks\toword \def\multcolumnout@split{% proceed with splitting and balancing the columns % normalize the max column height of the collected material first \divide\dimen\z@\baselineskip \multiply\dimen\z@\baselineskip \dimen\@ne=\pagegoal % we claculate the maximum allowable height of the % middle column next \advance\dimen\@ne by-\vsize \advance\dimen\@ne by \fnotesspan\dimen\z@ \divide\dimen\@ne by\fnotesspan % \balanceallcolumns % \ifoutputnow \global\fromword=\expandafter{\firstmark} \global\toword=\expandafter{\botmark} \iflastpageup \onpage{\testpageno}{\message{outputting last page...}}% \ifnum\outputpenalty<-9999 % this break was forced (most likely by the \break in \enddouble...) \ifvoid\footins \else \ifdim\dp\footins=\z@ \else {\setbox\footins=\box\footins}% this was a correcion box after which no new real footnotes \fi % were contributed \fi % a correction (\hbox{}) was added by the \enddouble... command; % this correction will affect \box\footins (since it will appear % as a box in \foothhbox, a box that is not a footnote); % this correction will be translated into an appropriate % adjustment to \box\footins (since the output routine thinks % it is a footnote); however, it does throw the footnote count in \foothhbox % off by one; kill it here; the footnotes will be inserted from the footins box \setbox\z@=\vbox{\pagesofar}% \unvbox\z@ \penalty\lastpenalty %? % since we could not touch \foothhbox above (to keep the footnote height calculations correct), % the \footins box is messed up; fix it {\setbox\footins=\box\footins}% \global\setbox\foothhbox=\hbox{}% to keep the footnote counting \global\setbox\foothbox=\hbox{}% consistent \global\footvboxht=\z@ \else \normaloutput\page\lheader\rheader % \global\vsize=\longvsize \global\outputnowfalse \global\holdinginserts=\@ne \fi \else % this is not the last page, perform normal multicolumn output \normaloutput\page\lheader\rheader % \global\vsize=\longvsize \global\outputnowfalse \global\holdinginserts=\@ne \ifpenultimatepage % page broken at a penalty inserted by \enddoublecols \global\p@nultimatepagetrue % the next penalty should be removed \fi \fi {\setbox\@cclv=\box\@cclv}% use up \box255 ! \else % do not output yet, see if adjustments worked \ifnum\dimen\tw@>\dimen\@ne \global\advance\vsize by -\fnotesspan pt \else \global\outputnowtrue \global\holdinginserts=\z@ \fi \unvbox\@cclv\relax \ifnum\outputpenalty=\@M % 10000 the break was not at a penalty item \else \ifp@nultimatepage % we already split the page at this penalty \global\p@nultimatepagefalse % let \enddoublecols insert the penalty \else \penalty\outputpenalty \fi \fi \fi } % we will change some of the plain TeX macros used by cwebmac \def\pagebody{% \vbox to \pageheight{ \boxmaxdepth=\maxdepth \pagecontents \the\footline \ifr@ggedbottom \vskip\adjskip \fi } } % since the output routine is executed several times for every physical page of output % we have to make sure that the \topmark value is saved only once; % the mechanism below relies on \normaloutput being the only physical means of outputting the page % (more precisely, the only macro that contains the \shipout command and expands \savetopmark) \newtoks\savedtopmark % keep track of the last mark \def\settopmark{% this has to be done at the beginning of every \output routine % it would have been a lot easier if there was an \everyoutput type command available \yytoksempty\savedtopmark{\global\savedtopmark\expandafter{\topmark}}{}% \yytoksempty\savedtopmark{\global\savedtopmark{{0}{0}{0}}}{}% make sure the saved topmark is not empty from now on } \def\normaloutput#1#2#3{\ifodd\pageno\hoffset=\pageshift\fi % this is a convenient (although not very refined) way to ivestigate spacing problems \onpageg{\testpageno}{\tracingoutput=1\relax}% \shipout\vbox{ \vbox to\fullpageheight{ \iftitle\global\titlefalse \else\hbox to\pagewidth{\vbox to10pt{}\ifodd\pageno #3\else#2\fi}\fi \vfill #1 } }% parameter #1 is the page itself \ifnum\outputpenalty=-'10000000000 % this is the \end ... \everyendofjob \fi \global\advance\pageno by1 \global\savedtopmark{}% reset the last mark (the only place where this is done) } \def\topsecno{\expandafter\takeone\the\savedtopmark} % the last section on the % previous page % we change the original output routine from cwebmac.tex to handle the topmark saving % mechanism introduced here % a word of caution about the change below: if dcols.sty is not loaded immediately after % cwebmac.tex (or at least before the first page is discarded) the output routine below % must be further adjusted to % \global\output{\settopmark\normaloutput\page\lheader\rheader} % so that any `watsit' nodes on the first page (like \write, \open, etc) have a chance to % execute; one possible (although not perfect) way of automating this choice is to detect % the horizontal mode here and change the output routine accordingly. \output{\setbox0=\page % the first page is garbage \openout\cont=\contentsfile \write\cont{\catcode `\noexpand\@=11\relax} % \makeatletter \global\output{\settopmark\normaloutput\page\lheader\rheader}} % make sure the \topmark is nonempty; AS \let\page\pagebody % this is a cwebmac command but it has to be executed here, after the \pagebody macro is changed \def\pagecontents{ \ifvoid\topins \else \unvbox\topins \fi \setbox\z@=\vbox{\thepage}\dimen\z@=\dp\z@ % for \ruggedbottom \unvbox\z@ \ifr@ggedbottom \kern-\dimen\z@\vfil \fi \ifvoid\footins \else \ifnum\dp\footins=\z@ % this is not an adjustment \vskip\realfootins\footnoterule \vbox{\hsize=\pagewidth\makefootnoteparagraph}% \fi \fi } \def\thepage{\unvbox\@cclv} \def\balanceallcolumns{ \tcthr=\vbadness \vbadness=1000000 % set \vbadness to the badness of a overfull box \count\@cclv\z@ % (does not really prevent TeX from reporting one) \setbox\z@=\vbox{\unvcopy\@cclv}% \setbox\tw@=\vbox{}%%% this box is changed globally \b@lanceallcolumns } \def\b@lanceallcolumns{ \onpage{\testpageno}{\message{normalized (after partial page) max column ht(dimen0): \the\dimen0}}% \advance\count\@cclv\@ne \whichcolumn{\count\@cclv}% \ifinfoots % if the footnotes go under these columns ... \dimen\tw@=\ht\z@ \onpage{\testpageno}{\message{total height of remaining collected material, in footnotes(dimen2): \the\dimen2}}% \advance\dimen\tw@ by -\remaindernonfoots\dimen\z@ \advance\dimen\tw@ by -\remaindergaps\baselineskip \advance\dimen\tw@ by \remaindergaps\topskip \divide\dimen\tw@ by \fnotesspan \onpage{\testpageno}{\message{set footnote column ht(dimen2): \the\dimen2}}% \let\next=\b@l@nceallcolumns \else % otherwise, split off the columns ... \onpage{\testpageno}{\message{total height of remaining collected material, pre footnotes(ht0): \the\ht0}}% \ifnum\dimen\z@<\topskip \setbox\@ne=\vsplit\z@ to \topskip \else \setbox\@ne=\vsplit\z@ to \dimen\z@ % see a remark below on why this was necessary \fi \wd\@ne=\hsize \setbox\tw@=\vbox{\box\@ne \unvbox\tw@}%%% this box is changed globally \let\next=\b@lanceallcolumns \fi \next } \newcount\tcthr \def\b@l@nceallcolumns{% splitting off the columns after the footnotes start \count\@cclv=\fnotesstart \setbox3=\copy\z@ \setbox5=\vbox{}% \b@l@nc@allcolumns } \def\b@l@nc@allcolumns{ % box3 contains a copy of the collected material after the pre footnote columns have been split off \whichcolumn{\count\@cclv}% \iflastcolumn \ifnum\ht3>\dimen\ifinfoots \tw@ \else \z@ \fi \onpage{\testpageno}{\message{last \ifinfoots (footnote) \fi column too high: \the\ht3 % \space vs. allowable height(dimen\ifinfoots 2\else 0\fi): \the\dimen\ifinfoots \tw@ \else \z@ \fi}}% \advance\dimen\tw@ by \@ne pt \let\next=\b@l@nceallcolumns \else \ifinfoots \else \ifnum\dimen\z@<\topskip \onpage{\testpageno}{\message{d0}}% \setbox3=\vsplit3 to \topskip \else \onpage{\testpageno}{\message{d0>=ts--->}}% \setbox3=\vsplit3 to \dimen\z@ \fi \fi \onpage{\testpageno}{\message{last \ifinfoots footnote \fi column height(ht3): \the\ht3 % \space topskip: \the\topskip, }}% \onpage{\testpageno}{\message{max column height(dimen0): \the\dimen0}}% \wd3=\hsize \setbox\tw@=\vbox{\box3 \unvbox5 \unvbox\tw@}% %%% \box2 is later changed globally \vbadness=\tcthr \let\next=\relax \fi \else \ifnum\dimen\ifinfoots \tw@ \else \z@ \fi<\topskip \setbox4=\vsplit3 to \topskip \else \setbox4=\vsplit3 to \dimen\ifinfoots \tw@ \else \z@ \fi \fi % the code above is a replacement for: % \setbox4=\vsplit3 to \dimen\ifinfoots \tw@ \else \z@ \fi % \ifnum\badness>\@MM \errmessage{\the\badness:\the\vbadness}\fi % the replacement was necessary to avoid `Overfull \vbox ... ' warnings % that (unlike those for underfull boxes) cannot be silenced by raising % \vbadness \wd4=\hsize \setbox5=\vbox{\box4 \unvbox5}% \advance\count\@cclv\@ne \let\next=\b@l@nc@allcolumns \fi \next } \def\pagesofar{% \unvbox\partialpage \count\@cclv\z@ \hbox to\pagewidth{\p@gesofar}% \kern-\prevdepth \vskip\adjskip } \def\p@gesofar{\advance\count\@cclv\@ne \whichcolumn{\count\@cclv}% \ifinfoots \let\next=\footblock \else \iflastcolumn \getnextcolumn\box\currentcolumn \let\next=\relax \else \getnextcolumn\box\currentcolumn\hfil \let\next=\p@gesofar \fi \fi \next } \def\footblock{% \onpage{\testpageno}{\message{building footnote columns...}}% \hbox to \fnoteboxwidth{\f@otblock}% \count\@cclv=\fnotesstart \advance\count\@cclv by\fnotesspan \advance\count\@cclv\m@ne \whichcolumn{\count\@cclv}% \onpage{\testpageno}{\message{column \the\count\@cclv\space to process...}}% \iflastcolumn \let\next=\relax \onpage{\testpageno}{\message{done...}}% \else \hfil \let\next=\p@gesofar \onpage{\testpageno}{\message{process columns after the footnotes...}}% \fi \next } \def\f@otblock{% \whichcolumn{\count\@cclv}% \ifinfoots \iffirstfootcol % put all the footnotes after the first column \setbox\z@=\rlap{\vbox{ \ifvoid\footins \else \ifdim\dp\footins=\z@ % footnote info is present \vskip\realfootins\footnoterule \vbox{\hsize=\fnoteboxwidth\makefootnoteparagraph} \fi \fi }}% \dimen5=\ht\z@ \dimen6=\dimen5 \advance\dimen6 by\dimen\tw@ \setbox\z@=\vbox{ \getnextcolumn\unvbox\currentcolumn\kern-\dimen3 \vskip\adjskip \box\z@ }% \ifnum\ht\z@>\baselineskip \setbox\z@=\vbox to \dimen\iflastpageup 6 \else \z@ \fi{\unvbox\z@}% \fi \wd\z@=\hsize \box\z@ \else % \onpage{\testpageno}{\showboxbreadth=100 \showboxdepth=100 \showbox\currentcolumn}% \hfil\setbox\z@=\vbox{ \getnextcolumn\unvbox\currentcolumn\kern-\dimen3 \vskip\adjskip \hrule width\z@ height \dimen5 depth\z@ }% \onpage{\testpageno}{\message{topskip: \the\topskip, adjskip: \the\adjskip, bottom rule: wd=0pt, ht=\the\dimen5, dp=0pt}}% \onpage{\testpageno}{\message{splittopskip: \the\splittopskip}}% \onpage{\testpageno}{\message{last box height (preadjustment): \the\ht0 }}% \ifnum\ht\z@<\topskip%>\baselineskip is another option \else \setbox\z@=\vbox to \dimen\iflastpageup 6 \else \z@ \fi{\unvbox\z@}% \fi \onpage{\testpageno}{\message{last box height: \the\ht0 }}% \wd\z@=\hsize \box\z@ \fi \iflastcolumn \let\next=\relax \else \let\next=\f@otblock \fi \else \let\next=\relax \fi \advance\count\@cclv\@ne \next } \def\getnextcolumn{% \global\setbox\tw@=\vbox{\unvcopy\tw@ \global\setbox\currentcolumn=\lastbox}% \dimen3=\dp\currentcolumn } \newif\ifinfoots \newif\iflastcolumn \newif\ifbeforefoots \newif\iffirstfootcol \def\whichcolumn#1{% \infootsfalse \lastcolumnfalse \beforefootsfalse \firstfootcolfalse \ifnum#1<\fnotesstart \beforefootstrue \else \ifnum#1=\fnotesstart \firstfootcoltrue \infootstrue \else \advance\fnotesstart by\fnotesspan \ifnum#1<\fnotesstart \infootstrue \fi \advance\fnotesstart by-\fnotesspan \fi \ifnum#1=\noofcolumns \lastcolumntrue \fi \fi } % footnote accounting macros using aux stream \yyuniondeclare\fnoteunion{aux:global:fnotes} \defp\addfnlabel{} \defp\addpgendlabel#1{} \defp\setfniteration#1{} \toyyunion{aux:global:fnotes:neutral} \defc\addfnlabel{\expandafter\fnstream\expandafter{\the\fnstream*}} \defc\addpgendlabel#1{\expandafter\fnstream\expandafter{\the\fnstream|}} \defc\setfniteration#1{\fniteration=#1 } \toyyunion{aux:global:fnotes} \def\yyuniontag{\auxunionctl} \defp\fnoteunionctl{}% sequence to activate/deactivate/take other action for % fnote set of macros \defc\fnoteunionctl{% \restorecslist{aux:global:fnotes}\fnoteunion } \savecs{aux:global:activate}\fnoteunionctl \defc\fnoteunionctl{% \restorecslist{aux:global:fnotes:neutral}\fnoteunion } \savecs{aux:global:deactivate}\fnoteunionctl \defc\fnoteunionctl{% this command should not make any page material contributions \message{footnotes...}% \fnstream{}% \restorecslist{aux:global:deactivate}\auxunionctl \auxunionctl % ignore all other sets \restorecslist{aux:global:fnotes}\fnoteunion \restorecs{aux:global:fnotes:neutral}\setfniteration \input\jobname.aux \edef\next{\the\fnstream}% \checkfnprefixx{\savedfnstream}{\the\fnstream}% {\message{Footnotes are stable ...}}% {\message{Footnotes may be set incorrectly ...}}% } \savecs{aux:global:preend}\fnoteunionctl \defc\fnoteunionctl{% this command should not make any page material contributions \message{footnotes...}% \let\footthenotes\markbottomofpage \edef\savedfnstream{\the\fnstream}% \advance\fniteration by\@ne \toksa\expandafter{\fnoteunion}% \immediate\write\auxstream{\harmlesscomment\the\toksa}% \immediate\write\auxstream{\noexpand\setfniteration{\the\fniteration}}% } \savecs{aux:global:prestart}\fnoteunionctl % end footnote accounting macros % text crossreferencing setup using the aux stream \yyuniondeclare\textrefunion{aux:global:textrefs} \defp\refanchor#1#2\end{} \toyyunion{aux:global:textrefs:neutral} \defc\refanchor#1#2\end{% \expandafter\def\csname ref: #1\endcsname{#2}% }% \toyyunion{aux:global:textrefs} \def\yyuniontag{\auxunionctl} \defp\textrefunionctl{}% sequence to activate/deactivate/take other action for % fnote set of macros \defc\textrefunionctl{% \restorecslist{aux:global:textrefs}\textrefunion } \savecs{aux:global:activate}\textrefunionctl \defc\textrefunionctl{% \restorecslist{aux:global:textrefs:neutral}\textrefunion } \savecs{aux:global:deactivate}\textrefunionctl \defc\textrefunionctl{% this command should not make any page material contributions \message{text references...}% } \savecs{aux:global:preend}\textrefunionctl \defc\textrefunionctl{% this command should not make any page material contributions \message{text references...}% \toksa\expandafter{\textrefunion}% \immediate\write\auxstream{\harmlesscomment\the\toksa}% } \savecs{aux:global:prestart}\textrefunionctl % end text cross referencing macros % macros for adding and using counters for referencing \def\volatile@counters{1(0){\errmessage{invalid counter!}}} \def\delayed@counters{1(0){\errmessage{invalid counter!}}} \def\addvcounter#1#2{% #1 is the name of the counter % #2 is the access sequence \counterattach\volatile@counters{#2}{#1}% } \def\adddcounter#1#2{% #1 is the name of the counter % #2 is the access sequence \counterattach\delayed@counters{#2}{#1}% } \def\counterattach#1#2{% \expandafter\c@unterattach#1\end{#1}{#2}% } \def\c@unterattach#1(#2\end#3#4#5{% #1 is the counter top index % #2 is the counter array % #3 is the name of the counter array % #4 is the access sequence of the new counter % #5 is the name of the counter \expandafter\def\expandafter#3\expandafter{\number\xincrement{#1}(#2(#1){#4}}% add the counter to the array \expandafter\def\csname ct:\expandafter\eatone\string#3[#5]\endcsname{#1}% save counter index \expandafter\def\csname get ct:\expandafter\eatone\string#3[#5]\endcsname##1(#1)##2##3\end{##2}% } \def\getcountervalue#1#2#3{% #1 is the name % #2 is the name of the array % #3 is the array instance \csname get ct:\expandafter\eatone\string#2[#1]\endcsname#3\end } \addvcounter{section}{\secno} \adddcounter{page}{\the\pageno} \def\fulllabel#1{% {% \edef\next{\toksa{\volatile@counters}}\next % immediate references \toksb\expandafter{\delayed@counters}% references to be processed at the page output stage \edef\next{\write\auxstream{% \string\refanchor{#1}\the\toksa\string\delayed\the\toksb\end}}\next }% } \def\extractref#1{% \ifx#1\relax \yybreak{\ignoreref}% \else \yybreak{\expandafter\extractr@f#1}% \yycontinue }% \def\ignoreref#1\end#2\end{{ref \bf ??}} \def\extractr@f#1\delayed#2\end#3#4\end{% % #1 is the volatile counters % #2 is the delayed counters % #3 is text for the link % #4 is the reference constructor (like \solrefcompose) #4{#1}{#2}{#3}% } % end crossreferencing setup macros % helper macros to check if footnotes have been correctly placed \def\checkfnprefix#1#2{% \expandafter\ch@ckfnprefix\romannumeral-0\yyprefixmatch{#1}{#2}% } \def\ch@ckfnprefix#1#2#3{% #1 is the common prefix, #2 and #3 are remainders \yystringempty{#2}{% \yyifrepeatedchar|{#3}{\yyfirstoftwo}{\yysecondoftwo}% }{% \yysecondoftwo } } \def\checkfnprefixx#1#2{% \expandafter\ch@ckfnprefixx\expandafter{#1}{#2}% } \def\ch@ckfnprefixx#1#2{% \expandafter\ch@ckfnpr@fixx\expandafter{#2}{#1}% } \def\ch@ckfnpr@fixx#1#2{% \checkfnprefix{#2}{#1}% } % end footnote prefix checking helper macros \let\footthenotes\empty \footline{% \footthenotes % so the footnotes know where to reset \ifchapterhead \vbox to 0pt{ \hbox to\pagewidth{\hfil \mainfont\vrule width 0pt height 2pc\oldstyle\the\pageno \hfil} \vss }% \global\chapterheadfalse \fi } \def\fnmark#1{{% \ifnum#1<\@M \setbox\z@=\hbox{\rm)}\vbox to \ht\z@{\hbox{$\scriptstyle\the#1$}\vss}\box\z@ \else \setbox\z@=\hbox{\rm)}\setbox2=\hbox{$\scriptstyle0$}% \setbox\@ne=\hbox{\vrule width\wd2 height\ht2}% \vbox to \ht\z@{\box\@ne\vss}\box\z@ \fi}} \newtoks\fnstream % locations of footnotes \fnstream={} \newcount\localfn % footnote count \newcount\fniteration % current footnote calculation iteration count \fniteration\z@ \def\markbottomofpage{% \write\auxstream{\noexpand\addpgendlabel{\the\pageno}\harmlesscomment\space bottom of page \the\pageno}% } \def\setfnmark{{% \ifnum\localfn<\@M \getfntok \if*\nexttok \global\advance\localfn\@ne \else \global\localfn=\@M \fi \fi \removewhitespace\kern2pt\fnmark\localfn \write\auxstream{\noexpand\addfnlabel}% }} \def\getfntok{\loop\splitfnstream\if|\nexttok\global\localfn=\z@ \repeat} \def\splitfnstream{% \edef\tempdefone{\the\fnstream}% \ifx\tempdefone\empty % no footnote tokens left, although we are expecting one \def\nexttok{?}\message{You may have to reposition the footnotes ...}% \else \expandafter\splitfnstre@m\tempdefone\end \fi } \def\splitfnstre@m#1#2\end{\def\nexttok{#1}\global\fnstream={#2}}