diff options
Diffstat (limited to 'macros/latex/contrib/revtex/source/ltxgrid.dtx')
-rw-r--r-- | macros/latex/contrib/revtex/source/ltxgrid.dtx | 6849 |
1 files changed, 6849 insertions, 0 deletions
diff --git a/macros/latex/contrib/revtex/source/ltxgrid.dtx b/macros/latex/contrib/revtex/source/ltxgrid.dtx new file mode 100644 index 0000000000..1bd35cbd62 --- /dev/null +++ b/macros/latex/contrib/revtex/source/ltxgrid.dtx @@ -0,0 +1,6849 @@ +% \iffalse meta-comment balanced on line 109 +% ltxgrid.dtx: package to change page grid, MVL. +% Copyright (c) 2009 Arthur Ogawa +% +% Disclaimer +% This file is distributed WITHOUT ANY WARRANTY; +% without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +% License +% You may distribute this file under the conditions of the +% LaTeX Project Public License 1.3c or later +% (http://www.latex-project.org/lppl.txt). +% ReadMe +% For the documentation and more detailed instructions for +% installation, typeset this document with \LaTeX. +% Maintenance Status +% This work has the LPPL maintenance status "maintained"; +% Current Maintainer of this work is Arthur Ogawa +% changes for version 4.2d--4.2f by Phelype Oleinik. +% +% This work consists of the main source file ltxgrid.dtx +% and the derived files +% ltxgrid.sty, ltxgrid.pdf +% Distribution: +% CTAN:macros/latex/contrib/revtex/ +% +% Unpacking: +% tex ltxgrid.dtx +% +% Documentation: +% latex ltxgrid.dtx; ... +% +% Programm calls to get the documentation (example): +% pdflatex ltxgrid.dtx +% makeindex -s gind.ist ltxgrid +% makeindex -s gglo.ist -o ltxgrid.gls ltxgrid.glo +% pdflatex ltxgrid.dtx +% makeindex -s gind.ist ltxgrid.idx +% pdflatex ltxgrid.dtx +% +% Installation: +% TDS:doc/latex/revtex/ +% TDS:tex/latex/revtex/ +% TDS:source/latex/revtex/ +% +% Thanks, Heiko! +% This method of letting a single .dtx file serve as both +% documentation (via latex) and installer (via tex) follows +% the example of Heiko Oberdiek. Thanks! +%<*ignore> +\begingroup + \def\x{LaTeX2e}% +\expandafter\endgroup +\ifcase + 0\expandafter\ifx\csname processbatchFile\endcsname\relax\else1\fi\ifx\fmtname\x\else 1\fi + \relax +\else + \csname fi\endcsname +%</ignore> +%<*install> +%% This file will generate documentation and runtime files +%% from ltxgrid.dtx when run through LaTeX or TeX. +\input docstrip +\preamble + +This is a generated file; +altering it directly is inadvisable; +instead, modify the original source file. +See the URL in the file README-LTXGRID.tex. + +License + You may distribute this file under the conditions of the + LaTeX Project Public License 1.3c or later + (http://www.latex-project.org/lppl.txt). + + This file is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. + +\endpreamble +\askforoverwritefalse +\keepsilent + \generate{% + %{ignore} +% \usedir{tex/latex/revtex}% + \file{ltxgrid.sty}{% + \from{ltxgrid.dtx}{package,kernel}% + }% + }% +\ifToplevel{ +\Msg{***********************************************************} +\Msg{*} +\Msg{* To finish the installation, please move} +\Msg{* ltxgrid.sty} +\Msg{* into a directory searched by TeX;} +\Msg{* in a TDS-compliant installation:} +\Msg{* texmf/tex/macros/latex/revtex/.} +\Msg{*} +\Msg{* To produce the documentation, + run ltxgrid.dtx through LaTeX.} +\Msg{*} +\Msg{* Happy TeXing} +\Msg{***********************************************************} +} +\endbatchfile +%</install> +%<*ignore> +\fi +%</ignore> +% \fi +% +% \GetFileInfo{ltxgrid.dtx} +% +% \iffalse ltxdoc klootch +%<*package> +%%% @LaTeX-file{ +%%% filename = "ltxgrid.dtx", +%%% version = "4.2f", +%%% date = "2022/06/05", +%%% author = "Arthur Ogawa (mailto:arthur_ogawa at sbcglobal.net), +%%% Phelype Oleinik (mailto:phelype.oleinik at latex-project.org), +%%% commissioned by the American Physical Society. +%%% ", +%%% copyright = "Copyright (C) 1999, 2009 Arthur Ogawa, +%%% distributed under the terms of the +%%% LaTeX Project Public License 1.3c, see +%%% ftp://ctan.tug.org/macros/latex/base/lppl.txt +%%% ", +%%% address = "Arthur Ogawa, +%%% USA", +%%% telephone = "", +%%% FAX = "", +%%% email = "mailto colon arthur_ogawa at sbcglobal.net", +%%% codetable = "ISO/ASCII", +%%% keywords = "latex, page grid, main vertical list", +%%% supported = "yes", +%%% abstract = "package to change page grid, MVL", +%%% } +%</package> +% \fi +% +% \iffalse ltxdoc klootch +% The following references the \file{README-LTXGRID} file, +% which contains basic information about this package. +% The contents of this file are generated when +% you typeset the programmer's documentation. +% Search on "{filecontents*}{README-LTXGRID}" to locate it. +% \fi\input{README-LTXGRID}% +% +% \subsection{Bill of Materials} +% +% Following is a list of the files in this distribution arranged +% according to provenance. +% +% \subsubsection{Primary Source}% +% One single file generates all. +%\begin{verbatim} +%ltxgrid.dtx +%\end{verbatim} +% +% \subsubsection{Generated by \texttt{latex ltxgrid.dtx}}% +% Typesetting the source file under \LaTeX\ +% generates the readme and the installer. +%\begin{verbatim} +%README-LTXGRID ltxgrid.ins +%\end{verbatim} +% +% \subsubsection{Generated by \texttt{tex ltxgrid.ins}}% +% Typesetting the installer generates +% the package files. +%\begin{verbatim} +%ltxgrid.sty +%\end{verbatim} +% +% \subsubsection{Documentation}% +% The following are the online documentation: +% \begin{verbatim} +%ltxgrid.pdf +% \end{verbatim} +% +% \subsubsection{Auxiliary}% +% The following are auxiliary files generated +% in the course of running \LaTeX: +% \begin{verbatim} +%ltxgrid.aux ltxgrid.idx ltxgrid.ind ltxgrid.log ltxgrid.toc +% \end{verbatim} +% +% \section{Code common to all modules}% +% +% The following may look a bit klootchy, but we +% want to require only one place in this file +% where the version number is stated, +% and we also want to ensure that the version +% number is embedded into every generated file. +% +% Now we declare that +% these files can only be used with \LaTeXe. +% An appropriate message is displayed if +% a different \TeX{} format is used. +% \begin{macrocode} +%<*driver|package> +\NeedsTeXFormat{LaTeX2e}[1995/12/01]% +%</driver|package> +% \end{macrocode} +% As desired, the following modules all +% take common version information: +% \begin{macrocode} +%<kernel&!package&!doc>\typeout{% +%<*package|doc> +\ProvidesFile{% +%</package|doc> +%<*kernel|package|doc> +ltxgrid% +%</kernel|package|doc> +%<*doc> +.dtx% +%</doc> +%<package>.sty% +%<*package|doc> +}% +%</package|doc> +% \end{macrocode} +% +% The following line contains, for once and for all, +% the version and date information. +% By various means, this information is reproduced +% consistently in all generated files and in the +% typeset documentation. +% Give credit where due. +% \begin{macrocode} +%<*doc|package|kernel> +%<version> + [2022/06/05 4.2f page grid package (portions licensed from W. E. Baxter web at superscript.com)]% \fileversion +%</doc|package|kernel> +%<kernel&!package&!doc>}% +% \end{macrocode} +% +% +% \section{The driver module \texttt{doc}} +% +% This module, consisting of the present section, +% typesets the programmer's documentation, +% generating the \file{.ins} installer and \file{README-LTXGRID} as required. +% +% Because the only uncommented-out lines of code at the beginning of +% this file constitute the \file{doc} module itself, +% we can simply typeset the \file{.dtx} file directly, +% and there is thus rarely any need to +% generate the ``doc'' {\sc docstrip} module. +% Module delimiters are nonetheless required so that +% this code does not find its way into the other modules. +% +% The \enve{document} command concludes the typesetting run. +% +% \begin{macrocode} +%<*driver> +% \end{macrocode} +% +% \subsection{The Preamble} +% The programmers documentation is formatted +% with the \classname{ltxdoc} class with local customizations, +% and with the usual code line indexing. +% \begin{macrocode} +\documentclass{ltxdoc} +\RequirePackage{ltxdocext}% +\RequirePackage[colorlinks=true,linkcolor=blue]{hyperref}% +%\ifx\package@font\@undefined\else +% \expandafter\expandafter +% \expandafter\RequirePackage +% \expandafter\expandafter +% \expandafter{% +% \csname package@font\endcsname +% }% +%\fi +\CodelineIndex\EnableCrossrefs % makeindex -s gind.ist ltxgrid +\RecordChanges % makeindex -s gglo.ist -o ltxgrid.gls ltxgrid.glo +% \end{macrocode} +% +% \subsubsection{Docstrip and info directives} +% We use so many {\sc docstrip} modules that we set the +% \texttt{StandardModuleDepth} counter to 1. +% \begin{macrocode} +\setcounter{StandardModuleDepth}{1} +% \end{macrocode} +% The following command retrieves the date and version information +% from this file. +% \begin{macrocode} +\expandafter\GetFileInfo\expandafter{\jobname.dtx}% +% \end{macrocode} +% +% \subsection{The ``Read Me'' File} +% As promised above, here is the contents of the +% ``Read Me'' file. That file serves a double purpose, +% since it also constitutes the beginining of the +% programmer's documentation. What better thing, after +% all, to have appear at the beginning of the +% typeset documentation? +% +% A good discussion of how to write a ReadMe file can be found in +% Engst, Tonya, ``Writing a ReadMe File? Read This'' +% \emph{MacTech} October 1998, p. 58. +% +% Note the appearance of the +% \cmd\StopEventually\ command, which marks the +% dividing line between the user documentation +% and the programmer documentation. +% +% The usual user will not be asked to +% do a full build, not to speak +% of the bootstrap. +% Instructions for carrying these processes +% begin the programmer's manual. +% +% \begin{macrocode} +\begin{filecontents*}{README-LTXGRID} +\title{% + A \LaTeX\ Package for changing the page grid and MVL% + \thanks{% + This file has version number \fileversion, + last revised \filedate.% + }% + \thanks{% + Version \fileversion\ \copyright\ 2019--2022 American Physical Society + }% +}% +\author{% + Arthur Ogawa% + \thanks{\texttt{mailto:arthur\_ogawa at sbcglobal.net}}% +}% +%\iffalse +% For version number and date, +% search on "\fileversion" in the .dtx file, +% or see the end of the README-LTXGRID file. +%\fi +\maketitle + +This file embodies the \classname{ltxgrid} package, +the implementation and its user documentation. + +The distribution point for this work is +\url{journals.aps.org/revtex}, +which contains the REV\TeX\ package, and includes source and documentation for this package. + +The \classname{ltxgrid} package was commissioned by the American Physical Society +and is distributed under the terms of the \LaTeX\ Project Public License 1.3c, +the same license under which all the portions of \LaTeX\ itself is distributed. +Please see \url{http://ctan.tug.org/macros/latex/base/lppl.txt} for details. + +To use this document class, you must have a working +\TeX\ installation equipped with \LaTeXe\ +and possibly pdftex and Adobe Acrobat Reader or equivalent. + +To install, retrieve the distribution, +unpack it into a directory on the target computer, +into a location in your filesystem where it will be found by \LaTeX; +in a TDS-compliant installation this would be: +\file{texmf/tex/macros/latex/revtex/.} + +To use, read the user documentation \file{src/ltxgrid.pdf}. + +\tableofcontents + +\section{Processing Instructions} + +The package file \file{ltxgrid.sty} +is generated from this file, \file{ltxgrid.dtx}, +using the {\sc docstrip} facility of \LaTeX +via |tex ltxgrid.dtx|. +The typeset documentation that you are now reading is generated from +this same file by typesetting it with \LaTeX\ or pdftex +via |latex ltxgrid.dtx| or |pdflatex ltxgrid.dtx|. + +\subsection{Build Instructions} + +You may bootstrap this suite of files solely from \file{ltxgrid.dtx}. +Prepare by installing \LaTeXe\ (and either tex or pdftex) on your computer, +then carry out the following steps: +\begin{enumerate} +\item +Within an otherwise empty directory, +typeset \file{ltxgrid.dtx} with \TeX\ or pdftex; +thereby generating the package file \file{ltxgrid.sty}. + +\item +Now typeset \file{ltxgrid.dtx} with \LaTeX\ or pdflatex; +you will obtain the typeset documentation you are now reading, +along with the file \file{README-LTXGRID}. + +Note: you will have to run \LaTeX\ twice, then \file{makeindex}, then +\LaTeX\ again in order to obtain a valid index and table of contents. + +\item +Install the following files into indicated locations within your +TDS-compliant \texttt{texmf} tree (you may need root access): +\begin{itemize} +\item +\file{$TEXMF/}\file{tex/}\file{latex/}\file{revtex/}\classname{ltxgrid.sty} +\item +\file{$TEXMF/}\file{source/}\file{latex/}\file{revtex/}\classname{ltxgrid.dtx} +\item +\file{$TEXMF/}\file{doc/}\file{latex/}\file{revtex/}\classname{ltxgrid.pdf} +\end{itemize} +where \file{TEXMF/} stands for \file{texmf-local/}, or some other \texttt{texmf} tree in your installation. +\item +Run \texttt{mktexlsr} on directory \file{$TEXMF/} (you may need root access). +\item +Build and installation are now complete; +now put a \cmd\usepackage\texttt{\{ltxgrid\}} in your document preamble! +(Note: \texttt{ltxgrid} requires package \texttt{ltxutil}.) +\end{enumerate} + +\subsection{Change Log} +\changes{4.0a}{2001/06/18}{Introduce \cs{marry@height} } +\changes{4.0a}{2001/06/18}{Introduce \cs{set@marry@height} } +\changes{4.0a}{2008/06/26 }{\cs{@yfloat}: de-fang \cs{set@footnotewidth} (see ltxutil.dtx): we have already done its job. } +\changes{4.1a}{2008/06/29}{Change \cs{LT@array@new}: restore \cs{@tabularcr} and \cs{@xtabularcr}} +\changes{4.1a}{2008/06/29}{Change \cs{LT@array@new}: set \cs{LT@LL@FM@cr} to \cs{@arraycr@array} instead of \cs{@arraycr}} +\changes{4.1a}{2008/06/29}{Repair error in \cs{endlongtable@new} involving \cs{@ifx}: argument not delimited.} +\changes{4.1b}{2008/08/04}{Get rid of the \cs{reserved@a} idiom} +\changes{4.1b}{2008/08/04}{Turn off the \cs{set@footnotewidth} mechanism; a float `knows' its proper typesetting context} +\changes{4.1b}{2008/08/04}{(AO, 452) Support length checking: show size of shipped out text.} +\changes{4.1b}{2008/08/04}{(AO, 456) Compatibility with other packages that override the output routine, following suggestion by David Kastrup.} +\changes{4.1b}{2008/08/04}{} +\changes{4.1b}{2008/08/04}{Box \cs{footbox} changed to box \cs{footsofar}} +\changes{4.1b}{2008/08/04}{Change \cs{@combinepage} to \cs{@combinepage} with argument} +\changes{4.1b}{2008/08/04}{Change \cs{@makecol} to \cs{@makecolumn} with argument} +\changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +\changes{4.1b}{2008/08/04}{New procedure \cs{@iffpsbit} replaces \cs{@getfpsbit}} +\changes{4.1b}{2008/08/04}{New procedure \cs{@output@combined@page}} +\changes{4.1b}{2008/08/04}{New procedure for showing a box contents, \cs{trace@box}} +\changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@head} headpatches \cs{@outputpage}}% +\changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@tail} tailpatches \cs{@outputpage}}% +\changes{4.1b}{2008/08/04}{Procedure \cs{balance@2} defined more transparently}% +\changes{4.1b}{2008/08/04}{Tally the height of the float} +\changes{4.1b}{2008/08/04}{Use \cs{document@inithook} instead of \cs{AtBeginDocument}} +\changes{4.1b}{2008/08/04}{Use \cs{trace@box} instead of \cs{showbox}} +\changes{4.1f}{2009/07/07}{(AO, 515) Prevent line numbering within a footnote} +\changes{4.1f}{2009/07/10}{(AO, 518) Tally register overflow when locument is long} +\changes{4.1f}{2009/07/14}{(AO, 519) \cs{footins} content must be preserved and reintegrated} +\changes{4.1f}{2009/07/15}{(AO, 519) Preserve footnotes that are in \cs{footsofar} across a page grid change} +\changes{4.1g}{2009/10/06}{(AO, 531) Fix package \classname{float} } +\changes{4.1n}{2009/12/02}{Restore the \cs{lastbox} if it is not a footnote} +\changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +\changes{4.1n}{2009/12/18}{(AO, 571) Deconstruct balanced footnotes when needed} +\changes{4.1n}{2010/01/02}{(AO, 571) Interface \cs{set@footnotewidth} for determining the set width of footnotes}% +\changes{4.1n}{2010/01/02}{(AO, 571) Footnotes, when columns are balanced or when they are composed with their column}% +\changes{4.1n}{2010/01/02}{(AO, 571) Abandon \cs{recover@footins} in favor of \cs{recover@column}}% +\changes{4.1n}{2010/01/02}{(AO, 571) Use procedures \cs{output@do@prep} and \cs{output@column@do} as dispatchers} +\changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +\changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +\changes{4.1n}{2010/01/02}{(AO, 571) footnote rule is leaders, so that it may be removed by \cs{vsplit}; mechanism of \cs{kern} signals to indicate footnote height}% +\changes{4.1o}{2010/02/02}{(AO, 576) Allow \classname{lscape} to act on \cs{@outputbox} at the right time}% +\changes{4.1p}{2010/02/24}{(AO, 583) Provide setup code also for footnotes in a one-column document}% +\changes{4.2a}{2018/12/12}{(MD) Updated name of README file and use standard fonts when typesetting}% +\changes{4.2d}{2020/09/19}{(PHO) Adapt \cs{document} and \cs{enddocument} hooks to the 2020-10-01 \LaTeX{} release.}% +\changes{4.2d}{2020/09/30}{(PHO) Correct \cs{@normalcr} patch for \LaTeX{} 2020-02-02 and later.}% +\end{filecontents*} +% \end{macrocode} +% +% \subsection{The Document Body} +% +% Here is the document body, containing only a +% \cmd\DocInput\ directive---referring to this very file. +% This very cute self-reference is a common \classname{ltxdoc} idiom. +% \begin{macrocode} +\begin{document}% +\def\revtex{REV\TeX}% +\expandafter\DocInput\expandafter{\jobname.dtx}% +\end{document} +%</driver> +% \end{macrocode} +% +% \section{Using this package} +% Once this package is installed on your filesystem, you can employ it in +% adding functionality to \LaTeX\ by invoking it in your document or document class. +% +% \subsection{Invoking the package} +% In your document, you can simply call it up in your preamble: +% \begin{verbatim} +%\documentclass{book}% +%\usepackage{ltxgrid}% +%\begin{document} +%<your document here> +%\end{document} +% \end{verbatim} +% However, the preferred way is to invoke this package from within your +% customized document class: +% \begin{verbatim} +%\NeedsTeXFormat{LaTeX2e}[1995/12/01]% +%\ProvidesClass{myclass}% +%\LoadClass{book}% +%\RequirePackage{ltxgrid}% +%<class customization commands> +%\endinput +% \end{verbatim} +% +% Note that this package requires the features of the \classname{ltxutil} package, +% available at +% \url{publish.aps.org/revtex}. +% +% Once loaded, the package gives you acccess to certain procedures, +% usually to be invoked by a \LaTeX\ command or environment, but not at the document level. +% +% \subsection{Changing the page grid}% +% This package provides two procedures, \cmd\onecolumngrid, \cmd\twocolumngrid, +% that change the page grid (it can be extended to more columns and to other page grids). +% +% They differ from standard \LaTeX's \cmd\onecolumn\ and \cmd\twocolumn\ commands in that +% they do not force a page break. Also, upon leaving a multiple-column grid, the columns are balanced. +% In other respects they work same. +% +% They differ from the grid-changing commands of Frank Mittelbach's \classname{multicol} package +% in that they allow floats of all types (single- and double column floats, that is) and +% preserve compatability with the \classname{longtable} package. +% +% These commands must be issued in vertical mode (conceivably via a \cmd\vadjust) such that +% they are ultimately present in the MVL, where they can do their work. +% Because they do not work in \LaTeX's left-right mode, they are unsuitable at the +% document level. +% Furthermore, packaging a grid command in a \cmd\vadjust, although possible, will probably +% not acheive satisfactory page layout. +% +% Page grid commands are not intended to be issued unnecessarily: only the first of +% two successive \cmd\onecolumngrid\ commands is effective; the second will be silently ignored. +% +% \DescribeMacro\onecolumngrid +% You command \LaTeX\ to return to the one-column grid with the +% \cmd\onecolumngrid\ command. If you are already in the one-column grid, this +% is a no-op. The one-column grid is considered special of all page grids, in that +% no portion of the page is held back (in \cmd\pagesofar); all items that might go +% on the current page (with the exception of floats and footnotes) are on the MVL. +% +% \DescribeMacro\twocolumngrid +% You command \LaTeX\ to return to the two-column grid with the +% \cmd\twocolumngrid\ command. If you are already in the two-column grid, this +% is a no-op. +% +% These two commands should be issued by a macro procedure that can ensure that +% \TeX\ is in outer vertical mode. +% +% \subsection{Changing the MVL}% +% +% This package also provides commands to modify the main vertical list (MVL) in a safe way. +% The scheme here is to structure, insofar possible, \TeX's MVL as follows: +%\begin{quotation} +%box or boxes\\ +%penalty\\ +%glue +%\end{quotation} +% This should be a familiar sequence. It is the prototype sequence for a vertical list, +% and is followed when \TeX\ breaks paragraphs into lines, and when \TeX\ generates +% a display math equation. +% +% If you (as a macro programmer) wish to modify the value of the penalty or glue item, +% you can use one of the MVL-altering commands to do so. Certain operations are implemented +% here; you can make up your own. +% +% Note that these commands must be issued in vertical mode, perhaps via a \cmd\vadjust\ or a \cmd\noalign. +% They can work directly if you are in inner mode (say within a parbox or a minipage). +% +% \DescribeMacro\removestuff +% You instruct \LaTeX\ to remove both the penalty and the glue item with this command. +% +% \DescribeMacro\addstuff +% You issue the \cmd\addstuff\arg{penalty}\arg{glue} command to add a penalty, glue, or both. +% If you do not wish to add one or the other, the corresponding argument should be nil. +% Note that the effect of \cmd\addstuff\ is to stack the penalties and glue items. +% Therefore, the lesser of the two penalties takes effect, +% and the two glue items add together. +% +% \cmd\addstuff\ is limited because once applied, it cannot be applied again with correct results. +% +% \DescribeMacro\replacestuff +% The \cmd\replacestuff\ command is syntactically the same as \cmd\addstuff, but works +% differently: the existing penalty and glue are replaced or modified. +% +% The specified penalty is not inserted if the existing penalty is greater than 10000 +% (that is, in case of a \cmd\nobreak), otherwise, the lower (non-zero) of the two penalties is inserted. +% +% If the specified glue has a larger natural component than the existing glue, we replace the glue. +% However, if the specified glue's natural component is negative, then the existing glue's natural component is +% changed by that amount. +% +% \cmd\replacestuff\ can be applied mutiple times bceause it retains the list structure in the canonical form. +% +% Note that we treat two penalties specially (as does \TeX): a penalty of 10000 is considered +% a garbage value, to be replaced if found. This is the signal value that \TeX\ inserts on +% the MVL replacing the penalty that caused the page break (if the page break occurred at a penalty). +% Also, a penalty of zero is indistinguishable from no penalty at all, so it will always +% be replaced by the given value. +% +% Therefore, it is highly recommended to never set any of \TeX's penalty parameters to +% zero (a value of, say, 1, is practically the same), nor should a skip parameter be set to zero +% (instead, use, say, 1sp). Also, to prevent a pagebreak, do not use a penalty of 10000, use, say +% 10001 instead. +% +% You can define your own construct that modifies the MVL: +% Define a command, say, \cmd\myadjust, as follows: +%\begin{verbatim} +%\def\myadjust#1{\noexpand\do@main@vlist{\noexpand\@myadjust{#1}}\@tempa}% +%\end{verbatim} +% that is, \cmd\myadjust\ invokes \cmd\do@main@vlist, passing it the procedure name +% \cmd\@myadjust\ along with the arguments thereof pre-expanded. +% Next, define the procedure \cmd\@myadjust: +%\begin{verbatim} +%\def\@myadjust#1{<meddle with the MVL>}% +%\end{verbatim} +% when \cmd\@myadjust\ executes, you will be in the output routine (in inner vertical mode) +% and the MVL will be that very vertical list. +% +% +% +% +% \section{Compatability with \LaTeX's Required Packages} +% Certain packages, usually ones written by members of the +% \LaTeX\ Project itself, have been designated ``required'' and +% are distributed as part of standard \LaTeX. +% These packages have been placed in a priviledged position +% vis \'a vis the \LaTeX\ kernel in that they override the definitions of certain kernel macros. +% +% Compatability between \classname{ltxgrid} and these packages is complicated +% by a number of factors. First is that \classname{ltxgrid} alters the meaning of some of the same +% kernel macros as certain of the ``required'' packages. +% Second is that fact that certain of the ``required'' packages of \LaTeX\ are incompatible with +% each other. +% +% Examples of the first kind are the \classname{ftnright}, \classname{multicol}, and \classname{longtable} +% packages. +% The \classname{ltxgrid} package is not compatible with \classname{multicol}, +% but if you are using \classname{ltxgrid}, you do not need to use \classname{ftnright} or \classname{multicol} +% anyway. The \classname{ltxgrid} package does however attempt to be compatible with \classname{longtable}. +% +% Among the ``required'' packages that are mutually incompatible are \classname{multicol} and \classname{longtable}, +% the incompatibility arising because both packages replace \LaTeX's output routine: +% if one package is active, the other must not be so. +% This state of affairs has remained essentially unchanged since the introduction of the two as \LaTeX2.09 packages in the late 1980s. +% +% The reason that \classname{ltxgrid} can remain compatible with \classname{longtable} is due to the +% introduction of a more modern architecture, the ``output routine dispatcher'', which allows all macro packages access to the +% safe processing environment of the output routine, on an equal footing. +% The relevant portions of the \classname{longtable} package are reimplemented in \classname{ltxgrid} +% to take advantage of this mechanism. +% +% Timing is critical: +% the \classname{ltxgrid} package will be incompatible with any package that +% redefines any of the kernel macros that \classname{ltxgrid} patches---if that +% package is loaded \emph{after} \classname{ltxgrid}. +% +% Hereinafter follows some notes on specific \LaTeX\ packages. +% +% \subsection{ftnright} +% Frank Mittelbach's \classname{ftnright} package effects a change to \LaTeX's +% \cmd\twocolumn\ mode such that footnotes are set at the bottom of the right-hand +% column instead of at the foot of each of the two columns. +% +% Note that it overwrites three \LaTeX\ kernel macros: \cmd\@outputdblcol, \cmd\@startcolumn, and \cmd\@makecolumn. +% Fortunately none of the three are patched by \classname{ltxgrid}, so that compatability +% is not excluded on this basis. +% +% At the same time, it changes the meaning of \cmd\footnotesize, the macro that is automatically +% invoked when setting a document's footnote into type. +% One might well argue that it is an error for the meaning of \cmd\footnotesize\ to be determined by +% a package such as \classname{ftnright}, that indeed such a choice should be made in the +% document class, or in a file such as \file{bk10.clo}. +% +% To avoid being tripped up by this misfeature in \classname{ftnright}, it is only necessary to +% reassert our meaning for \cmd\footnotesize\ later on, after \classname{ftnright} has been loaded. +% +% Note that \classname{ftnright} inserts code that demands that \LaTeX's flag \cmd\if@twocolumn\ +% is true, that is, it will complain if deployed in a \cmd\onecolumn\ document. +% It is therefore necessary for any other multicolumn package to assert that flag in order to +% avoid this package's complaint. It is an interesting question exactly why this package has +% this limitation. After all, a one-column page grid is just a degenerate case of the +% two column. +% +% \subsection{longtable} +% David Carlisle's \classname{longtable} package sets tables that can be so long as to break over pages. +% According to its author, it uses the same override of \LaTeX's output routine as +% Frank Mittelbach's \classname{multicol} package. By implication, then, it has a hard +% incompatability with the latter. +% +% The \classname{longtable} package also performs a check of whether the document is in +% \cmd\twocolumn\ mode, and declines to work if this is the case. It is not clear, however, +% that there is any true incompatability present if so. It's just that David did not see any reason +% anyone would want to set such long tables in a multicolumn document, hence the check. +% +% There does not appear to be any indication that \classname{longtable} would work less +% well under \classname{ltxgrid} than under standard \LaTeX's \cmd\twocolumn\ mode. +% Therefore, this \classname{ltxgrid} patches \classname{longtable} (if loaded) so as to provide +% compatability. In the course of which, \classname{longtable} becomes more robust +% (\classname{longtable} has mumerous bugs and incompatabilities of long standing, +% some of which are repaired by \classname{ltxgrid}). +% +% One problem remains, namely that, if a \env{longtable} environment breaks over columns +% and thereby inserts its special headers and footers at that break, and those columms are then +% balanced (due to a return to the one-column page grid), then those inserted rows +% will remain, and may no longer fall at the column break. This will, of course look +% wrong. +% +% The only way to fix this problem is to avoid doing column balancing in the way +% I have implemented here; such an enhancement to this package is possible. +% +% \subsection{multicol} +% Frank Mittelbach's \classname{multicol} package provides a page grid with many columns, +% albeit denies the placement of floats in individual columns. +% +% It establishes its own \cmd\output\ routine, which is the reason it runs afoul of +% the \classname{longtable} package. On the other hand, \classname{ltxgrid} specifically +% allows for the case where a package installs its own \cmd\output\ routine, so +% there is no incompatability on that basis. +% +% Still, it is pointless to use \classname{multicol} if you are using \classname{ltxgrid}, +% since both packages provide multicolumn page layouts. +% Therefore, \classname{multicol} is not supported by \classname{ltxgrid}. +% +% \subsection{ltxgrid} +% It has been pointed out that one of the disadvantages of adopting the \classname{ltxgrid} package is that +% it does alter the \LaTeX\ kernel. +% Any package that itself alters the \LaTeX\ kernel may be incompatible with \classname{ltxgrid}, and new packages +% (destined perhaps to become part of the successor to \LaTeXe) may break \classname{ltxgrid}. +% +% The consequence is that packages introduced in future, and future changes to \LaTeX\ may be incompatible +% with \classname{ltxgrid}. +% This is, of course, true. +% The development plan for \classname{ltxgrid} is that when such packages and \LaTeX\ kernel changes come about, +% the burden will be on \classname{ltxgrid} to change in a way that provides for continued compatability with +% those packages and \LaTeX\ kernel changes. +% +% +% \section{How \classname{ltxgrid} places footnotes} +% +% In conventional multicolumn layouts, a footnote will appear at the bottom of the column in which it is called out. +% The \classname{ltxgrid} package implements this conventional layout choice by default. +% However, other choices are possible (a la \classname{ftnright}, whose compatability with \classname{ltxgrid} has not been tested). +% +% One unusual feature of \classname{ltxgrid}'s default implementation must be mentioned, though, +% namely the case in a two-column page grid, where a footnote is followed by a temporary change to the one-column page grid +% (e.g., for a wide equation). +% In such a case, the material above the wide material is split into two columns, and a footnote whose callout +% appears in the right-hand column will nonetheless be set at the base of the left column. +% +% This arrangement was chosen because it ensures that the footnotes at the bottom of any page will appear in +% numerical order. It can be argued that this choice is ``incorrect'', but be that as it may, +% the \classname{ltxgrid} package does not foreclose on other arrangements for the footnotes. +% The package can be adapted to accomodate any page design desired. +% +% \section{Limitations in \classname{ltxgrid}'s default column balancing method}% +% +% In a multicolumn page grid, when encountering a page that is not completely full, +% it is customary to set the material in balanced columns (typically with the last column no longer than any of the others). +% Such a case also crops up when temporarily interrupting the multicolumn grid to set material on the full width of the page: +% the material on the page above the break is customarily set in balanced columns. +% +% An awkward case arises when we have already set one or more complete columns of type before encountering the need to +% balance columns. In this subset of cases, the default in \classname{ltxgrid} is to +% do an operation I call ``re-balancing'': +% the material on the page so far is pasted back together into a single column, and new, balanced column breaks are +% calculated. +% +% This scheme typically works fine, but it has a significant vulnerability: +% any discardable items trimmed at the original column break are lost, never to be retrieved. +% Consequently, after re-balancing, an element like, say, a section head can fail to have the correct amount of whitespace above. +% +% This problem is due to an unfortunate optimization in \TeX, wherein a certain class of nodes is trimmed from the +% top of main vertical list upon returning from the output routine: +% any penalty, glue, or leader node falls in to this class of discardable nodes, +% and trimming proceeds until a non-discardable node (such as a box, or rule) is encountered. +% It gets better: a third class of nodes is transparent to this trimming process; +% they are neither discarded nor do they halt the process of trimming: +% mark nodes and all whatsits fall into this class of transparent nodes; +% they are quietly passed over during trimming. +% +% An alternative approach for \TeX\ to take would have been, +% rather than discarding the node entirely, to simply \emph{mark} it as discarded. +% (Implementors of extended \TeX, please note!) +% Then, upon shipping out, such nodes would not make it into the DVI. +% \TeX's optimization, driven by the small computer architectures current when it was developed, +% does save mem, but at the cost of revisiting page breaks in a reliable way. +% +% FIXME: how to fix a column break in the above case? Widetext? +% +%\StopEventually{} +% +% \section{Implementation of package} +% +% Special acknowledgment: this package uses concepts pioneered +% and first realized by William Baxter (mailto:web at superscript.com) +% in his SuperScript line of commercial typesetting tools, and +% which are used here with his permission. His thorough understanding +% of \TeX's output routine underpins the entire \classname{ltxgrid} +% package. +% +% \subsection{Beginning of the \file{ltxgrid} {\sc docstrip} module} +% Requires the underpinnings of the \classname{ltxkrnext} package. +% \begin{macrocode} +%<*package> +\def\package@name{ltxgrid}% +\expandafter\PackageInfo\expandafter{\package@name}{% + Page grid for \protect\LaTeXe, + by A. Ogawa (arthur_ogawa at sbcglobal.net)% +}% +\RequirePackage{ltxutil}% +%</package> +% \end{macrocode} +% +% \subsection{Banner}% +% \begin{macrocode} +%<*kernel> +% \end{macrocode} +% +% \subsection{Sundry}% +% Here are assorted macro definitions. +% \begin{macro}{\lineloop} +% \begin{macro}{\linefoot} +% The (document-level) command \cmd\lineloop\ sets numbered lines until the +% specified count is reached. +% The command \cmd\linefoot\ sets a single, automatically numbered line, but with a footnote (with the specified label); +% it automatically increments the line counter. +% These commands are typically used to construct test documents. +% +% Because the counter is globally advanced and never reset, successive +% calls to \cmd\lineloop\ should have an argument ever larger. +% The formatted output will have each line labeled with its ordinal number. +% \begin{macrocode} +\newcounter{linecount} +\def\loop@line#1#2{% + \par + \hb@xt@\hsize{% + \global\advance#1\@ne + \edef\@tempa{\@ifnum{100>#1}{0}{}\@ifnum{10>#1}{0}{}\number#1}% + \@tempa\edef\@tempa{\special{line:\@tempa}}\@tempa + \vrule depth2.5\p@#2\leaders\hrule\hfil + }% +}% +\def\lineloop#1{% + \loopwhile{\loop@line\c@linecount{}\@ifnum{#1>\c@linecount}}% +}% +\def\linefoot#1{% + \loop@line\c@linecount{% + \footnote{% + #1\special{foot:#1}\vrule depth2.5\p@\leaders\hrule\hfill + }% + }% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \subsection{Mark Components}% +% +% Override LaTeX's mark macros to allow more components. +% +% We remain bound by the weakness of LaTeX's scheme in that +% one cannot emulate the action of \TeX\ whereby +% material with marks can be inserted in the middle of +% a vertical list such that the marks are reliably calculated. +% If we did that, \cmd\@themark\ would no longer be utilized. +% +% A more robust scheme involves placing all marks (component and value) +% into a list (using global scoping, i.e., \cmd\gdef), +% and using \cmd\@@mark to place an index on that list into the MVL. +% Then, e.g., \cmd\@@botmark signifies the place where that list is to be cut, +% and the \cmd\botmark\ of any component is +% the value of the last element of the cut +% list having the given component. The \cmd\firstmark\ and \cmd\topmark\ +% can likewise be defined relative to \cmd\@@firstmark\ and \cmd\@@topmark, +% except in the latter case, we want the first following the cut instead of the last +% preceding the cut. +% +% The limitation of this scheme is its demands upon \TeX's mem. +% The list of marks would need to be trimmed back to, effectively, +% \cmd\topmark\ at the beginning of every page. +% +% This approach is not yet part of the extended LaTeX kernel. +% +% \begin{macro}{\@@mark} +% \begin{macro}{\@@topmark} +% \begin{macro}{\@@firstmark} +% \begin{macro}{\@@botmark} +% \begin{macro}{\@@splitfirstmark} +% \begin{macro}{\@@splitbotmark} +% Remember primitives under a new set of names. +% \begin{macrocode} +\let\@@mark\mark +\let\@@topmark\topmark +\let\@@firstmark\firstmark +\let\@@botmark\botmark +\let\@@splitfirstmark\splitfirstmark +\let\@@splitbotmark\splitbotmark +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsubsection{Procedures that expose the component data structure}% +% This portion of the code exposes the internal representation of +% the mark components. If we wish to add more components, we will have to revise +% these macro definitions: +% \cmd\@themark, +% \cmd\nul@mark, +% \cmd\set@mark@netw@, +% \cmd\set@marktw@, +% \cmd\set@markthr@@, +% \cmd\get@mark@@ne, +% \cmd\get@mark@tw@, +% \cmd\get@mark@thr@@, +% \cmd\get@mark@f@ur. +% +% \begin{macro}{\@themark} +%FIXME: is it safer to eliminate \cmd\@themark\ in favor of a message that evaluates \cmd\@@botmark? +% +% Note: these definitions expose the data structure of mark components. +% \begin{macrocode} +\def\@themark{{}{}{}{}}% +\def\nul@mark{{}{}{}{}\@@nul}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\set@mark@netw@} +% \begin{macro}{\set@marktw@} +% \begin{macro}{\set@markthr@@} +% These procedures insert the new value of a particular mark component into the given argument. +% They expose the data structure of mark components. +% +% \begin{macrocode} +\def\set@mark@netw@#1#2#3#4#5#6#7{\gdef#1{{#6}{#7}{#4}{#5}}\do@mark}% +\def\set@marktw@#1#2#3#4#5#6{\gdef#1{{#2}{#6}{#4}{#5}}\do@mark}% +\def\set@markthr@@#1#2#3#4#5#6{\gdef#1{{#2}{#3}{#6}{#5}}\do@mark}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\get@mark@@ne} +% \begin{macro}{\get@mark@tw@} +% \begin{macro}{\get@mark@thr@@} +% \begin{macro}{\get@mark@f@ur} +% These procedures retreive the value of a particular mark component. +% They expose the data structure of mark components. +% \begin{macrocode} +\def\get@mark@@ne#1#2#3#4#5\@@nul{#1}% +\def\get@mark@tw@#1#2#3#4#5\@@nul{#2}% +\def\get@mark@thr@@#1#2#3#4#5\@@nul{#3}% +\def\get@mark@f@ur#1#2#3#4#5\@@nul{#4}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsubsection{Procedures that do not expose the component data structure}% +% +% \begin{macro}{\mark@netw@} +% \begin{macro}{\marktw@} +% \begin{macro}{\markthr@@} +% These procedures insert the new value of a particular mark component into \cmd\@themark, +% then execute \cmd\do@mark. +% They constitute the implementation layer for mark components one, two, and three. +% An analogous procedure for component four could be defined; call it \cmd\markf@ur. +% +% \begin{macrocode} +\def\mark@netw@{\expandafter\set@mark@netw@\expandafter\@themark\@themark}% +\def\marktw@{\expandafter\set@marktw@\expandafter\@themark\@themark}% +\def\markthr@@{\expandafter\set@markthr@@\expandafter\@themark\@themark}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\do@mark} +% \begin{macro}{\do@@mark} +% Access procedures \cmd\mark (AKA \cmd\@@mark). +% The \cmd\do@mark\ procedure is used when a mark is being put down into the MVL; +% \cmd\do@@mark\ when this happens in the output routine. +% \begin{macrocode} +\def\do@mark{\do@@mark\@themark\nobreak@mark}% +\def\do@@mark#1{% + \begingroup + \let@mark + \@@mark{#1}% + \endgroup +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\let@mark} +% \begin{macro}{\nobreak@mark}% +% The procedure that makes \cmd\csname s robust within a mark. +% Use \cmd\appdef\ and \cmd\robust@\ to extend the list. +% \begin{macrocode} +\def\let@mark{% + \let\protect\@unexpandable@protect + \let\label\relax + \let\index\relax + \let\glossary\relax +}% +\def\nobreak@mark{% + \@if@sw\if@nobreak\fi{\@ifvmode{\nobreak}{}}{}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \subsubsection{Using mark components}% +% +% These procedures use the component mark mechanism to implement +% a mark component that remembers the current environment (used in page makeup) +% and the the two mark components left over from the original \LaTeX. +% The fourth component is presently unused. +% +% \begin{macro}{\mark@envir} +% The third mark component's access procedures. +% The \cmd\mark@envir\ and \cmd\bot@envir\ commands are a good model of how to write +% access procedures for a new mark component. +% \begin{macrocode} +\def\mark@envir{\markthr@@}% +\def\bot@envir{% + \expandafter\expandafter + \expandafter\get@mark@thr@@ + \expandafter\@@botmark + \nul@mark +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\markboth} +% \begin{macro}{\markright} +% \begin{macro}{\leftmark} +% \begin{macro}{\rightmark} +% Set procedures for legacy components. +% \begin{macrocode} +\def\markboth{\mark@netw@}% +\def\markright{\marktw@}% +% \end{macrocode} +% +% Retrieval procedures for legacy mark components. +% The procedure for retrieving the first component from \cmd\botmark\ +% and the second component from \cmd\firstmark have names in \LaTeX; +% they are called, respectively, \cmd\leftmark\ and \cmd\rightmark. +% +% It is possible to retrieve the components of \cmd\topmark\ +% as well: use \cmd\saved@@topmark. +% \begin{macrocode} +\def\leftmark{% + \expandafter\expandafter + \expandafter\get@mark@@ne + \expandafter\saved@@botmark + \nul@mark +}% +\def\rightmark{% + \expandafter\expandafter + \expandafter\get@mark@tw@ + \expandafter\saved@@firstmark + \nul@mark +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% +% \subsection{Output Super-routine}% +% +% We want to change \LaTeX's output routine, but do not wish to remain vulnerable +% to interference from such ``required'' packages as +% \classname{multicol} (authored by Frank Mittelbach) +% and \classname{longtable} (authored by David P. Carlisle), which +% swap in their own output routines when the respective package is active. +% +% The better mechanism, used here, is due to William Baxter (web at superscript.com), +% who has allowed his several ideas to be used in this package. +% +% In what follows, we effectively wrap up the old \LaTeX\ output routine inside +% a new, more flexible ``super routine''. When the output routine is called, +% the ``super routine'' acts as a dispatcher. If the old routine is needed, it is called. +% +% If a package attempts to substitute in their own output routine, they will effectively +% be modifying a token register by the name of \cmd\output. +% The primitive \cmd\output\ is now known by a different name, which should no longer be +% necessary to use. +% +% Usage note: to make a visit to the output routine employing the dispatcher, enter +% with a value of \cmd\outputpenalty\ that corresponds to a macro. Defining as follows: +%\begin{verbatim} +%\@namedef{output@10000}{<your code here>}% +%\end{verbatim} +% by convention, your output routine should void out \cmd\box\cmd\@cclv. +% +% In rewriting \LaTeX's output dispatcher +% in a much simpler form, we also avoid the sin of multiple \cmd\shipout s +% within a single visit to the output routine. +% +% Conceptually, we divide visits to the output routine into two classes. +% The first involves natural page breaks +% (at a \cmd\newpage\ or when \cmd\pagetotal $>$ \cmd\pagegoal) +% and usually resulting in \cmd\box\cmd\@cclv\ either being shipped out or +% salted away (e.g., each column in a multicolumn layout). +% We might call this class the ``natural output routines''; the \cmd\outputpenalty\ +% will never be less than $-10000$. +% Furthermore, we ensure that \cmd\holdinginserts\ is cleared when +% calling such routines. +% +% The other class involves a forced visit to the output routine +% via a large negative penalty ($< -10000$). They do not generally +% result in a \cmd\shipout\ of \cmd\box\cmd\@cclv: they may be dead cycles. +% We provide a mechanism (call it a ``one-off'' output routine) that allows +% us to specify certain processing to be done when \TeX\ reaches +% the current position on the page. +% +% One-off output routines themselves fall into two divisions, ones +% that process \cmd\box\cmd\@cclv, and ones that work on the main vertical list (MVL). +% The former are typified by changes to the page grid, perhaps +% even column balancing. +% The latter involve the insertion of penalties or glue and the processing of floats. +% +% The natural output routine is a single procedure. We have not introduced multiple +% natural output routines based on the \cmd\outputpenalty\ because \TeX\ does not +% support such a thing: \TeX\ sometimes lays down a penalty whose value is the sum +% of other penalties. Because of this, we cannot depend on the value of \cmd\outputpenalty\ +% in such areas. +% +% We do introduce flexibility in the form of a mechanism for patching into the +% natural output routine. Three hooks are offered, allowing a procedure +% to prepare for the upcoming visit to the output routine, +% access to \cmd\box\cmd\@cclv, and after doing \cmd\shipout\ (or otherwise +% committing the material to the page). +% +% Environments, commands, and even packages can install their +% own procedures into these hooks. +% For instance, if the longtable package is loaded, it will install +% its procedures, but those procedures will punt if the page break +% being processed does not actually fall within a longtable environment. +% +% \begin{macro}{\primitive@output} +% Here we remember the \TeX\ primitive \cmd\output\ and its value, +% and then proceed to take over the \cmd\csname\ of \cmd\output, +% making it a \cmd\toks\ register and installing the old value of +% the output routine. +% \begin{macrocode} +\let\primitive@output\output +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\output@latex} +% \begin{macro}{\output} +% Grab the tokens in \cmd\the\cmd\output\ (but without the extra set of braces). +% The value of \cmd\toks@\ must remain untouched until loaded into the appropriate token +% register; this is done a few lines below. +% \begin{macrocode} +\long\def\@tempa#1\@@nil{#1}% + \toks@ +\expandafter\expandafter +\expandafter{% +\expandafter \@tempa + \the\primitive@output + \@@nil + }% +\newtoks\output@latex +\output@latex\expandafter{\the\toks@}% +\let\output\output@latex +% \end{macrocode} +% +% A comment on compatibility with other packages that co-opt the output routine. +% +% Somewhere on the LaTeX-L list, David Kastrup has urged macro writers to take over +% the output routine in such a way that others can do likewise. How is this to be +% accomplished? +% +% Consider what the \classname{lineno} package does when it loads. +% \begin{enumerate} +% \item +% It does \cmd\let\ cmd\@tempa\ \cmd\output. +% This has the effect of identifying \cmd\@tempa\ with the +% \cmd\toks\ register we created above to hold the old output routine of \LaTeX. +% Let us say that was \cmd\toks14. +% \item +% \classname{lineno} itself effectively does \cmd\newtoks\ \cmd\@LN@output, +% which assigns that \cmd\csname\ to \cmd\toks 15. +% \item +% It loads \cmd\@LN@output\ with the contents of \cmd\@tempa +% (that is, \cmd\toks14, our copy of \LaTeX's output routine). +% \item +% Then it loads \cmd\@tempa\ with its own desired procedure, +% to be executed at \cmd\output\ time, thereby taking over what it thinks is the output routine, +% but which is in reality the procedure \revtex\ executes when it wants to pass control +% to \LaTeX's original output routine. +% \item +% It then does \cmd\let\ \cmd\output\ \cmd\@LN@output, +% which now identifies \cmd\output\ with \cmd\toks15, the output routine of \classname{lineno}. +% \item +% When the \cmd\output\ routine is triggered, +% the primitive output routine \cmd\primitive@output\ is executed, and if +% appropriate, control is passed to \cmd\output@latex, which \revtex\ had loaded with the old +% \LaTeX\ output routine, but which is presently loaded with that of \classname{lineno}. +% \item +% The output routine of \classname{lineno} is executed, and if appropriate control is passed +% to \cmd\@LN@output, the old output routine of \LaTeX. +% \item +% Furthermore, the \cmd\csname\ \cmd\output\ now points to \cmd\@LN@output\ (\cmd\toks15). +% This means that someone coming in after \classname{lineno} to take over the output routine +% will actually get executed after that of \classname{lineno}, but before \LaTeX. +% \end{enumerate} +% As you can see, the process of taking over the output routine may continue until all of the +% \cmd\toks\ registers have been allocated. +% If, say, \classname{newpackage} would itself like to take over the output routine, +% and if it uses the above set of steps, then when the output routine is triggered, the order +% of execution is \revtex, then \classname{lineno}, then \classname{newpackage}, then \LaTeX. +% Each new package inserts itself on front of \LaTeX. +% \end{macro} +% \end{macro} +% +% \begin{macro}{\dispatch@output} +% \changes{4.1b}{2008/08/04}{(AO, 456) Compatibility with other packages that override the output routine, following suggestion by David Kastrup.} +% We now install our own output routine in place of the original +% output routine of \LaTeX, which is still available as \cmd\the\ \cmd\output. +% +% The output routine is simply the procedure \cmd\dispatch@output. +% It either dispatches to a procedure based on a particular value of +% \cmd\outputpenalty\ or it executes \cmd\the\cmd\output@latex\ tokens. +% \begin{macrocode} +\primitive@output{\dispatch@output}% +\def\dispatch@output{% + \let\par\@@par +% \end{macrocode} +% Try to interpret \cmd\outputpenalty\ as a dispatcher to a message handler, +% its value is, e.g., \cmd\do@startpage@pen. +% \begin{macrocode} + \expandafter\let\expandafter\output@procedure\csname output@\the\outputpenalty\endcsname +% \end{macrocode} +% If we have failed to find a dispatcher, then settle for \cmd\output@latex. +% \begin{macrocode} + \@ifnotrelax\output@procedure{}{% + \expandafter\def\expandafter\output@procedure\expandafter{\the\output@latex}% + }% +% \end{macrocode} +% Now test if the dispatcher is the special case of \cmd\execute@message@pen, in which case execute the \cmd\@message@saved. +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \begin{macrocode} + \expandafter\@ifx\expandafter{\csname output@-\the\execute@message@pen\endcsname\output@procedure}{% + \let\output@procedure\@message@saved + }{}% + \ltxgrid@info@sw{\class@info{\string\dispatch@output}\say\output@procedure\saythe\holdinginserts}{}% + \outputdebug@sw{\output@debug}{}% + \output@procedure +}% +% \end{macrocode} +% +% \begin{macrocode} +\def\set@output@procedure#1#2{% + \count@\outputpenalty\advance\count@-#2% + \expandafter\let\expandafter#1\csname output@\the\count@\endcsname +}% +% \end{macrocode} +% +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% The following procedure is executed at the beginning of each visit to the output routine, +% contingent on the level of diagnostics specified. +% However, it bails out when the visit is part of a tight sequence of visits to the output routine. +% \begin{macrocode} +\def\output@debug{% + \def\@tempa{\save@message}% + \@ifx{\output@procedure\@tempa}{% + \true@sw + }{% + \@ifnum{\outputpenalty=-\save@column@insert@pen}{% + \@ifnum{\holdinginserts>\z@}% + }{% + \false@sw + }% + }% + {}{\output@debug@}% +}% +\def\output@debug@{% +%<ignore> \saythe\inputlineno + \saythe\outputpenalty + \saythe\interlinepenalty + \saythe\brokenpenalty + \saythe\clubpenalty + \saythe\widowpenalty + \saythe\displaywidowpenalty + \saythe\predisplaypenalty + \saythe\interdisplaylinepenalty + \saythe\postdisplaypenalty + \saythe\badness + \say\thepagegrid + \saythe\pagegrid@col + \saythe\pagegrid@cur +%<ignore> \say\bot@envir + \saythe\insertpenalties +%<ignore> \say\@@topmark +%<ignore> \say\saved@@topmark +%<ignore> \say\@@firstmark +%<ignore> \say\saved@@firstmark + \say\@@botmark +%<ignore> \say\saved@@botmark + \saythe\pagegoal + \saythe\pagetotal + \saythe{\badness\@cclv}% + \say\@toplist + \say\@botlist + \say\@dbltoplist + \say\@deferlist + \trace@scroll{% + \showbox\@cclv + \showbox\@cclv@saved + \showbox\pagesofar +% \end{macrocode} +% Klootch! The following line provides only for two-column page grid; if debugging more columns, you must +% add more statements here. +% \begin{macrocode} + \showbox\csname col@1\endcsname + \showbox\footsofar + \showbox\footins + \showbox\footins@saved + \showlists + }% +}% +\@ifxundefined{\outputdebug@sw}{% + \@booleanfalse\outputdebug@sw +}{}% +\def\trace@scroll#1{\begingroup\showboxbreadth\maxdimen\showboxdepth\maxdimen\scrollmode#1\endgroup}% +\def\trace@box#1{\trace@scroll{\showbox#1}}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@outputpage} +% \begin{macro}{\@outputpage@head} +% \begin{macro}{\@outputpage@tail} +% \changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@tail} tailpatches \cs{@outputpage}}% +% \changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@head} headpatches \cs{@outputpage}}% +% The procedure \cmd\@outputpage\ of standard \LaTeX\ is the sole place where a \cmd\shipout\ is carried out. +% The procedures that build \cmd\@outputbox\ just before a page is shipped out by \cmd\@outputpage\ are: +% \cmd\@makecolumn, +% \cmd\@combinepage, and +% \cmd\@combinedblfloats. +% +% We need to head- and tailpatch this procedure, so we perform here +% the only modifications to that procedure that are essential. +% Elsewhere, we will build up the meanings of \cmd\@outputpage@head\ and \cmd\@outputpage@tail. +% \begin{macrocode} +\prepdef\@outputpage{\@outputpage@head}% +\let\@outputpage@head\@empty +\appdef\@outputpage{\@outputpage@tail}% +\let\@outputpage@tail\@empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\show@box@size} +% \begin{macro}{\show@text@box@size} +% \begin{macro}{\show@pagesofar@size} +% \begin{macro}{\show@box@size@sw} +% \begin{macro}{\total@text} +% \changes{4.1b}{2008/08/04}{(AO, 452) Support length checking: show size of shipped out text.} +% Procedure \cmd\show@box@size\ is a diagnostic for the sizes of boxes; +% the boolean \cmd\show@box@size@sw\ turns it on and off. +% \begin{macrocode} +\def\show@box@size#1#2{% + \show@box@size@sw{% + \begingroup + \setbox\z@\vbox{\unvcopy#2\hrule}% + \class@info{Show box size: #1^^J% + (\the\ht\z@\space X \the\wd\z@) + \the\c@page\space\space\the\pagegrid@cur\space\the\pagegrid@col + }% + \endgroup + }{}% +}% +% \end{macrocode} +% Procedure \cmd\show@text@box@size\ tallies the size of the indicated column. +% If \cmd\box\ \cmd\pagesofar\ is a factor, then its height has been memorized +% in the depth of the tally box. +% +% \changes{4.1f}{2009/07/10}{(AO, 518) Tally register overflow when locument is long} +% \begin{macrocode} +\def\show@text@box@size{% + \show@box@size{Text column}\@outputbox + \tally@box@size@sw{% + \@ifdim{\wd\@outputbox>\z@}{% + \dimen@\ht\@outputbox\divide\dimen@\@twopowerfourteen + \advance\dimen@-\dp\csname box@size@\the\pagegrid@col\endcsname + \@ifdim{\dimen@>\z@}{% + \advance\dimen@ \ht\csname box@size@\the\pagegrid@col\endcsname + \global\ht\csname box@size@\the\pagegrid@col\endcsname\dimen@ + \show@box@size@sw{% + \class@info{Column: \the\dimen@}% + }{}% + }{}% + }{}% + \global\dp\csname box@size@\the\pagegrid@col\endcsname\z@ + }{}% +}% +% \end{macrocode} +% Take the height of \cmd\box\ \cmd\pagesofar\ into account. +% \begin{macrocode} +\def\show@pagesofar@size{% + \show@box@size{Page so far}\pagesofar + \dimen@\ht\pagesofar\divide\dimen@\@twopowerfourteen + \global\dp\csname box@size@1\endcsname\dimen@ + \show@box@size@sw{% + \class@info{Pagesofar: \the\dimen@}% + }{}% +}% +\@booleanfalse\tally@box@size@sw +\@booleanfalse\show@box@size@sw +\expandafter\newbox\csname box@size@1\endcsname +\expandafter\setbox\csname box@size@1\endcsname\hbox{}% +\expandafter\newbox\csname box@size@2\endcsname +\expandafter\setbox\csname box@size@2\endcsname\hbox{}% +\def\total@text{% + \@tempdima\the\ht\csname box@size@2\endcsname\divide\@tempdima\@twopowertwo\@tempcnta\@tempdima + \@tempdimb\the\ht\csname box@size@1\endcsname\divide\@tempdimb\@twopowertwo\@tempcntb\@tempdimb + \class@info{Total text: Column(\the\@tempcnta pt), Page(\the\@tempcntb pt)}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsection{Further thoughts about inserts} +% +% The only safe way to deal with inserts is to either set \cmd\holdininserts\ or +% to commit to using whatever insert comes your way: you cannot change your mind +% once you see a non-void \cmd\box\cmd\footins, say. +% +% Therefore all output routine processing must proceed with \cmd\holdinginserts\ set +% until you are sure of the material to be committed to the page. At that point, you +% can clear \cmd\holdinginserts, spew \cmd\box\cmd\@cclv, put down the appropriate penalty, +% and exit, with the knowledge that \TeX\ will re-find the same pagebreak, this time +% visiting the output routine with everything, including inserts, in their proper +% place. +% This technique applies to split elements (screens, longtable, index) as well as to +% manufactured pages (float pages and clearpage pages). +% +% Therefore, the output routine must not make assumptions about whether \cmd\holdinginserts\ +% should be cleared; instead this must be left to the one-off output routines or the natural output routine. +% +% If we are manufacturing pages (``float page processing''), and if \cmd\pagegoal\ is not equal to +% \cmd\vsize, then inserts are at hand, and our criterion should take into account the insert +% material, even though we cannot measure its height based on the size of \cmd\box\cmd\footins\ +% (because \cmd\holdinginserts\ is set, you see). +% +% It would be better to take the complement of \cmd\floatpagefraction\ and use that +% as a standard for the looseness of the page. Since \cmd\pagegoal\ reflects the inserted material, +% the criterion becomes the difference of the aggregate height of the floats and the \cmd\pagegoal\ +% versus this "page looseness" standard. +% +% As a check, consider what happens if we bail out: \cmd\@deferlist\ has never been touched, so it +% requires no attention. Also, \cmd\holdinginserts\ has never been cleared, so inserts require +% no attention. So we only have to ensure that marks are preserved, which is already taken +% care of by the message handler mechanism. +% +% If we are doing ordinary page cutting, then the scheme would be to detect whether we are within +% a screen (or longtable as may be), do the adjustment to the page height, and return, but this time +% with \cmd\holdinginserts\ cleared. Upon reentering the output routine, we may or may not be within +% the screen environment, but we are now sure to have a final page break, and we can commit this +% material (by shipping out or by saving it out as a full column). +% +% In the above, the first of the two visits to the output routine is a dead cycle and requires +% propagation of marks, but nothing else. +% +% \subsection{The difference between inserts and floats} +% +% While revisiting this package in 2008, I needed to clarify under what circumstances inserts +% would be added to the \cmd\pagesofar. My conclusion is that I had been treating them +% exactly the same as floats, but that was a mistake. +% +% Floats can be committed at the top of a column, in the middle, or at the bottom. +% Footnotes (the only \cmd\insert\ that is used in \LaTeX) may only be committed at the bottom +% of a column. So, it was necessary to provide two versions of \cmd\@combinepage, one +% that committed \cmd\insert s, and the other that did not, the former used only when +% a column of text was committed. Note that even after a column is committed, we could change our minds: +% for instance if in multicolumn grid and we decide to balance the columns. +% +% +% \subsection{The natural output routine} +% +% Here is the portion of the output routine that fields cases not handled by +% the dispatcher. +% +% The default is to ship out a page and then look around for more material +% that might constitute a ``float page''. However, because \cmd\holdinginserts\ +% is normally set, this output routine must first have a dead cycle and +% come back again with \cmd\holdinginserts\ cleared. +% Then, after shipping out, it puts down a message that +% will manufacture zero or more float pages, finally terminating +% with a procedure that commits floats to a new unfinished page. +% +% To accomodate special processing, we execute hooks whose name is based +% on the value of the "envir" mark component. The default is "document", +% ensured by an initial mark of that value; the associated procedures +% are all nil. Any unknown envir value will "\cmd\relax\ out". +% +% The test made by \cmd\toggle@insert\ tells whether we are on our first visit to +% the output routine (with \cmd\holdinginserts\ still positive), or our second +% (with \cmd\holdinginserts\ zeroed). The output routine will toggle the setting. +% +% The commands \cmd\hold@insertions\ and \cmd\move@insertions\ respectively +% clear and set \cmd\holdinginserts, so this procedure effectively +% clears \cmd\holdinginserts\ just long enough to pick up the insertions. +% Important: any output routine that clears \cmd\holdinginserts\ +% must guarentee that it is restored on the subsequent visit to the output routine. +% Or, to put it another way, if an output routine detects that \cmd\holdinginserts\ +% is cleared, it should take it upon itself to restore it to a positive value before exiting. +% +% The branch with \cmd\holdinginserts\ set is executed first; the other +% branch follows on practically immediately thereafter. In the first branch, +% we simply execute the appropriate hook and then execute a dead cycle. +% +% In the branch with \cmd\holdinginserts\ cleared, the procedure +% builds up the current column, which is now complete, with \cmd\@makecolumn, then +% dispatches to the shipout routine associated with the current page grid, \cmd\output@column@. +% At the end, it triggers the execution of an output routine to prepare the next column (or page). +% +% \subsection{Natural output routine}% +% +% \begin{macro}{\natural@output} +% \begin{macro}{\output} +% Here is the output routine that handles natural pagebreaks: +% we now have page that needs to be shipped out or a portion of a page that is ready to be committed to the page grid. +% Processing is of necessity divided into phases, \cmd\output@holding\ is executed upon first encountering the natural page-breaking point, while inserts are being held. +% The second phase, \cmd\output@moving, is set in motion by the first: here the same material (in most cases) will be processed with \cmd\holdinginserts\ cleared, +% and the insertions (e.g., footnotes) are split off into their assigned box registers. +% \begin{macrocode} +\def\natural@output{\toggle@insert{\output@holding}{\output@moving}}% +\output@latex{\natural@output}% +% \end{macrocode} +% +% In accordance with the scheme suggested by David Kastrup for allowing another output routine +% to slip itself into ours, we use a token register called \cmd\output. +% However, we reserve the ability to restore things if we so desire. +% This we must do in the case of the \filename{lineno.sty} package, because its functionality +% is best served by being integrated into our own dispatcher-based output routine. +% +% To restore our own output routine, we can repeat the above assignment, +% \begin{verbatim} +%\output@latex{\natural@output}% +% \end{verbatim} +% some time before the document begins. +% \end{macro} +% \end{macro} +% +% \begin{macro}{\output@holding} +% \begin{macro}{\@if@exceed@pagegoal} +% The procedure \cmd\output@holding\ +% is our first cycle through the output routine; \cmd\holdinginserts\ is still set. +% We give the current environment a heads up +% (it is through this means that \classname{longtable} sets its running header and footer), +% then we execute a dead cycle, which should propagate marks. +% +% One corner case that can crop up is the presence of a single unbreakable chunk whose size is larger +% than \cmd\vsize. +% Doing a dead cycle under such circumstances will not find the same breakpoint as this time +% (remember we threw in a \cmd\mark\ node). +% Instead, we attempt to remove the excess height of the material, so we can continue to propagate marks. +% +% The corner case is at hand if the natural size of \cmd\box\cmd\@cclv\ exceeds \cmd\pagegoal\ and +% the contents cannot be shrunk to fit. +% +% \changes{4.1b}{2008/08/04}{New procedure for showing a box contents, \cs{trace@box}} +% \begin{macrocode} +\def\output@holding{% + \csname output@init@\bot@envir\endcsname + \@if@exceed@pagegoal{\unvcopy\@cclv}{% + \setbox\z@\vbox{\unvcopy\@cclv}% + \outputdebug@sw{\trace@box\z@}{}% + \dimen@\ht\@cclv\advance\dimen@-\ht\z@ + \dead@cycle@repair\dimen@ + }{% + \dead@cycle + }% +}% +\def\@if@exceed@pagegoal#1{% + \begingroup + \setbox\z@\vbox{#1}% + \dimen@\ht\z@\advance\dimen@\dp\z@ + \outputdebug@sw{\saythe\dimen@}{}% + \@ifdim{\dimen@>\pagegoal}{% + \setbox\z@\vbox{\@@mark{}\unvbox\z@}% + \splittopskip\topskip + \splitmaxdepth\maxdepth + \vbadness\@M + \vfuzz\maxdimen + \setbox\tw@\vsplit\z@ to\pagegoal + \outputdebug@sw{\trace@scroll{\showbox\tw@\showbox\z@}}{}% + \setbox\tw@\vbox{\unvbox\tw@}% + \@ifdim{\ht\tw@=\z@}{% + \ltxgrid@info{Found overly large chunk while preparing to move insertions. Attempting repairs}% + \aftergroup\true@sw + }{% + \aftergroup\false@sw + }% + }{% + \aftergroup\false@sw + }% + \endgroup +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\output@moving} +% \begin{macro}{\@cclv@nontrivial@sw} +% The procedure \cmd\output@moving\ +% is our second cycle through the output routine; \cmd\holdinginserts\ is now cleared, +% and \cmd\insert s will have been split off into their respective box registers, like \cmd\footins. +% +% \begin{enumerate} +% \item +% Set the values of \cmd\topmark\ and \cmd\firstmark. +% \item +% If we got here because of a \cmd\clearpage\ command, remove the protection box that this mechanism has left on the MVL. +% \item +% If the contents of \cmd\box\cmd\@cclv\ are non-trivial, commit it to the current page (as a column) or ship it out, as the case may call for. +% \item +% If not, discard it (we are at the end of \cmd\clearpage\ processing). +% \item +% Set various values, including the available space for setting type on the next column (\cmd\@colroom). +% \end{enumerate} +% +% The processing for a non-trivial \cmd\box\cmd\@cclv\ are: +% \begin{enumerate} +% \item +% Execute the head procedure for the current environment. +% \item +% Make up a column and ship it out (or commit it to the current page) via a procedure keyed to the current page grid. +% \item +% Put down an interrupt for \cmd\do@startcolumn@pen: this will force a visit to the output routine for the +% purpose of committing floats to the next column. +% \item +% Possibly put down an interrupt to continue \cmd\clearpage\ proccessing. +% \item +% Execute the tail procedure for the current environment. +% \end{enumerate} +% +% +% The processing for a trivial \cmd\box\cmd\@cclv\ are: +% \begin{enumerate} +% \item +% Void out \cmd\box\cmd\@cclv\ and give appropriate warning messages and diagnostics. +% \item +% Put down the same interrupts as for the non-trivial case above. +% \end{enumerate} +% +% This instance of \cmd\@makecolumn\ is followed by \cmd\output@column@, +% that is, it builds a column for \cmd\shipout\ rather than for adding to \cmd\pagesofar. +% +% We need to handle cases where the \cmd\output@pre@, \cmd\output@column@, or \cmd\output@post@\ +% dispatchers come up \cmd\relax ed out: the default is to execute the corresponding +% procedures from the \env{docuemnt} environment and the one-column grid respectively. +% +% One such case comes up with frequency: at the end of the document, where the \cmd\botmark\ is +% now empty. +% \changes{4.1b}{2008/08/04}{Change \cs{@makecol} to \cs{@makecolumn} with argument} +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% \changes{4.1n}{2010/01/02}{(AO, 571) Use procedures \cs{output@do@prep} and \cs{output@column@do} as dispatchers} +% \begin{macrocode} +\def\output@moving{% + \set@top@firstmark + \@ifnum{\outputpenalty=\do@newpage@pen}{% + \setbox\@cclv\vbox{% + \unvbox\@cclv + \remove@lastbox + \@ifdim{\ht\z@=\ht\@protection@box}{\box\lastbox}{\unskip}% + }% + }{}% + \@cclv@nontrivial@sw{% + \expandafter\output@do@prep\csname output@prep@\bot@envir \endcsname + \@makecolumn\true@sw + \expandafter\output@column@do\csname output@column@\thepagegrid\endcsname + \protect@penalty\do@startcolumn@pen + \clearpage@sw{% + \protect@penalty\do@endpage@pen + }{}% + \expandafter\let\expandafter\output@post@\csname output@post@\bot@envir \endcsname + \outputdebug@sw{\say\output@post@}{}% + \@ifx{\output@post@\relax}{\output@post@document}{\output@post@}% + }{% + \void@cclv + }% + \set@colht + \global\@mparbottom\z@ + \global\@textfloatsheight\z@ +}% +% \end{macrocode} +% Procedure \cmd\output@do@prep\ dispatches to the proper procedure to prepare page. +% \begin{macrocode} +\def\output@do@prep#1{% + \outputdebug@sw{\class@info{Prep: \string#1}}{}% + \@ifx{#1\relax}{\output@prep@document}{#1}% +}% +% \end{macrocode} +% Procedure \cmd\output@column@do\ dispatches to the proper procedure to output column or page. +% \begin{macrocode} +\def\output@column@do#1{% + \outputdebug@sw{\class@info{Output column: \string#1}}{}% + \@ifx{#1\relax}{\output@column@one}{#1}% +}% +\def\void@cclv{\begingroup\setbox\z@\box\@cclv\endgroup}% +\def\remove@lastbox{\setbox\z@\lastbox}% +% \end{macrocode} +% +% The procedure \cmd\@cclv@nontrivial@sw\ determines if this visit to \cmd\output@moving\ +% is a trivial one, which happens at the end of \cmd\clearpage\ processing and under some pathological circumstances. +% It emits a Boolean, so it is syntactically like \cmd\true@sw, albeit does not execute solely via expansion. +% +% Note: the case where \cmd\box\cmd\@cclv\ is void comes up at the very beginning of the job, when +% typesetting a (full-page-width) title block in a two-column layout. +% +% Note: the code that removes the last box and skip from the output is intended to detect the case +% where the output has whatsit nodes followed by topskip and a protection box. +% This is what happens under normal circumstances at the end of \cmd\clearpage\ processing. +% \changes{4.1b}{2008/08/04}{New procedure for showing a box contents, \cs{trace@box}} +% \begin{macrocode} +\def\@cclv@nontrivial@sw{% + \@ifx@empty\@toplist{% + \@ifx@empty\@botlist{% + \@ifvoid\footins{% + \@ifvoid\@cclv{% + \false@sw + }{% + \setbox\z@\vbox{\unvcopy\@cclv}% + \@ifdim{\ht\z@=\topskip}{% + \setbox\z@\vbox\bgroup + \unvbox\z@ + \remove@lastbox + \dimen@\lastskip\unskip + \@ifdim{\ht\z@=\ht\@protection@box}{% + \advance\dimen@\ht\z@ + \@ifdim{\dimen@=\topskip}{% + \aftergroup\true@sw + }{% + \aftergroup\false@sw + }% + }{% + \aftergroup\false@sw + }% +% \end{macrocode} +% End of \cmd\box\cmd\z@. +% \begin{macrocode} + \egroup + {% +% \end{macrocode} +% Normal for \clearpage +% \begin{macrocode} + \false@sw + }{% + \true@sw + }% + }{% + \@ifdim{\ht\z@=\z@}{% + \ltxgrid@info{Found trivial column. Discarding it}% + \outputdebug@sw{\trace@box\@cclv}{}% + \false@sw + }{% + \true@sw + }% + }% + }% + }{% + \true@sw + }% + }{% + \true@sw + }% + }{% + \true@sw + }% +}% +% \end{macrocode} +% +% +% \end{macro} +% \end{macro} +% +% \begin{macro}{\protect@penalty} +% The procedure \cmd\protect@penalty\ is the utility procedure for invoking a +% one-off output routine. Such a routine can expect to find the protection box +% above it in \cmd\box\cmd\@cclv: it should remove that box. +% +% Note that \cmd\execute@message\ does the same thing as \cmd\protect@penalty, but +% in a slightly different way. +% +% We create a specially formulated box that will be universally used when a protection box is needed. +% In this way, we can always recognize when \cmd\box\cmd\@cclv\ is trivial: +% it will consist of whatsits followed by \cmd\topskip\ glue and the \cmd\@protection@box. +% \begin{macrocode} +\def\protect@penalty#1{\protection@box\penalty-#1\relax}% +\newbox\@protection@box +\setbox\@protection@box\vbox to1986sp{\vfil}% +\def\protection@box{\nointerlineskip\copy\@protection@box}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dead@cycle} +% \begin{macro}{\dead@cycle@repair} +% The procedure \cmd\dead@cycle\ is defined separately as a utility which can be used by +% any output processing routine to emulate what takes place in the standard output routine. +% +% Here, we have entered the output routine with \cmd\holdinginserts\ enabled, which means that we +% are not yet ready to ship out material, because the \cmd\insert\ registers are being held. +% We want to clear \cmd\holdinginserts\ and come back here with the same page break as before, whereupon +% we may properly proceed with page makeup. +% +% To do this, we +% propagate marks, then spew the contents of \cmd\box\cmd\@cclv\ followed by the +% original output penalty that landed us here (but only if it is not 10000, +% the flag value for a pagebreak not at a penalty). +% +% However, the natural output routine should do this only if \cmd\box\cmd\@cclv\ is nontrivial. +% A pathological case exists wherein a box of height greater than \cmd\textheight\ would cause an infinite loop involving the output routine. +% The procedure \cmd\dead@cycle@repair, attempts to catch this case and avoid the loop. +% +% The test of the height of \cmd\box\cmd\@cclv\ is not the correct one, because this test will run afoul in +% the case where \cmd\box\cmd\@cclv\ contains nothing but an \cmd\insert\ node. What to do? +% +% It is possible that the pathological case can be detected by looking at \cmd\pagetotal. If that quantity is +% zero, then \cmd\box\cmd\@cclv\ really is trivial. +% +% In the procedure \cmd\dead@cycle@repair, if \cmd\box\cmd\@cclv\ is nontrivial, we execute \cmd\dead@cycle, +% otherwise it contains nothing but a mark, so we dispense with propagating marks +% and we simply spew out \cmd\box\cmd\@cclv\ without an accompanying mark. +% This has the effect of failing to propagate marks, but this problem is preferrable to the infinite loop, +% which in principle could crash even a robust operating system by filling up the file system. +% +% If a document has such a large chunk, it should be fixed, so we give a message in the log. +% +% You ask, ``In what way does this infinite loop come about?'' Good question! +% +% The setup is a chunk in the MVL that is taller than \cmd\textheight. +% (Yes, it's that simple.) +% As soon as the previous page ships out, the MVL will contain a mark (propagated from the previous page) followed +% by that large chunk (call it the `big bad box', albeit does not need to be a single box). +% The next visit to the output routine will be a natural page break, but +% \TeX\ will select the juncture between the mark and the big bad box as the least-cost page break. +% Unless the test in \cmd\dead@cycle\ is done, the cycle is perpetuated when the macro +% reinserts the mark. +% +% The crux matter is achieving, in a robust way, the goal of going from a \cmd\holdinginserts\ state to one +% where the insertions are moving. +% +% \begin{macrocode} +\def\dead@cycle@repair#1{% + \expandafter\do@@mark + \expandafter{% + \@@botmark + }% + \unvbox\@cclv + \nointerlineskip + \vbox to#1{\vss}% + \@ifnum{\outputpenalty<\@M}{\penalty\outputpenalty}{}% +}% +\def\dead@cycle@repair@protected#1{% + \expandafter\do@@mark + \expandafter{% + \@@botmark + }% + \begingroup + \unvbox\@cclv +% \end{macrocode} +% Remove the protection box +% \begin{macrocode} + \remove@lastbox + \nointerlineskip + \advance#1-\ht\@protection@box + \vbox to#1{\vss}% + \protection@box % Reinsert protection box + \@ifnum{\outputpenalty<\@M}{\penalty\outputpenalty}{}% + \endgroup +}% +\def\dead@cycle{% + \expandafter\do@@mark + \expandafter{% + \@@botmark + }% + \unvbox\@cclv + \@ifnum{\outputpenalty<\@M}{\penalty\outputpenalty}{}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\output@init@document} +% \begin{macro}{\output@prep@document} +% \begin{macro}{\output@post@document} +% The default processing simply provides for insertion of held-over footnotes. +% At a natural page break, we are either at the bottom of a column or at the bottom +% of a page. In either case, the \cmd\output@init@\ processing adjusts for the height +% of the held-over footnotes and bails out. +% Upon our return, at \cmd\output@prep@\ time, the page break will accomodate the material; +% it is now actually inserted by concatenating it with the contents of \cmd\footins. +% The default processing for \cmd\output@post@\ is nil. +% \changes{4.1b}{2008/08/04}{Box \cs{footbox} changed to box \cs{footsofar}} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \begin{macrocode} +\def\output@init@document{% + \ltxgrid@info@sw{\class@info{\string\output@init@document}}{}% + \global\vsize\vsize +}% +% \end{macrocode} +% QUERY: the following procedure is very like \cmd\combine@foot@inserts. Should it be the same? +% Answer: no, the two differ: this procedure makes a local assignment of \cmd\footins; +% the latter makes a global assignment of \cmd\footsofar. +% +% Note: In a multicolumn document, footnotes must \emph{not} be balanced at this point. +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \begin{macrocode} +\def\output@prep@document{% + \ltxgrid@foot@info@sw{\class@info{\string\output@prep@document}\trace@scroll{\showbox\footins\showbox\footsofar}}{}% + \@ifvoid\footsofar{% + }{% + \global\setbox\footins\vbox\bgroup + \unvbox\footsofar + \@ifvoid\footins{}{% + \marry@baselines + \unvbox\footins + }% + \egroup + \ltxgrid@foot@info@sw{\trace@box\footins}{}% + }% +}% +\def\output@post@document{}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@opcol} +% The standard \LaTeX\ procedure \cmd\@opcol\ is now completely obsoleted. +% \begin{macrocode} +\let\@opcol\@undefined +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@makecolumn} +% \changes{4.1b}{2008/08/04}{Change \cs{@makecol} to \cs{@makecolumn} with argument} +% The procedure \cmd\@makecolumn\ packages up a page along with all its insertions and floats. +% Therefore it is essential that it be executed with \cmd\holdininserts\ cleared. +% +% Note that there is a corner case when in a multi-column grid, where the change back to +% one-column grid occurs just after a complete page ships out. We want to detect when +% \cmd\@cclv\ contains nothing but a \cmd\mark, but this is a \TeX\ impossibility. +% +% Note on \cmd\@kludgeins: we have removed this mechanism from \LaTeX, because the implementation +% of \cmd\enlargethispage\ no longer requires it. +% Here, for consistency sake, we remove \cmd\@makespecialcolbox. +% +% The argument of \cmd\@makecolumn\ is a Boolean and determines if we combine the footnote material +% into the present column. If the procedure is building a column for shipping out, then we will +% combine the footnote material, if not, we return with the \cmd\footins\ box unchanged. +% +% \changes{4.1f}{2009/07/14}{(AO, 519) \cs{footins} content must be preserved and reintegrated} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +% \changes{4.1n}{2010/01/02}{(AO, 571) change calling sequence of \cs{combine@foot@inserts} to expose box registers}% +% I changed the behavior of this procedure in the case where the argument is \cmd\false@sw: +% send the unused footnote material to \cmd\footsofar. +% \begin{macrocode} +\def\@makecolumn#1{% + \ltxgrid@foot@info@sw{\class@info{\string\@makecolumn\string#1}}{}% + \setbox\@outputbox\vbox\bgroup + \boxmaxdepth\@maxdepth + \@tempdima\dp\@cclv + \unvbox\@cclv + \vskip-\@tempdima + \egroup + \xdef\@freelist{\@freelist\@midlist}\global\let\@midlist\@empty + \show@text@box@size + \@combinefloats + #1{% + \@combineinserts\@outputbox\footins + }{% + \combine@foot@inserts\footsofar\footins + }% + \set@adj@colht\dimen@ + \count@\vbadness + \vbadness\@M + \setbox\@outputbox\vbox to\dimen@\bgroup + \@texttop + \dimen@\dp\@outputbox + \unvbox\@outputbox + \vskip-\dimen@ + \@textbottom + \egroup + \vbadness\count@ + \global\maxdepth\@maxdepth +}% +\let\@makespecialcolbox\@undefined +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@combineinserts} +% The procedure to add the specified insertions to the packaged-up page. +% All other classes of insertions should also be dealt with at this time. +% +% Note that the second argument must be a \cmd\newinsert\ register: we access the \cmd\box\ along with the \cmd\skip. +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +% \changes{4.1n}{2010/01/02}{(AO, 571) footnote rule is leaders, so that it may be removed by \cs{vsplit}; mechanism of \cs{kern} signals to indicate footnote height}% +% \begin{macrocode} +\def\@combineinserts#1#2{% + \ltxgrid@foot@info@sw{\class@info{\string\@combineinserts\string#1\string#2}\trace@box#2}{}% + \setbox#1\vbox\bgroup + \unvbox#1% + \@ifvoid{#2}{}{% + \dimen@\ht#2\advance\dimen@\dp#2\advance\dimen@\skip#2% + \show@box@size{Combining inserts}#2% + \vskip\skip#2% +% \end{macrocode} +% The footnote rule is created as leaders, so that it may be removed automatically (via \cmd\vsplit) +% in the event the footnote is recovered from this column. +% Note that if \cmd\color@begingroup\ or \cmd\normalcolor\ produce marks, this technique will be confounded. +% \begin{macrocode} + \setbox\z@\vbox{\footnoterule}\dimen@i\ht\z@ + \color@begingroup + \normalcolor + \cleaders\box\z@\vskip\dimen@i\kern-\dimen@i + \csname combine@insert@\the\pagegrid@col\endcsname#2% + \color@endgroup +% \end{macrocode} +% The following tells \cmd\recover@column\ the size of the footnotes added here, including the skip glue above. +% \begin{macrocode} + \kern-\dimen@\kern\dimen@ + }% + \egroup + \ltxgrid@foot@info@sw{\trace@box#1}{}% +}% +% \end{macrocode} +% We provide for a layer of abstraction for the laying down of footnotes at the bottom of this column or page. +% \end{macro} +% +% \begin{macro}{\combine@insert@tw@} +% \begin{macro}{\combine@insert@@ne} +% \begin{macro}{\twocolumn@grid@setup} +% \begin{macro}{\onecolumn@grid@setup} +% \begin{macro}{\columngrid@setup} +% \changes{4.1p}{2010/02/24}{(AO, 583) Provide setup code also for footnotes in a one-column document}% +% The following two definitions cover the cases of a two-column document (with footnotes set on a single-column width), +% and a one-column document. +% However, the case of a two-column document with footnotes set on full text width is not covered. +% +% For a document in an overall two-column page grid, execute the commands +% \cmd\twocolumn@grid@setup\ followed by \cmd\open@twocolumn; +% if on the full page width (one-column grid), the command \cmd\onecolumn@grid@setup. +% +% The following is the way REVTeX does the initialization. +% The procedure \cmd\select@column@grid\ is executed at \cmd\AtBeginDocument\ time; +% the boolean \cmd\twocolumn@sw\ selects between the two alternatives. +% \begin{verbatim} +%\def\select@column@grid{% +% \twocolumn@sw{% +% \twocolumn@grid@setup +% \open@twocolumn +% }{% +% \onecolumn@grid@setup +% }% +%}% +%\appdef\class@documenthook{% +% \select@column@grid +%}% +% \end{verbatim} +% +% \begin{macrocode} +\def\combine@insert@tw@#1{% + \compose@footnotes@two#1\@ifvbox{#1}{\unvbox}{\box}#1% +}% +\def\combine@insert@@ne#1{% + \compose@footnotes@one#1\@ifvbox{#1}{\unvbox}{\box}#1% +}% +\def\twocolumn@grid@setup{% + \expandafter\let\csname combine@insert@1\endcsname\combine@insert@tw@ + \expandafter\let\csname combine@insert@2\endcsname\combine@insert@@ne +}% +\def\onecolumn@grid@setup{% + \expandafter\let\csname combine@insert@1\endcsname\combine@insert@@ne + \expandafter\let\csname combine@insert@2\endcsname\combine@insert@@ne +}% +\let\columngrid@setup\onecolumn@grid@setup +\columngrid@setup +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@floatplacement} +% In standard \LaTeX, someone (DPC?) makes the assumption that \cmd\@fpmin\ can be assigned +% locally. This is no longer true now that we ship no more than one page per visit to the output routine. +% We apply a bandaid. +% \begin{macrocode} +\appdef\@floatplacement{% + \global\@fpmin\@fpmin +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pagebreak@pen} +% While we are in the way of registering certain penalty values, +% let us register the smallest one that will force a visit to the output routine. +% However, this penalty will not have an assciated macro: we wish to execute the +% natural output routine instead. +% +% Note that this penalty is invoked by \cmd\clearpage\ and \cmd\newpage. +% \begin{macrocode} +\mathchardef\pagebreak@pen=\@M +\expandafter\let\csname output@-\the\pagebreak@pen\endcsname\relax +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Float placement}% +% +% \begin{macro}{\do@startcolumn@pen} +% The procedure \cmd\do@startcolumn@pen\ is executed as a one-off output routine +% just after a page is shipped out (or, in a multicolumn page grid, a column is salted away). +% +% Its job is to either generate a ``float page'' (in reality a column) for shipping out, +% or to commit deferred floats to the fresh column, concluding with a dead cycle. +% In the former case, we accomodate split footnotes and other insertions (by comparing \cmd\vsize\ and \cmd\pagegoal): +% the floats are spewed onto the page, whereupon \LaTeX's output routine will place the footnotes and ship out, +% iterating the process once again. +% +% Note that when this procedure is invoked, \cmd\box\cmd\@cclv\ still has within it the protection box, so we +% start by removing it. Note also that if there was a split insertion held over from the previous page, the +% insert node will be present in \cmd\box\cmd\@cclv, \emph{prior to} the protection box. For this reason, we cannot +% just throw away that box, as we might be tempted to do. +% +% FIXME: where else do we possibly inappropriately discard \cmd\box\cmd\@cclv? +% +% Note that, because a column or page page had previously just been completed, +% we can assume that there is nothing of importance on the page, +% and because no message is being passed, we can preserve marks in a simple way. +% +% A Note on terminology: +% In a single-column page grid, you might expect that we would execute the procedure \cmd\do@startpage. +% But this is not so. +% \LaTeX\ has a confustion of long standing, +% in which the procedures that handle full-page width floats in a two-column page grid all have in their names +% the string `dbl', which erroneously suggests having something to do with ``double''. It does not: +% when you see `dbl', think ``full page width''. +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% \begin{macrocode} +\mathchardef\do@startcolumn@pen=10005 +\@namedef{output@-\the\do@startcolumn@pen}{\do@startcolumn}% +\def\do@startcolumn{% + \setbox\@cclv\vbox{\unvbox\@cclv\remove@lastbox\unskip}% + \clearpage@sw{\@clearfloatplacement}{\@floatplacement}% + \set@colht + \@booleanfalse\pfloat@avail@sw + \begingroup + \@colht\@colroom + \@booleanfalse\float@avail@sw + \@tryfcolumn\test@colfloat + \float@avail@sw{\aftergroup\@booleantrue\aftergroup\pfloat@avail@sw}{}% + \endgroup + \fcolmade@sw{% + \setbox\@cclv\vbox{\unvbox\@outputbox\unvbox\@cclv}% +% \end{macrocode} +% Now ask for a return visit, this time with insertions and all. +% \begin{macrocode} + \outputpenalty-\pagebreak@pen + \dead@cycle + }{% + \begingroup + \let\@elt\@scolelt + \let\reserved@b\@deferlist\global\let\@deferlist\@empty\reserved@b + \endgroup + \clearpage@sw{% + \outputpenalty\@M + }{% + \outputpenalty\do@newpage@pen + }% + \dead@cycle + }% + \check@deferlist@stuck\do@startcolumn + \set@vsize +}% +\def\@scolelt#1{\def\@currbox{#1}\@addtonextcol}% +\def\test@colfloat#1{% + \csname @floatselect@sw@\thepagegrid\endcsname#1{}{\@testtrue}% + \@if@sw\if@test\fi{}{\aftergroup\@booleantrue\aftergroup\float@avail@sw}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@addtonextcol} +% We must adjust \cmd\@addtonextcol\ to take held-over inserts into account. +% Now that all deferred floats are queued up together (in order), we must have a way of +% differentiating them; this is done by the page grid-dependent procedure \cmd\@floatselect@sw@. +% \begin{macrocode} +\def\@addtonextcol{% + \begingroup + \@insertfalse + \@setfloattypecounts + \csname @floatselect@sw@\thepagegrid\endcsname\@currbox{% + \@ifnum{\@fpstype=8 }{}{% + \@ifnum{\@fpstype=24 }{}{% + \@flsettextmin + \@reqcolroom \ht\@currbox + \advance \@reqcolroom \@textmin + \advance \@reqcolroom \vsize % take into account split insertions + \advance \@reqcolroom -\pagegoal + \@ifdim{\@colroom>\@reqcolroom}{% + \@flsetnum \@colnum + \@ifnum{\@colnum>\z@}{% + \@bitor\@currtype\@deferlist + \@if@sw\if@test\fi{}{% + \@addtotoporbot + }% + }{}% + }{}% + }% + }% + }{}% + \@if@sw\if@insert\fi{}{% + \@cons\@deferlist\@currbox + }% + \endgroup +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\do@startpage@pen} +% \begin{macro}{\forcefloats@sw} +% \begin{macro}{\@output@combined@page} +% \begin{macro}{\@sdblcolelt} +% \begin{macro}{\test@dblfloat} +% \begin{macro}{\@if@notdblfloat} +% Similar to \cmd\do@startcolumn, +% the procedure \cmd\do@startpage\ starts up a new page (not column) in a multi-column page grid. +% It is invoked after a page is shipped out in a multi-column page grid, and +% it commits full-page-width floats to the fresh page, possibly resulting in a float page. +% In implementation, it is similar to \cmd\do@startcolumn, except that +% it commits effectively via \cmd\@addtodblcol\ instead of \cmd\@addtonextcol. +% Note that this procedure will inevitably be followed by \cmd\do@startcolumn. +% +% Some details of the procedure: +% +% We begin by removing the protection box from \cmd\box\cmd\@cclv, then setting the values of the +% float placement parameters appropriately, and resetting \cmd\@colht, \cmd\@colroom, and \cmd\vsize\ to base values. +% +% Next we attempt to compose a float page, a page consisting entirely of floats. If successful, +% we ship out the float page and lay down an interrupt that will send us back here for another try. +% +% If no float page is formed, we attempt to commit full-page-width floats to the text page, and return with a dead cycle. +% We are now ready to compose columns of text. +% +% Note that all floats (both column floats and full-page-width floats) move through a single queue. +% To differentiate between the two, the width of the float is compared to \cmd\textwidth. +% This comparison is encapsulated in the macro \cmd\@if@notdblfloat, which should be used whenever +% such a determination must be made. This procedure returns a Boolean. +% +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% \begin{macrocode} +\mathchardef\do@startpage@pen=10006 +\@namedef{output@-\the\do@startpage@pen}{\do@startpage}% +\def\do@startpage{% + \setbox\@cclv\vbox{\unvbox\@cclv\remove@lastbox\unskip}% + \clearpage@sw{\@clearfloatplacement}{\@dblfloatplacement}% + \set@colht + \@booleanfalse\pfloat@avail@sw + \begingroup + \@booleanfalse\float@avail@sw + \@tryfcolumn\test@dblfloat + \float@avail@sw{\aftergroup\@booleantrue\aftergroup\pfloat@avail@sw}{}% + \endgroup + \fcolmade@sw{% + \global\setbox\pagesofar\vbox{\unvbox\pagesofar\unvbox\@outputbox}% + \@output@combined@page + }{% + \begingroup + \@booleanfalse\float@avail@sw + \let\@elt\@sdblcolelt + \let\reserved@b\@deferlist\global\let\@deferlist\@empty\reserved@b + \endgroup + \@ifdim{\@colht=\textheight}{% No luck... + \pfloat@avail@sw{% ...but a float *was* available! + \forcefloats@sw{% + \ltxgrid@warn{Forced dequeueing of floats stalled}% + }{% + \ltxgrid@warn{Dequeueing of floats stalled}% + }% + }{}% + }{}% + \outputpenalty\@M + \dead@cycle + }% + \check@deferlist@stuck\do@startpage + \set@colht +}% +% \end{macrocode} +% +% Procedure \cmd\@output@combined@page\ is a utility that ships out a page consisting of the +% result of \cmd\@combinepage\ and \cmd\@combinedblfloats, after which it prepares for +% the process to repeat. +% +% It is coincidentally identical to what needs to happen with +% a float page that has been built by \cmd\@tryfcolumn, in the multi-column page grid, +% and also handles the case where a page needs to be shipped out when in multicolumn mode. +% \changes{4.1b}{2008/08/04}{New procedure \cs{@output@combined@page}} +% \changes{4.1b}{2008/08/04}{Change \cs{@combinepage} to \cs{@combinepage} with argument} +% \begin{macrocode} +\def\@output@combined@page{% + \@combinepage\true@sw + \@combinedblfloats + \@outputpage + \global\pagegrid@cur\@ne + \protect@penalty\do@startpage@pen +}% +\def\@sdblcolelt#1{\def\@currbox{#1}\@addtodblcol}% +\def\test@dblfloat#1{% + \@if@notdblfloat{#1}{\@testtrue}{}% + \@if@sw\if@test\fi{}{\aftergroup\@booleantrue\aftergroup\float@avail@sw}% +}% +\def\@if@notdblfloat#1{\@ifdim{\wd#1<\textwidth}}% +\@booleanfalse\forcefloats@sw +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@addtodblcol} +% +% The procedure \cmd\@addtodblcol\ is called into play at the beginning of each fresh page +% and operates on each deferred float, in the hopes of placing one or more such floats +% at the top of the current page. +% +% We alter the procedure of standard \LaTeX\ by putting failed floats into +% \cmd\@deferlist\ instead of \cmd\@dbldeferlist. Having done so, we must have a means +% of differentiating full-page-width floats from column-width floats. +% We assume that the latter will always be narrower than \cmd\textwidth. +% +% In aid of detecting a stalled float flushing process, we set a Boolean if we encounter +% a qualified full-page-width float here. Any that qualify but fail the rest of the tests +% might still pass when reconsidered on an otherwise blank page. +% \begin{macrocode} +\def\@addtodblcol{% + \begingroup + \@if@notdblfloat{\@currbox}{% + \false@sw + }{% + \@setfloattypecounts + \@getfpsbit \tw@ + \@bitor \@currtype \@deferlist + \@if@sw\if@test\fi{% + \false@sw + }{% + \@ifodd\@tempcnta{% + \aftergroup\@booleantrue\aftergroup\float@avail@sw + \@flsetnum \@dbltopnum + \@ifnum{\@dbltopnum>\z@}{% + \@ifdim{\@dbltoproom>\ht\@currbox}{% + \true@sw + }{% + \@ifnum{\@fpstype<\sixt@@n}{% + \begingroup + \advance \@dbltoproom \@textmin + \@ifdim{\@dbltoproom>\ht\@currbox}{% + \endgroup\true@sw + }{% + \endgroup\false@sw + }% + }{% + \false@sw + }% + }% + }{% + \false@sw + }% + }{% + \false@sw + }% + }% + }% + {% + \@tempdima -\ht\@currbox + \advance\@tempdima + -\@ifx{\@dbltoplist\@empty}{\dbltextfloatsep}{\dblfloatsep}% + \global \advance \@dbltoproom \@tempdima + \global \advance \@colht \@tempdima + \global \advance \@dbltopnum \m@ne + \@cons \@dbltoplist \@currbox + }{% + \@cons \@deferlist \@currbox + }% + \endgroup +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@tryfcolumn} +% \begin{macro}{\@wtryfc} +% \begin{macro}{\@xtryfc} +% \begin{macro}{\@ztryfc} +% Whenever a page is shipped out, \LaTeX\ automatically tries out a float column: +% a page containing nothing but floats (and, as we have added here, split footnotes). +% +% The following four procedures employ certain macros to communicate between each other: +% +% \cmd\fcolmade@sw, a boolean, says whether we were successful in making a float column. +% +% \cmd\if@test, a \cmd\newif\ switch, says a float has failed some test. +% +% \cmd\@deferlist, is the input to the process, a list, of deferred floats. +% +% \cmd\@trylist, a list, stores the deferred floats to be tried out on the float column. +% +% \cmd\@failedlist, a list of floats that have failed the selection for the float column. +% +% \cmd\@flfail, a list of floats that have failed the second selection for the float column. +% +% \cmd\@flsucceed, a list, the floats that have been successfully placed on the float column. +% +% \cmd\@freelist, a list, receives any freed floats. +% +% \cmd\@colht, a dimen, the available space for the column, including column floats and insertions (footnotes). +% +% \cmd\@fpmin, a dimen, the required minimum height for the float column. +% +% \cmd\@outputbox, a box, the output of the process. +% +% \cmd\@fptop, \cmd\@fpsep, \cmd\@fpbot, glue, placed above, between, and below floats on the float column. +% +% \cmd\@currtype, a count, used temporarily for the float's bits. +% +% \cmd\@tempcnta, a count, used temporarily for the float's bits. +% +% In \cmd\@tryfcolumn, we alter the criterion for a float page, because if footnotes are present at this point +% (presumably due to a split insertion) then \cmd\@fpmin is no longer the right threshold to apply. +% +% Note that we have changed \cmd\@tryfcolumn, \cmd\@xtryfc, and \cmd\@ztryfc\ syntactically so that the procedure +% to test for the float's being a column float versus a full-page-width float is passed in as an +% argument. +% +% \begin{macrocode} +\def\@tryfcolumn#1{% + \global\@booleanfalse\fcolmade@sw + \@ifx@empty\@deferlist{}{% + \global\let\@trylist\@deferlist + \global\let\@failedlist\@empty + \begingroup + \dimen@\vsize\advance\dimen@-\pagegoal\@ifdim{\dimen@>\z@}{% + \advance\@fpmin-\dimen@ + }{}% + \def\@elt{\@xtryfc#1}\@trylist + \endgroup + \fcolmade@sw{% + \global\setbox\@outputbox\vbox{\vskip \@fptop}% + \let \@elt \@wtryfc \@flsucceed + \global\setbox\@outputbox\vbox{\unvbox\@outputbox + \unskip \vskip \@fpbot + }% + \let \@elt \relax + \xdef\@deferlist{\@failedlist\@flfail}% + \xdef\@freelist{\@freelist\@flsucceed}% + }{}% + }% +}% +\def\@wtryfc #1{% + \global\setbox\@outputbox\vbox{\unvbox\@outputbox + \box #1\vskip\@fpsep + }% +}% +\def\@xtryfc#1#2{% + \@next\reserved@a\@trylist{}{}% trim \@trylist. Ugly! + \@currtype \count #2% + \divide\@currtype\@xxxii\multiply\@currtype\@xxxii + \@bitor \@currtype \@failedlist + \@testfp #2% + #1#2% + \@ifdim{\ht #2>\@colht }{\@testtrue}{}% + \@if@sw\if@test\fi{% + \@cons\@failedlist #2% + }{% + \begingroup + \gdef\@flsucceed{\@elt #2}% + \global\let\@flfail\@empty + \@tempdima\ht #2% + \def \@elt {\@ztryfc#1}\@trylist + \@ifdim{\@tempdima >\@fpmin}{% + \global\@booleantrue\fcolmade@sw + }{% + \@cons\@failedlist #2% + }% + \endgroup + \fcolmade@sw{% + \let \@elt \@gobble + }{}% + }% +}% +\def\@ztryfc #1#2{% + \@tempcnta \count#2% + \divide\@tempcnta\@xxxii\multiply\@tempcnta\@xxxii + \@bitor \@tempcnta {\@failedlist \@flfail}% + \@testfp #2% + #1#2% + \@tempdimb\@tempdima + \advance\@tempdimb \ht#2\advance\@tempdimb\@fpsep + \@ifdim{\@tempdimb >\@colht}{% + \@testtrue + }{}% + \@if@sw\if@test\fi{% + \@cons\@flfail #2% + }{% + \@cons\@flsucceed #2% + \@tempdima\@tempdimb + }% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsection{Clearing pages}% +% +% Clearing the page is an elaboration of ending the page: it entails flushing all floats. +% +% This package might make number of float flushing algorithms available, +% a very simple one that does not try to produce excellent pages, +% another that tries to make the best use of space, +% and a more complex one that tries to balance columns. +% +% At the beginning of the page-clearing process, by definition all of the paragraph text involved is on the MVL and all floats have been encountered. +% There may be material in \cmd\pagesofar, and (in a multi-column page grid) any number of columns of the page have been composed. +% Also, there might be footnote material saved up in \cmd\footsofar. +% +% Because we did not want to perform multiple \cmd\shipout s per visit to the output routine, +% our multi-column page makeup will not compose multiple columns per visit. +% This implementation detail may not require alteration, but it is not a limitation that is truly necessary: +% it is only multiple \cmd\shipout s per visit that must be avoided. +% +% The crux matter is how to continue with flushing floats even after the material in the MVL is exhausted. +% At that point, we must, upon completion of the output routine, +% insert into the MVL an interrupt that triggers the next step in the processing. +% +% Therefore, after processing a \cmd\do@startcolumn\ interrupt, we must somehow force the completion of that column. +% This could be done by inserting a \cmd\do@newpage@pen\ interrupt. +% +% And after processing a \cmd\do@startpage@pen\ interrupt, that results in \cmd\@dbltopinsert s, +% we must ensure that the multiple columns on the page get completed, so that the page itself finally gets shipped out. +% This part will proceed automatically given that \cmd\do@startcolumn\ processing completes successfully. +% +% The process will not be complete until all deferred floats have been placed and shipped out, and all saved-up footnotes have been inserted. +% +% Full-page-width floats can get out of order of column floats. This problem can be remedied by holding them all in the same list. +% We therefore stop using \cmd\@dbldeferlist\ entirely, and all of the procedures that formerly used it have been rewritten to +% use \cmd\@deferlist\ instead. When traversing the list, we apply a selector on the given box that determines whether it is a column-width or page-width float. +% This selector is different depending on the page grid. +% +% When the \cmd\@deferlist\ is processed (by any means), we have to take care of the case where a float of one category is passed over but we are looking for a float of the other category. +% Here, we must terminate processing, to avoid disordering the floats. This we do by the usual means. +% +% The system has a Boolean that says we are clearing pages: \cmd\clearpage@sw; if it is true, +% then at the tail of \cmd\do@startcolumn\ processing, we should put down a (\cmd\vfil?) \cmd\do@newpage@pen\ interrupt. +% This is because the MVL is now empty, so we have to force the columns to complete. +% +% One potential very pathological case would be where there is one or more deferred floats that never successfully get placed: +% placing floats has stalled, and we will ship out blank pages indefinitely. How to detect this case? +% +% First, \cmd\do@startpage\ will evidently be stalled if the following are all true: +% a) \cmd\@tryfcolumn\ and \cmd\@sdblcolelt\ both fail, +% b) there are deferred floats available for page placement, and +% c) the \cmd\@colht=\cmd\textheight, that is, the full page height is available for placement of column floats. +% +% Second, \cmd\do@startcolumn\ will evidently be stalled if the following are all true: +% a) tryfcolumn fails, +% b) there are deferred floats available for column placement, and +% a) the \cmd\@colroom=\cmd\textheight, that is, the full page height is available for placement of column floats. +% +% +% \begin{macro}{\cleardoublepage} +% \begin{macro}{\clearpage} +% \begin{macro}{\newpage} +% \begin{macro}{\newpage@prep} +% The function of \cmd\clearpage\ is to end the current page with \cmd\newpage\ and then +% ship out additional pages until (\footins) inserts and (deferred) floats are exhausted. +% +% The method involves setting the float placement parameters to completely permissive values +% and kicking out the current page (using a non-discardable penalty). +% A possibly short page will be shipped out, followed +% by any number of float pages. However these float pages, because using permissive float placement, +% will exhaust all inserts and deferred floats. +% +% Bug Note: in the code for \cmd\clearpage, the first penalty we output is an unprotected \cmd\pagebreak@pen. +% I tried using a protected \cmd\do@newpage@pen, but that gave rise to a corner case where a blank page +% was output. +% +% At present, the \cmd\clearpage\ procedure does the same as \cmd\newpage, +% except that \cmd\clearpage@sw\ is turned on, +% and the (discardable) \cmd\newpage\ is inevitably followed by the same procedures +% that are executed if a page is shipped out. +% +% FIXME: it seems that better than \cmd\pagebreak@pen\ would be an unprotected penalty of a special value that would +% entail output routine processing consisting of the following steps: +% 3) \cmd\unvbox\cmd\@cclv, +% 1) set \cmd\clearpage@sw\ to \cmd\true@sw, +% 2) put down a protected \cmd\do@startcolumn@pen, +% 4) take a dead cycle. +% +% The effect would be to liberalize float placement options for the current column as well as further columns that may be output as part of \cmd\clearpage\ processing. +% Of course, it would still be necessary to set \cmd\clearpage@sw\ again via an interrupt. +% +% An optimization might be to clear \cmd\clearpage@sw\ as part of the same interrupt, +% but that would actually not work properly, because it is necessary for \cmd\do@endpage\ to +% possibly invoke further visits to the output routine before clearpage processing ceases. +% \begin{macrocode} +\def\newpage@prep{% + \if@noskipsec + \ifx \@nodocument\relax + \leavevmode + \global \@noskipsecfalse + \fi + \fi + \if@inlabel + \leavevmode + \global \@inlabelfalse + \fi + \if@nobreak \@nobreakfalse \everypar{}\fi + \par +}% +\def \newpage {% + \newpage@prep + \do@output@MVL{% + \vfil + \penalty-\pagebreak@pen + }% +}% +\def\clearpage{% + \newpage@prep + \do@output@MVL{% + \vfil + \penalty-\pagebreak@pen + \global\@booleantrue\clearpage@sw + \protect@penalty\do@startcolumn@pen + \protect@penalty\do@endpage@pen + }% + \do@output@MVL{% + \global\@booleanfalse\clearpage@sw + }% +}% +\def\cleardoublepage{% + \clearpage + \@if@sw\if@twoside\fi{% + \@ifodd\c@page{}{% + \null\clearpage + }% + }{}% +}% +\@booleanfalse\clearpage@sw +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\do@endpage@pen} +% The penalty \cmd\do@endpage@pen\ simply dispatches to the page grid procedure that forces an end page. +% That procedure should test whether there is anything to ship out (say committed floats), then act accordingly. +% Note that as part of this work, it should \cmd\unvbox\cmd\@cclv, which has been left boxed up so it can be +% measured. +% \begin{macrocode} +\mathchardef\do@endpage@pen=10007 +\@namedef{output@-\the\do@endpage@pen}{\csname end@column@\thepagegrid\endcsname}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\do@newpage@pen} +% The penalty \cmd\do@newpage@pen\ allows a ``non-discardable \cmd\newpage'' command: +% a \cmd\newpage\ command that will not disappear at a pagebreak. +% This visit to the output routine will not be dispatched to an interrupt, +% rather the natural output routine will be executed, where it +% will remove the protection box. +% +% Call this routine by executing \cmd\protect@penalty\cmd\do@newpage@pen. +% \begin{macrocode} +\mathchardef\do@newpage@pen=10001 +\expandafter\let\csname output@-\the\do@newpage@pen\endcsname\relax +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@clearfloatplacement} +% The procedure \cmd\@clearfloatplacement\ sets the float placement parameters +% to completely permissive values (except for \cmd\@fpmin). The standard values are: +% +% \begin{tabular}{ll} +%\cmd\@topnum &\cmd\c@topnumber\\ +%\cmd\@toproom &\cmd\topfraction\cmd\@colht\\ +%\cmd\@botnum &\cmd\c@bottomnumber\\ +%\cmd\@botroom &\cmd\bottomfraction\cmd\@colht\\ +%\cmd\@colnum &\cmd\c@totalnumber\\ +%\cmd\@fpmin &\cmd\floatpagefraction\cmd\@colht\\ +%\cmd\@dbltopnum &\cmd\c@dbltopnumber\\ +%\cmd\@dbltoproom &\cmd\dbltopfraction\cmd\@colht\\ +%\cmd\@textmin &\cmd\@colht\cmd\advance\cmd\@textmin -\cmd\@dbltoproom\\ +%\cmd\@fpmin &\cmd\dblfloatpagefraction\cmd\textheight +% \end{tabular} +% \begin{macrocode} +\def\@clearfloatplacement{% + \global\@topnum \maxdimen + \global\@toproom \maxdimen + \global\@botnum \maxdimen + \global\@botroom \maxdimen + \global\@colnum \maxdimen + \global\@dbltopnum \maxdimen + \global\@dbltoproom \maxdimen + \global\@textmin \z@ + \global\@fpmin \z@ + \let\@testfp\@gobble + \appdef\@setfloattypecounts{\@fpstype16\advance\@fpstype\m@ne}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@doclearpage} +% \begin{macro}{\@makefcolumn} +% \begin{macro}{\@makecol} +% The \cmd\@doclearpage\ procedure is now obsoleted, as is \cmd\@makefcolumn, which it invoked. +% We also completely avoid using \cmd\@makecol\ (in favor of \cmd\@makecolumn). +% \begin{macrocode} +\let\@doclearpage\@undefined +\let\@makefcolumn\@undefined +\let\@makecol\@undefined +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\clr@top@firstmark} +% \begin{macro}{\set@top@firstmark} +% \begin{macro}{\@outputpage@tail} +% We want accurate values of \cmd\topmark\ and \cmd\firstmark, but we must deal with +% the fact that there are many different ways of contributing material +% to the page. Only upon the first contribution to the page is the value of \cmd\topmark\ +% accurate. However, with \cmd\firstmark\ we must potentially examine each contribution +% because the first mark on the page may happen to fall in the last piece of material contributed. +% +% To begin, we define the procedure that initializes the macros to appropriate flag values. +% \begin{macrocode} +\def\clr@top@firstmark{% + \global\let\saved@@topmark\@undefined + \global\let\saved@@firstmark\@empty + \global\let\saved@@botmark\@empty +}% +\clr@top@firstmark +% \end{macrocode} +% +% Note that the flag value for \cmd\saved@@topmark\ is \cmd\@undefined, just as one would +% expect. But that for \cmd\saved@@firstmark\ and \cmd\saved@@botmark\ is \cmd\@empty. +% +% Next, we define procedure \cmd\set@top@firstmark; it will be exercised everywhere material is contributed, +% capturing the mark values if appropriate. +% \begin{macrocode} +\def\set@top@firstmark{% + \@ifxundefined\saved@@topmark{\expandafter\gdef\expandafter\saved@@topmark\expandafter{\@@topmark}}{}% + \@if@empty\saved@@firstmark{\expandafter\gdef\expandafter\saved@@firstmark\expandafter{\@@firstmark}}{}% + \@if@empty\@@botmark{}{\expandafter\gdef\expandafter\saved@@botmark\expandafter{\@@botmark}}% +}% +% \end{macrocode} +% When should \cmd\set@top@firstmark\ be called? +% A good candidate for a universal procedure for handling contributed material is +% the natural output routine; are any other calls needed? +% +% Yes, in \cmd\save@column\ we must execute \cmd\set@top@firstmark\ because we are about to +% save away \cmd\box\cmd\@cclv, and we will never see its marks again (unless it is unboxed into the MVL), +% because \TeX\ lets one access a box's marks only within an output routine that has put that box into \cmd\box\cmd\@cclv. +% +% As soon as a page is shipped out, we initialize the two macros that +% hold the values of \cmd\topmark\ and \cmd\firstmark, respectively. +% \changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@tail} tailpatches \cs{@outputpage}}% +% \begin{macrocode} +\appdef\@outputpage@tail{% + \clr@top@firstmark +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsection{Other interfaces to \LaTeX}% +% +% \begin{macro}{\@float} +% \begin{macro}{\@dblfloat} +% \begin{macro}{\@yfloat} +% \begin{macro}{\fps@} +% \begin{macro}{\fpsd@} +% The \LaTeX\ kernel procedures \cmd\@float\ and \cmd\@dblfloat\ are treated on an equal footing. +% Each now takes environment-specific float placement defaults. +% If none are defined for the calling environment, we apply a default. +% +% A parameter is passed that will set the width of text within the float, normally \cmd\columnwidth, +% and in the "dbl" version, \cmd\textwidth. However, an environment such as \env{turnpage} +% may change the meanings of these macros to allow turnpage floats. +% +% \changes{4.0a}{2008/06/26 }{\cs{@yfloat}: de-fang \cs{set@footnotewidth} (see ltxutil.dtx): we have already done its job. } +% +% Note on \cmd\@xfloat: the optional argument must come to it fully expanded, because the macro +% does a weird procedure on this argument, involving \cmd\@onelevel@sanitize, which I do not +% understand, and which does not work if not so expanded. +% \changes{4.1b}{2008/08/04}{Get rid of the \cs{reserved@a} idiom} +% \begin{macrocode} +\def\@float#1{% + \@ifnextchar[{% +% \end{macrocode} +% \verb+}]{+Brace-matching klootch +% \begin{macrocode} + \@yfloat\width@float{#1}% + }{% + \@ifxundefined@cs{fps@#1}{}{\expandafter\let\expandafter\fps@\csname fps@#1\endcsname}% + \expandafter\@argswap\expandafter{\expandafter[\fps@]}{\@yfloat\width@float{#1}}% + }% +}% +\def\@dblfloat#1{% + \@ifnum{\pagegrid@col=\@ne}{% + \@float{#1}% + }{% + \@ifnextchar[{% +% \end{macrocode} +% \verb+}]{+Brace-matching klootch +% \begin{macrocode} + \@yfloat\widthd@float{#1}% + }{% + \@ifxundefined@cs{fpsd@#1}{}{\expandafter\let\expandafter\fpsd@\csname fpsd@#1\endcsname}% + \expandafter\@argswap\expandafter{\expandafter[\fpsd@]}{\@yfloat\widthd@float{#1}}% + }% + }% +}% +% \end{macrocode} +% \changes{4.1b}{2008/08/04}{Turn off the \cs{set@footnotewidth} mechanism; a float `knows' its proper typesetting context} +% \changes{4.1n}{2010/01/02}{(AO, 571) Interface \cs{set@footnotewidth} for determining the set width of footnotes}% +% \cmd\@yfloat\ is the go-to procdure for creating the proper environment for the content of a float. +% Argument \verb+#1+ is the width of the float environment (we disable \cmd\set@footnotewidth), and +% we establish a self-contained (minipage) environment for footnotes. +% \begin{macrocode} +\def\@yfloat#1#2[#3]{% + \@xfloat{#2}[#3]% + \hsize#1\linewidth\hsize + \let\set@footnotewidth\@empty + \minipagefootnote@init +}% +\def\fps@{tbp}% +\def\fpsd@{tp}% +\def\width@float{\columnwidth}% +\def\widthd@float{\textwidth}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\end@float} +% \begin{macro}{\end@dblfloat} +% \begin{macro}{\end@@float} +% \begin{macro}{\check@currbox@count} +% \begin{macro}{\minipagefootnote@init} +% \begin{macro}{\minipagefootnote@here} +% \LaTeX\ kernel procedures \cmd\end@float\ and \cmd\end@dblfloat\ +% have been changed to work alike; in particular, floats of both classes +% are deferred into the same queue. +% This measure ensures that they will be placed in their original order, +% an aspect in which \LaTeX\ is broken. +% +% Note: when retrieving floats from the queues, we can differentiate those of the two categories +% by the width of the box. +% +% Floats are processed via an output routine message, and are checked for +% sanity in re the float placement options. In the case of full-page-width floats, +% we ensure that the h and b float placement options are never asserted, because they +% make no sense. +% +% Note that if we get to the end of the float box and still have pending +% footnotes, we put then out. +% +% LaTeX Bug note: if a user types \cmd\begin{table*}[h], the float will never succeed in being placed! +% we try to catch such cases. +% +% Note that the macro \cmd\check@currbox@count\ tries to catch cases where the float placement options +% are such that the float can never be placed. +% +% The calls to \cmd\@iffpsbit\ are part of a procedure to deny certain of the float placement +% parameters: ``h'' and ``b'' are not possible, the former because the \cmd\marginpar\ mechanism +% cannot place a full-page-width float within a multicolumn page grid, the latter because nobody +% has yet written the code to do so (pretty bad reason, I know). +% \changes{4.1b}{2008/08/04}{New procedure \cs{@iffpsbit} replaces \cs{@getfpsbit}} +% \begin{macrocode} +\def\end@float{% + \end@@float{% + \check@currbox@count + }% +}% +\def\end@dblfloat{% + \@ifnum{\pagegrid@col=\@ne}{% + \end@float + }{% + \end@@float{% + \@iffpsbit\@ne{\global\advance\count\@currbox\m@ne}{}% + \@iffpsbit\f@ur{\global\advance\count\@currbox-4\relax}{}% + \global\wd\@currbox\textwidth % Klootch + \check@currbox@count + }% + }% +}% +\def\end@@float#1{% + \minipagefootnote@here + \@endfloatbox + #1% + \@ifnum{\@floatpenalty <\z@}{% + \@largefloatcheck + \@cons\@currlist\@currbox + \@ifnum{\@floatpenalty <-\@Mii}{% + \do@output@cclv{\@add@float}% + }{% + \vadjust{\do@output@cclv{\@add@float}}% + \@Esphack + }% + }{}% +}% +% \end{macrocode} +% The \classname{float} package of Anselm Lingnau fails when used under \classname{ltxgrid}, but +% we can fix things. +% We also repair a bug in that package. +% +% \changes{4.1g}{2009/10/06}{(AO, 531) Fix package \classname{float} } +% \begin{macrocode} +\newcommand\float@end@float{% + \@endfloatbox + \global\setbox\@currbox\float@makebox\columnwidth + \let\@endfloatbox\relax + \end@float +}% +\newcommand\float@end@ltx{% + \end@@float{% + \global\setbox\@currbox\float@makebox\columnwidth + \check@currbox@count + }% +}% +\newcommand\newfloat@float[3]{% + \@namedef{ext@#1}{#3} %! + \let\float@do=\relax + \xdef\@tempa{\noexpand\float@exts{\the\float@exts \float@do{#3}}}% + \@tempa + \floatplacement{#1}{#2}% + \@ifundefined{fname@#1}{\floatname{#1}{#1}}{} %! + \expandafter\edef\csname ftype@#1\endcsname{\value{float@type}}% + \addtocounter{float@type}{\value{float@type}} %! + \restylefloat{#1}% + \expandafter\edef\csname fnum@#1\endcsname{% + \expandafter\noexpand\csname fname@#1\endcsname{} %! + \expandafter\noexpand\csname the#1\endcsname + } + \@ifnextchar[%] + {% + \float@newx{#1}% + }{% + \@ifundefined{c@#1}{\newcounter{#1}\@namedef{the#1}{\arabic{#1}}}{}% + }% +}% +\newcommand\newfloat@ltx[3]{% + \@namedef{ext@#1}{#3}% + \let\float@do=\relax + \xdef\@tempa{\noexpand\float@exts{\the\float@exts \float@do{#3}}}% + \@tempa + \floatplacement{#1}{#2}% + \@ifundefined{fname@#1}{\floatname{#1}{#1}}{}% + \expandafter\edef\csname ftype@#1\expandafter\endcsname\expandafter{\the\c@float@type}% + \addtocounter{float@type}{\value{float@type}}% + \restylefloat{#1}% + \expandafter\edef\csname fnum@#1\endcsname{% + \expandafter\noexpand\csname fname@#1\endcsname{}% + \expandafter\noexpand\csname the#1\endcsname + } + \@ifnextchar[%] + {% + \float@newx{#1}% + }{% + \@ifundefined{c@#1}{\newcounter{#1}\@namedef{the#1}{\arabic{#1}}}{}% + }% +}% +\appdef\document@inithook{% + \@ifxundefined\newfloat{}{% + \@ifx{\float@end\float@end@float}{% + \@ifx{\newfloat\newfloat@float}{\true@sw}{\false@sw}% + }{\false@sw}% + {% + \class@warn{Repair the float package}% + \let\float@end\float@end@ltx + \let\newfloat\newfloat@ltx + }{% + \class@warn{Failed to patch the float package}% + }% + }% +}% +% \end{macrocode} +% +% Boolean procedure \cmd\@iffpsbit\ is similar to the \cmd\@getfpsbit\ of \LaTeX, except +% that we do not expose the scratch count register or even change its value. +% \begin{macrocode} +\def\@iffpsbit#1{% + \begingroup + \@tempcnta\count\@currbox + \divide\@tempcnta#1\relax + \@ifodd\@tempcnta{\aftergroup\true@sw}{\aftergroup\false@sw}% + \endgroup +}% +% \end{macrocode} +% +% In procedure \cmd\check@currbox@count, we calculate the net float placement +% directive (encoded into \cmd\count\ \cmd\@currbox's least significant four bits). +% If zero, issue a warning. +% \changes{4.1b}{2008/08/04}{Tally the height of the float} +% \begin{macrocode} +\def\check@currbox@count{% + \@ifnum{\count\@currbox>\z@}{% + \count@\count\@currbox\divide\count@\sixt@@n\multiply\count@\sixt@@n + \@tempcnta\count\@currbox\advance\@tempcnta-\count@ + \@ifnum{\@tempcnta=\z@}{% + \ltxgrid@warn{Float cannot be placed}% + }{}% + \expandafter\tally@float\expandafter{\@captype}% + }{% +% \end{macrocode} +% In this case, the float is a \cmd\marginpar. +% \begin{macrocode} + }% +}% +\providecommand\minipagefootnote@init{}% +\providecommand\minipagefootnote@here{}% +\providecommand\tally@float[1]{}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@specialoutput} +% The \cmd\@add@float\ procedure used to reside in standard \LaTeX's \cmd\@specialoutput, +% which is no more. +% +% Historical Note: \cmd\@specialoutput\ and Lamport's method of an output routine dispatcher +% is the genesis of our more powerful and refined way of using \TeX's output routine to +% safely accomplish page makeup tasks. To it and to him we owe acknowledgement and thanks. +% \begin{macrocode} +\let\@specialoutput\@undefined +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@add@float} +% In the following, we do not need to execute \cmd\@reinserts, which was wrong anyway, as you cannot +% reliably recover insertions when they split (unless you have a way of reinserting the captured insertion +% ahead of the split-off part). +% +% Now that full-page-width floats are being processed the same as column floats, we +% have to nip in here and cause them always to be deferred. +% +% At the very end, the \cmd\vsize\ is adjusted for any newly committed float. +% \begin{macrocode} +\def\@add@float{% + \@pageht\ht\@cclv\@pagedp\dp\@cclv + \unvbox\@cclv + \@next\@currbox\@currlist{% + \csname @floatselect@sw@\thepagegrid\endcsname\@currbox{% + \@ifnum{\count\@currbox>\z@}{% + \advance \@pageht \@pagedp +% \end{macrocode} +% Do not assume \cmd\holdinginserts is cleared: +% \begin{macrocode} + \advance \@pageht \vsize \advance \@pageht -\pagegoal +% \end{macrocode} +% Commit an `h' float: +% \begin{macrocode} + \@addtocurcol + }{% + \@addmarginpar + }% + }{% + \@resethfps + \@cons\@deferlist\@currbox + }% + }{\@latexbug}% + \@ifnum{\outputpenalty<\z@}{% + \@if@sw\if@nobreak\fi{% + \nobreak + }{% + \addpenalty \interlinepenalty + }% + }{}% + \set@vsize +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@reinserts} +% The \cmd\@reinserts\ procedure of standard \LaTeX\ is now obsoleted (it had been erroneous anyway). +% \begin{macrocode} +\let\@reinserts\@undefined +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@addtocurcol} +% We modify the \cmd\@addtocurcol\ procedure of standard \LaTeX\ +% so that a float placed ``here'' may break over pages. +% \begin{macrocode} +\def \@addtocurcol {% + \@insertfalse + \@setfloattypecounts + \ifnum \@fpstype=8 + \else + \ifnum \@fpstype=24 + \else + \@flsettextmin + \advance \@textmin \@textfloatsheight + \@reqcolroom \@pageht + \ifdim \@textmin>\@reqcolroom + \@reqcolroom \@textmin + \fi + \advance \@reqcolroom \ht\@currbox + \ifdim \@colroom>\@reqcolroom + \@flsetnum \@colnum + \ifnum \@colnum>\z@ + \@bitor\@currtype\@deferlist + \if@test + \else + \@bitor\@currtype\@botlist + \if@test + \@addtobot + \else + \ifodd \count\@currbox + \advance \@reqcolroom \intextsep + \ifdim \@colroom>\@reqcolroom + \global \advance \@colnum \m@ne + \global \advance \@textfloatsheight \ht\@currbox + \global \advance \@textfloatsheight 2\intextsep + \@cons \@midlist \@currbox + \if@nobreak + \nobreak + \@nobreakfalse + \everypar{}% + \else + \addpenalty \interlinepenalty + \fi + \vskip \intextsep + \unvbox\@currbox %AO + \penalty\interlinepenalty + \vskip\intextsep + \ifnum\outputpenalty <-\@Mii \vskip -\parskip\fi + \outputpenalty \z@ + \@inserttrue + \fi + \fi + \if@insert + \else + \@addtotoporbot + \fi + \fi + \fi + \fi + \fi + \fi + \fi + \if@insert + \else + \@resethfps + \@cons\@deferlist\@currbox + \fi +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\if@twocolumn} +% The \cmd\newif\ switch \cmd\if@twocolumn\ is entirely unused. However its access words are invoked by +% \LaTeX's \cmd\document\ procedure, so we de-fang it. +% \begin{macrocode} +\@twocolumnfalse +\let\@twocolumntrue\@twocolumnfalse +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@addmarginpar} +% The procedure \cmd\@addmarginpar\ used to access \cmd\if@twocolumn, but that switch is not reliable; +% the better way is to use \cmd\thepagegrid. We establish a convention for a page-grid-oriented +% procedure, e.g., \cmd\@addmarginpar@one, that emits a boolean, telling this procedure +% whether to set the marginpar on the left or right. +% \begin{macrocode} +\def\@addmarginpar{% + \@next\@marbox\@currlist{% + \@cons\@freelist\@marbox\@cons\@freelist\@currbox + }\@latexbug + \setbox\@marbox\hb@xt@\columnwidth{% + \csname @addmarginpar@\thepagegrid\endcsname{% + \hskip-\marginparsep\hskip-\marginparwidth + \box\@currbox + }{% + \hskip\columnwidth\hskip\marginparsep + \box\@marbox + }% + \hss + }% + \setbox\z@\box\@currbox + \@tempdima\@mparbottom + \advance\@tempdima -\@pageht + \advance\@tempdima\ht\@marbox + \@ifdim{\@tempdima >\z@}{% + \@latex@warning@no@line {Marginpar on page \thepage\space moved}% + }{% + \@tempdima\z@ + }% + \global\@mparbottom\@pageht + \global\advance\@mparbottom\@tempdima + \global\advance\@mparbottom\dp\@marbox + \global\advance\@mparbottom\marginparpush + \advance\@tempdima -\ht\@marbox + \global\setbox \@marbox + \vbox {\vskip \@tempdima + \box \@marbox}% + \global \ht\@marbox \z@ + \global \dp\@marbox \z@ + \kern -\@pagedp + \nointerlineskip + \box\@marbox + \nointerlineskip + \hbox{\vrule \@height\z@ \@width\z@ \@depth\@pagedp}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{turnpage} +% Any float (viz., \env{figure} or \env{table}) within the scope of this environment +% will be a turnpage float: It will be assumed to occupy an entire page (constitute a float page), +% the width will be \cmd\textheight, the height \cmd\textwidth, and the entire float will be presented +% rotated 90 degrees. +% +% The implementation requires the services of the \cmd\rotatebox\ command, so we supply a dummy definition +% that explains things to the user. +% \begin{macrocode} +\newenvironment{turnpage}{% + \def\width@float{\textheight}% + \def\widthd@float{\textheight}% + \appdef\@endfloatbox{% + \@ifxundefined\@currbox{% + \ltxgrid@warn{Cannot rotate! Not a float}% + }{% + \setbox\@currbox\vbox to\textwidth{\vfil\unvbox\@currbox\vfil}% + \global\setbox\@currbox\vbox{\rotatebox{90}{\box\@currbox}}% + }% + }% +}{% +}% +\def\rotatebox@dummy#1#2{% + \ltxgrid@warn{You must load the graphics or graphicx package in order to use the turnpage environment}% + #2% +}% +% \end{macrocode} +% \changes{4.1b}{2008/08/04}{Use \cs{document@inithook} instead of \cs{AtBeginDocument}} +% \begin{macrocode} +\appdef\document@inithook{% + \@ifxundefined\rotatebox{\let\rotatebox\rotatebox@dummy}{}% +}% +% \end{macrocode} +% \end{environment} +% +% +% \subsection{One-off output routines} +% +% These procedures are executed in lieu of \cmd\the\cmd\output\ when the output penalty has the associated flag value. +% +% \begin{macro}{output@-1073741824} +% The first one-off output routine handles the end of the job, wherein +% \LaTeX\ executes \cmd\@@end, and breaks to the output with a penalty of +% $"40000000 = 2^{32}/4 = 1073741824$. +% We simply discard \cmd\box\cmd\@cclv\ and leave. +% This means that \LaTeX\ is obligated to do \cmd\clearpage\ as part of +% its \enve{document} processing, otherwise material will be lost. +% \begin{macrocode} +\@namedef{output@-1073741824}{% + \deadcycles\z@ +% \end{macrocode} +% \begin{verbatim} +%\showbox\@cclv +% \end{verbatim} +% \begin{macrocode} + \void@cclv +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\save@column@pen} +% The one-off output routine associated with \cmd\penalty\cmd\save@column@pen\ +% will be called within a sequence of three such routines by \cmd\execute@message +% or its companion routine \cmd\execute@message@insert. +% This procedure must save away any the current page and preserve marks. +% \begin{macrocode} +\mathchardef\save@column@pen=10016 +\@namedef{output@-\the\save@column@pen}{\save@column}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@cclv@saved} +% We take over the \cmd\@holdpg\ box register. Hereafter, +% we no longer use the \cmd\@holdpg\ box register, so let the world know. +% This should decisively break packages that assume standard \LaTeX. +% Breaking decisively is preferred to quietly proceeding erroneously. +% \begin{macrocode} +\let \@cclv@saved \@holdpg +\let \@holdpg \@undefined +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\save@column} +% The procedure \cmd\save@column\ does the actual work of saving away the material +% on the page. It is invoked both by \cmd\save@column@pen\ and by \cmd\save@column@insert@pen. +% We save \cmd\box\cmd\@cclv\ and the primitive \cmd\@@topmark. +% \begin{macrocode} +\def\save@column{% + \@ifvoid\@cclv@saved{% + \set@top@firstmark + \global\@topmark@saved\expandafter{\@@topmark}% + }{}% + \global\setbox\@cclv@saved\vbox{% + \@ifvoid\@cclv@saved{}{% + \unvbox\@cclv@saved + \marry@baselines + }% + \unvbox\@cclv + \lose@breaks + \remove@lastbox + }% +}% +\newtoks\@topmark@saved +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\prep@cclv} +% The procedure \cmd\prep@cclv\ is used by message handlers to set up their environment +% to ape that of the usual output routine, with the boxed-up page in \cmd\box\cmd\@cclv. +% Here, we retrieve the material from \cmd\@cclv@saved, where it was saved away by +% the one-off output routine associated with \cmd\save@column@pen. +% \begin{macrocode} +\def\prep@cclv{% + \void@cclv + \setbox\@cclv\box\@cclv@saved + \vbadness\@M +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\save@column@insert@pen} +% The one-off output routine associated with \cmd\penalty\cmd\save@column@insert@pen\ +% is similar to that of \cmd\save@column@pen\ augmented with the processing of insertions. +% It is called by \cmd\execute@message@insert\ (i.e., at a grid change) +% and saves away the current page and preserves marks. +% In addition, it saves away any insertions that fall on the current page. +% As with the natural output routine, it executes in two phases, +% first with \cmd\holdinginserts\ set, then cleared. +% \begin{macrocode} +\mathchardef\save@column@insert@pen=10017 +\@namedef{output@-\the\save@column@insert@pen}{\toggle@insert{\savecolumn@holding}{\savecolumn@moving}}% +% \end{macrocode} +% The procedure \cmd\savecolumn@holding\ is the first phase of saving a column with its inserts. +% This phase must detect and remedy the one circumstance that will confound our efforts to propagate marks. +% It is similar to \cmd\output@holding, except that we have to deal with the protection box, which must +% remain, because the messaging mechanism is being used. +% +% If it appears that we have the pathological ``Big Bad Box'' case at hand, we use the \cmd\dead@cycle@repair@protected\ +% procedure instead of \cmd\dead@cycle\ to do our dead cycle. +% \changes{4.1b}{2008/08/04}{Use \cs{trace@box} instead of \cs{showbox}} +% \begin{macrocode} +\def\savecolumn@holding{% + \@if@exceed@pagegoal{\unvcopy\@cclv\remove@lastbox}{% + \setbox\z@\vbox{\unvcopy\@cclv\remove@lastbox}% + \outputdebug@sw{\trace@box\z@}{}% + \dimen@\ht\@cclv\advance\dimen@-\ht\z@ + \dead@cycle@repair@protected\dimen@ + }{% + \dead@cycle + }% +}% +% \end{macrocode} +% \changes{4.1b}{2008/08/04}{New procedure for showing a box contents, \cs{trace@box}} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% The procedure \cmd\save@column@moving\ is the second phase of saving a column with its inserts. +% Now that \cmd\holdinginserts\ is cleared, we can look in the various \cmd\insert\ registers for +% our inserts (at present there is only one, \cmd\footins, along with \cmd\footins@saved). +% if anything is there, we save it away and ask for another cycle (because it may have split). +% +% Note that the message that is about to be executed had better deal properly with the contents of +% the \cmd\footins@saved\ box. +% +% \begin{macrocode} +\def\savecolumn@moving{% + \ltxgrid@info@sw{\class@info{\string\savecolumn@moving}}{}% + \@cclv@nontrivial@sw{% + \save@column + }{% + \void@cclv + }% + \@ifvoid\footins{}{% + \ltxgrid@foot@info@sw{\class@info{\string\savecolumn@moving}\trace@scroll{\showbox\footins@saved\showbox\footins}}{}% +% \end{macrocode} +% Save all away in \cmd\footins@saved. Note that if \cmd\footins\ is void, then \cmd\footins@saved\ remains untouched. +% \begin{macrocode} + \@ifvoid\footins@saved{% + \global\setbox\footins@saved\box\footins + }{% + \global\setbox\footins@saved\vbox\bgroup + \unvbox\footins@saved + \marry@baselines + \unvbox\footins + \egroup + }% + \ltxgrid@foot@info@sw{\trace@box\footins@saved}{}% + \protect@penalty\save@column@insert@pen + }% +}% +\newbox\footins@saved +\newbox\footins@recovered +\newbox\column@recovered +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\save@message@pen} +% The one-off output routine associated with \cmd\penalty\cmd\save@message@pen\ +% saves away the message that has been passed. +% This procedure is penultimate in a sequence of one-off output routine calls; +% earlier ones have saved away the MVL and preserved marks, the last executes the message. +% +% Note that we are passing tokens to \TeX's primitive \cmd\mark\ mechanism, so we must ensure +% that they are not inappropriately expanded. We use the same mechanism for all such cases, +% namely \cmd\let@mark. +% +% Note: we expect that \cmd\box\cmd\@cclv's contents are well known: +% \cmd\topskip, protection box, and a \cmd\mark, the latter containing the message. +% But if we came here via \cmd\penalty 10017, there might be an \cmd\insert\ node present as well, +% because a footnote may have split. +% Because this procedure simply voids out \cmd\box\cmd\@cclv, such material would be lost. +% Perhaps we can repair things by manipulating the \cmd\insert \ mechanism temporarily. +% \begin{macrocode} +\mathchardef\save@message@pen=10018 +\@namedef{output@-\the\save@message@pen}{\save@message}% +\def\save@message{% + \void@cclv +% \end{macrocode} +%FIXME: what if \cmd\box\cmd\@cclv is not empty? +% \begin{macrocode} + \toks@\expandafter{\@@firstmark}% + \expandafter\gdef\expandafter\@message@saved\expandafter{\the\toks@}% + \expandafter\do@@mark\expandafter{\the\@topmark@saved}% +}% +\gdef\@message@saved{}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\execute@message@pen} +% The one-off output routine associated with \cmd\execute@message@pen\ +% simply executes the given message. It is last in a sequence of one-off output routine calls; +% earlier ones have saved all that require saving. +% \begin{macrocode} +\mathchardef\execute@message@pen=10019 +\@namedef{output@-\the\execute@message@pen}{\@message@saved}% +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Output messages} +% +% Message handlers are procedures that execute output messages, tokens that are passed to +% the output routine for execution in an environment appropriate to page makeup. +% +% How it works. We put down three large negative penalties, each of which will be handled by +% the output dispatcher (\emph{not} the natural output routine), each penalty being protected by +% a removable, non-discardable item (i.e., a box). +% Either three or four invocations of one-off output routines are involved per message. +% +% We make the last of the three protection boxes have a depth equal to the value of \cmd\prevdepth\ +% that was current when the procedure is called. This effectively restores \cmd\prevdepth. +% +% In each case, the one-off output routine will remove the extraneous box we have inserted. +% And the second and third one-off routines will simply void \cmd\box\cmd\@cclv, because its contents +% are entirely artificial. +% +% FIXME: not so! If \cmd\holdinginserts\ is cleared, that box may have an insert node; it must be preserved, too. +% +% The first routine saves away the current column contents and remembers the \cmd\topmark\ for later +% use. There is a variant routine that first clears \cmd\holdinginserts, so that the message can +% handle any inserts present in the boxed-up page; this of course entails yet another +% visit to the output routine. +% +% The penultimate routine saves away the tokens transmitted in via the \cmd\@@mark: the argument of +% the macro. These tokens are of course the very thing we wish to execute within the safety +% of the output routine. It also puts down a mark containing the \cmd\topmark\ tokens saved +% by the first routine. By this means, the mark, which we have clobbered, is restored. +% +% The last routine simply executes the given tokens. +% In the course of doing this, it must take care of \cmd\box\cmd\@cclv, either by shipping it out, +% or by \cmd\unvbox ing it onto the MVL. +% +% \begin{macro}{\execute@message} +% The procedure \cmd\execute@message\ simply calls the utility procedure \cmd\@execute@message\ +% with a penalty value for the standard treatment. +% \begin{macrocode} +\def\execute@message{% + \@execute@message\save@column@pen +% \end{macrocode} +% Implicit second argument +% \begin{macrocode} +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\execute@message@insert} +% The procedure \cmd\execute@message@insert\ is like \cmd\execute@message\ in all respects +% except that the penalty value is \cmd\save@column@insert@pen, which arranges for the +% message handler involved to deal with the page's insertions. +% At the same time, we prepare the \cmd\footins\ box so that these insertions can be dealt with. +% +% Note: +% If more insertions are added to \LaTeX\ (presumably via \cmd\newinsert), then they +% must be dealt with in a way entirely analogous to \cmd\footins. +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \begin{macrocode} +\def\execute@message@insert#1{% + \@execute@message\save@column@insert@pen{% + \setbox \footins \box \footins@saved + \ltxgrid@foot@info@sw{\class@info{\string\execute@message@insert}\trace@box\footins}{}% + #1% + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@execute@message} +% The utility procedure \cmd\@execute@message\ is called by \cmd\execute@message\ and \cmd\execute@message@insert. +% We prepare by creating a \cmd\vbox\ containing all the needed nodes and proceed by simply +% \cmd\unvbox ing that box onto the MVL. +% We ensure that \cmd\box\cmd\@cclv\ is properly set up for the output message handler +% by always inserting \cmd\prep@cclv\ in advance of the argument. +% +% Note that each one-off output routine is invoked effectively the same as +% \cmd\protect@penalty, except that the second invocation involves an additional +% \cmd\mark\ node, and the third a specially prepared protection box. +% +% Note also that \TeX's primitive \cmd\mark\ is called here without any expansion protection. +% This is the only place where it is called that way, but it's OK because those tokens +% have have been pre-expanded by procedures that call \cmd\execute@message. +% FIXME: all procedures calling \cmd\execute@message\ must pre-expand their tokens! +% \begin{macrocode} +\long\def\@execute@message#1#2{% + \begingroup + \dimen@\prevdepth\@ifdim{\dimen@<\z@}{\dimen@\z@}{}% + \setbox\z@\vbox{% + \protect@penalty#1% + \protection@box + \toks@{\prep@cclv#2}% + \@@mark{\the\toks@}% + \penalty-\save@message@pen +% \end{macrocode} +%\begin{verbatim} +% \hbox{\vrule\@height\z@\@width\z@\@depth\dimen@}% +%\end{verbatim} +% \begin{macrocode} + \setbox\z@\null\dp\z@\dimen@\ht\z@-\dimen@ + \nointerlineskip\box\z@ + \penalty-\execute@message@pen + }\unvbox\z@ + \endgroup +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\do@output@cclv} +% The procedure \cmd\do@output@cclv\ provides access to message handlers at their simplest. +% The message will execute in the usual environment of the output routine, with +% the boxed-up page in \cmd\box\cmd\@cclv, and we assume that \cmd\holdinginserts\ remains set. +% This procedure must be invoked within main vertical mode; +% it is the obligation of the macro writer to ensure that this is the case. +% \begin{macrocode} +\def\do@output@cclv{\execute@message}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\do@output@MVL} +% The procedure \cmd\do@output@MVL, like \cmd\do@output@cclv, is an interface for messages, +% but provides two additional services: the command may also be invoked in horizontal mode, and +% the message handler will execute with the MVL unboxed. +% \begin{macrocode} +\def\do@output@MVL#1{% + \@ifvmode{% + \begingroup\execute@message{\unvbox\@cclv#1}\endgroup + }{% + \@ifhmode{% + \vadjust{\execute@message{\unvbox\@cclv#1}}% + }{% + \@latexerr{\string\do@output@MVL\space cannot be executed in this mode!}\@eha + }% + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\lose@breaks} +% The purpose of this procedure is to get rid of all the extraneous +% \cmd\penalty\cmd\@M\ nodes that tend to build up in the MVL. +% \begin{macrocode} +\def\lose@breaks{% + \loopwhile{% + \count@\lastpenalty + \@ifnum{\count@=\@M}{% +% \end{macrocode} +% Note: 10000 is a TeX magic number! +% \begin{macrocode} + \unpenalty\true@sw + }{% + \false@sw + }% + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\removestuff} +% \cmd\removestuff\ is a document-level command that removes the bottom skip glue item +% from the MVL. +% \begin{macrocode} +\def\removestuff{\do@output@MVL{\unskip\unpenalty}}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\removephantombox} +% The procedure \cmd\removephantombox\ is a special-purpose message handler exclusively for +% preventing incorrect spacing above display math. It must be issued in +% horizontal mode within the phantom paragraph generated when display math starts up in +% vertical mode. +% \begin{macrocode} +\def\removephantombox{% + \vadjust{% + \execute@message{% + \unvbox\@cclv + \remove@lastbox + \unskip + \unskip + \unpenalty + \penalty\predisplaypenalty + \vskip\abovedisplayskip + }% + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\addstuff} +% \cmd\addstuff\ is a document-level command that adds penalty, glue, or both to the +% MVL. The penalty and glue items are rearranged so that all penalties nodes precede all the glue nodes, +% which is the canonical arrangement. +% \begin{macrocode} +\def\addstuff#1#2{\edef\@tempa{\noexpand\do@output@MVL{\noexpand\@addstuff{#1}{#2}}}\@tempa}% +\def\@addstuff#1#2{% + \skip@\lastskip\unskip + \count@\lastpenalty\unpenalty + \@if@empty{#1}{}{\penalty#1\relax}% + \@ifnum{\count@=\z@}{}{\penalty\count@}% + \vskip\skip@ + \@if@empty{#2}{}{\vskip#2\relax}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\replacestuff} +% \cmd\replacestuff\ is a document-level command similar to \cmd\addstuff; +% but it replaces penalty, glue, or both in the MVL. +% The penalty and glue items are rearranged so that all penalties nodes precede all the glue nodes, +% which is the canonical arrangement. +% \begin{macrocode} +\def\replacestuff#1#2{\edef\@tempa{\noexpand\do@output@MVL{\noexpand\@replacestuff{#1}{#2}}}\@tempa}% +\def\@replacestuff#1#2{% + \skip@\lastskip\unskip + \count@\lastpenalty\unpenalty + \@if@empty{#1}{}{% + \@ifnum{\count@>\@M}{}{% + \@ifnum{\count@=\z@}{\count@=#1\relax}{% + \@ifnum{\count@<#1\relax}{}{% + \count@=#1\relax + }% + }% + }% + }% + \@ifnum{\count@=\z@}{}{\penalty\count@}% + \@if@empty{#2}{}{% + \@tempskipa#2\relax + \@ifdim{\z@>\@tempskipa}{% + \advance\skip@-\@tempskipa + }{% + \@ifdim{\skip@>\@tempskipa}{}{% + \skip@\@tempskipa + }% + }% + }% + \vskip\skip@ +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\move@insertions} +% \begin{macro}{\hold@insertions} +% In order to avoid bolluxing up \cmd\insert\ registers by our one-off +% output routines, we set \cmd\holdinginserts\ to zero by default and only +% clear it (briefly) while we handle cases where we want inserts to show up. +% \begin{macrocode} +\def\move@insertions{\global\holdinginserts\z@}% +\def\hold@insertions{\global\holdinginserts\@ne}% +\hold@insertions +\def\toggle@insert#1#2{% + \@ifnum{\holdinginserts>\z@}{\move@insertions#1}{\hold@insertions#2}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \subsection{Messages to alter the page grid}% +% +% Here is the implementation of the grid-switching procedures. +% We perform two checks when changing the page grid; first to ensure that +% the target page grid is known (defensive programming), second to ensure that +% the switch is a non-trivial one. The latter check must be performed within +% the safety of the output routine, so requires using an output message. +% Thus, a grid change requires two messages, for a total of six visits to the output routine. +% +% \begin{macro}{\do@columngrid} +% Utility procedure \cmd\do@columngrid\ changes the page grid. +% Note that this command forces an end to the current paragraph. This is necessary, because +% a page grid change makes no sense unless we can alter the \cmd\hsize\ before commencing to +% typeset the following paragraph. So the command should never be executed in horizontal mode +% anyway. +% \begin{macrocode} +\def\do@columngrid#1#2{% + \par + \expandafter\let\expandafter\@tempa\csname open@column@#1\endcsname + \@ifx{\relax\@tempa}{% + \ltxgrid@warn{Unknown page grid #1. No action taken}% + }{% + \do@output@MVL{\start@column{#1}{#2}}% + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\start@column} +% Procedure \cmd\start@column\ lays down the interrupts to switch the page grid. +% If the change to the page grid would have been trivial, it bails out. +% It seems a reasonable tradeoff of processing versus security: once we commit +% to changing the page grid, we clear \cmd\holdinginserts, so there is no turning back. +% +% Note that the second argument to the macro allows us to pass an argument to the +% page grid that is starting up. This can be handy, because a single procedure can +% handle multiple page grids, differing only by the value of a parameter. +% +% FIXME: this means that you cannot switch between mlt page grids in a single step. +% But do we want to do this, at all, at all? +% \begin{macrocode} +\def\start@column#1#2{% + \def\@tempa{#1}\@ifx{\@tempa\thepagegrid}{% + \ltxgrid@info{Already in page grid \thepagegrid. No action taken}% + }{% + \expandafter\execute@message@insert + \expandafter{% + \csname shut@column@\thepagegrid\expandafter\endcsname + \csname open@column@#1\endcsname{#2}% + \set@vsize + }% + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\thepagegrid} +% The macro \cmd\thepagegrid\ tracks what kind of page grid we are in. +% +% Note: Access \cmd\thepagegrid\ only within the safety of the output routine. +% +% Warning: The page grid should be changed only within the safety of the output routine. +% People who write multicol page grid mechanisms appear not to understand the matter, so they +% should particularly heed this warning. Think about it: obviously Lamport did so, which is why +% his \cmd\twocolumn\ command forced a pagebreak, which is limiting, but safe. +% \begin{macrocode} +\def\thepagegrid{one}% +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Application Note: implementing a page grid} +% +% If you want to create a new page grid for \LaTeX, +% you must define five procedures with specific names: +% \cmd\open@column@ name, \cmd\shut@column@ name, \cmd\end@column@ name, +% \cmd\output@column@ name, and \cmd\@addmarginpar@ name, where ``name'' is the +% name of your page grid. +% +% The procedure \cmd\open@column@ name starts the new page grid. It should define \cmd\thepagegrid, +% deal with \cmd\box\cmd\pagesofar\ and \cmd\box\cmd\footsofar\ (perhaps by leaving them alone), +% and it should set the values of \LaTeX's page layout parameters for the column size and height. +% +% The procedure \cmd\shut@column@ name should expect to be called with \cmd\holdinginserts\ +% cleared (it can assume that \cmd\holdinginserts\ will automatically be restored). +% It should properly deal with insertions (like footnotes); calling \cmd\@makecolumn\ +% with an argument of \cmd\false@sw\ will do this. +% It should know that the page grid is being terminated +% in the middle of a page, so it should make arrangements to carry the footnotes down to the +% bottom of the column or page, and it should possibly salt away the material for later +% incorporation into the page. The box registers \cmd\footsofar\ and \cmd\pagesofar\ are customarily used +% for this purpose. +% +% The procedure \cmd\end@column@ name should kick out a possibly short page containing all the +% floats committed to the page. It will be invoked during \cmd\clearpage\ processing. +% After that, it should \cmd\unvbox\cmd\@cclv. +% +% The procedure \cmd\output@column@ name should ship out or commit the current \cmd\@outputbox. +% In a one-column layout, you ship out; in a multicolumn layout, you commit the box as the contents +% of a particular column, and if that column is the last, you ship out. +% +% The procedure \cmd\@addmarginpar@ name should return a boolean (either \cmd\true@sw\ or \cmd\false@sw\ or an equivalent) +% to tell the marginpar mechanism to place the marginal material to the right or left, respectively. +% +% You can use the existing page grids ``one'' and ``mlt'' as a point of departure for creating others. +% The former can be the basis for, say, a single-column page grid with a side column. +% +% \begin{macro}{\pagesofar} +% \begin{macro}{\footsofar} +% The box register \cmd\pagesofar\ holds the portion of the (full-width) page that is already composed into columns. +% This, plus the finished columns, each with its floats, plus \cmd\box255 constitute the full galley. +% +% The box register \cmd\footsofar\ holds all of the footnotes associated with \cmd\pagesofar. +% \begin{macrocode} +\newbox\pagesofar +\newbox\footsofar +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\combine@foot@inserts} +% \changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +% \changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +% The procedure \cmd\combine@foot@inserts\ is for the purpose of merging +% the recently contributed footnotes (usually \cmd\box\cmd\footins) +% with those saved from earlier on the page (usually \cmd\box\cmd\footsofar). +% +% It is employed in a number of circumstances. +% +% \cmd\@makecolumn (when its argument is \cmd\false@sw): +% we are not shipping out, so we need to salt away any footnotes there may be. +% +% \cmd\shut@column@one: we are leaving the one-column page grid, so recover the footnotes from that material +% and combine them with those of \cmd\pagesofar. +% +% \expandafter\cmd\csname balance@2\endcsname: two columns of type have been balanced, so now balance the footnotes. +% The \cmd\combine@foot@inserts\ procedure is first used to gather footnotes from the columns balanced with those of \cmd\pagesofar. +% +% Bug 571 note: if balancing a two-column page grid, and there had been footnotes in the \cmd\pagesofar, +% those footnotes will have been balanced into a page-width box, \cmd\box\cmd\footsofar. +% We need to now re-cast them into a single, column-width galley, and only then +% combine them with those in \cmd\box\cmd\footins. +% +% \begin{macrocode} +\def\combine@foot@inserts#1#2{% + \ltxgrid@info@sw{\class@info{\string\combine@foot@inserts\string#1\string#2}}{}% + \@ifvoid#1{% + \ltxgrid@foot@info@sw{\trace@box#2}{}\global\setbox#1\box#2% + }{% + \global\setbox#1\vbox\bgroup + \ltxgrid@foot@info@sw{\trace@box#1}{}\unvbox#1% + \@ifvoid#2{}{% + \marry@baselines + \ltxgrid@foot@info@sw{\trace@box#2}{}\unvbox#2% + }% + \egroup + }% + \ltxgrid@foot@info@sw{\trace@scroll{\showbox#1\showbox#2}}{}% +}% +% \end{macrocode} +% \end{macro} +% +% +% \subsubsection{One-column page grid} +% +% \begin{macro}{\onecolumngrid} +% \begin{macro}{\open@column@one} +% \begin{macro}{\shut@column@one} +% \begin{macro}{\float@column@one} +% \begin{macro}{\end@column@one} +% \begin{macro}{\output@column@one} +% \begin{macro}{\@addmarginpar@one} +% Here are all the procedures necessary for the standard page grid named ``one'': +% a single column layout. It is, of course, \LaTeX's familiar \cmd\onecolumn\ layout. +% We begin with the procedure exposed to the style writer. +% This is, however, not a \LaTeX\ command; users should not change the page grid. +% \begin{macrocode} +\newcommand\onecolumngrid{\do@columngrid{one}{\@ne}}% +% \end{macrocode} +% +% Note that a document class that issues the command \cmd\onecolumn\ will break. This includes +% \LaTeX's standard classes.dtx-based classes: if your class descends from one of these, you +% must expunge it of all such commands. +% \begin{macrocode} +\let\onecolumn\@undefined +% \end{macrocode} +% +% The procedure \cmd\open@column@one\ takes advantage of the special nature of the one-column +% page grid to deal with \cmd\box\cmd\pagesofar, therefore it must also reset \cmd\@colroom. +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \begin{macrocode} +\def\open@column@one#1{% + \ltxgrid@info@sw{\class@info{\string\open@column@one\string#1}}{}% +% \end{macrocode} +% Throw the \cmd\pagesofar\ back onto the Main Vertical List. +% At this point, we must also \cmd\insert\ the footnotes back into the MVL. +% \changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +% \begin{macrocode} + \unvbox\pagesofar + \@ifvoid{\footsofar}{}{% + \insert\footins\bgroup\unvbox\footsofar\egroup + \penalty\z@ + }% +% \end{macrocode} +% Record which page grid we are using. Then calculate the set width (\cmd\hsize) and the goal height (\cmd\vsize). +% +% Klootch: we set the \cmd\count\cmd\footins\ to a magic number. This is only correct in the case of a two-column document. +% \begin{macrocode} + \gdef\thepagegrid{one}% + \global\pagegrid@col#1% + \global\pagegrid@cur\@ne + \global\count\footins\@m + \global\divide\count\footins\tw@ + \set@column@hsize\pagegrid@col + \set@colht +}% +% \end{macrocode} +% +% The procedure \cmd\shut@column@one\ saves away the one-column material into the box register \cmd\pagesofar. +% Because it is called from a message handler, we are assured that marks are properly taken care of. +% +% This instance of \cmd\@makecolumn\ is building a column for saving into \cmd\pagesofar. +% \changes{4.1b}{2008/08/04}{Change \cs{@makecol} to \cs{@makecolumn} with argument} +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% \changes{4.1f}{2009/07/15}{(AO, 519) Preserve footnotes that are in \cs{footsofar} across a page grid change} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +% We recover the footnotes into \cmd\footsofar\ (globally) and the column into \cmd\pagesofar\ (also globally), voiding \cmd\@outputbox\ by side effect. +% \begin{macrocode} +\def\shut@column@one{% + \ltxgrid@info@sw{\class@info{\string\shut@column@one}}{}% + \@makecolumn\false@sw +% \end{macrocode} +% Split text portion of \cmd\@outputbox\ into \cmd\pagesofar, +% and add its footnote portion to \cmd\footsofar. +% Then void out \cmd\@outputbox. +% \begin{macrocode} + \global\setbox\pagesofar\vbox\bgroup + \recover@column\@outputbox\footsofar\column@recovered\footins@recovered + \egroup + \begingroup\setbox\z@\box\@outputbox\endgroup +% \end{macrocode} +% FIXME: is \cmd\combine@foot@inserts\ needed? +% Also: if this procedure is immediately followed by \cmd\open@column@ \texttt{grid}, then \cmd\set@colht\ will be unneeded. +% \begin{macrocode} + \combine@foot@inserts\footsofar\footins + \set@colht +}% +% \end{macrocode} +% +%FIXME: the first line of a footnote should have an up-strut, and the last line a down-strut, so that they can marry baselines. +% The latter is the case; how about the former? +% +% The procedure \cmd\float@column@one\ takes care of a float column that has been built by +% \cmd\@tryfcolumn, in the single-column page grid. +% +% This instance of \cmd\@makecolumn\ is followed by \cmd\@outputpage: it is building +% a column for \cmd\shipout, rather than for saving into \cmd\pagesofar. +% \changes{4.1b}{2008/08/04}{Change \cs{@makecol} to \cs{@makecolumn} with argument} +% \begin{macrocode} +\def\float@column@one{% + \@makecolumn\true@sw + \@outputpage +}% +% \end{macrocode} +% +% The procedure \cmd\end@column@one\ is executed at the end of \cmd\clearpage\ processing, +% if we were in a one-column page grid, once all permissive float pages have been shipped out. +% At this point, one could perhaps +% assume that nothing more need be done, but let us anyway test for committed floats and force a shipout. +% +% FIXME: this procedure does the same as \cmd\end@column@mlt +% (except for the test of \cmd\@ifx@empty\cmd\@dbltoplist): +% the two could almost be the same procedure. +% +% I have changed this procedure to avoid the testing it once did: it simply puts down interrupts, +% upon which it relies to correctly do what \cmd\clearpage\ requires. +% \begin{macrocode} +\def\end@column@one{% + \unvbox\@cclv\remove@lastbox + \protect@penalty\do@newpage@pen +}% +% \end{macrocode} +% +% The procedure \cmd\output@column@one\ is dispatched from the output routine when +% we have completed a page (that is, a column in a one-column page grid); +% it ships out the page using the \cmd\@outputpage. +% It will be followed up with an output routine message to prepare a new column. +% +% Query: by what mechanism do the footnotes get placed onto such a page? +% \begin{macrocode} +\def\output@column@one{% + \@outputpage +}% +% \end{macrocode} +% +% The following procedure determines which side of the page a marginpar will appear. +% It reproduces the behavior of standard \LaTeX. +% \begin{macrocode} +\def\@addmarginpar@one{% + \@if@sw\if@mparswitch\fi{% + \@ifodd\c@page{\false@sw}{\true@sw}% + }{\false@sw}{% + \@if@sw\if@reversemargin\fi{\false@sw}{\true@sw}% + }{% + \@if@sw\if@reversemargin\fi{\true@sw}{\false@sw}% + }% +}% +% \end{macrocode} +% +% The following procedure yields a Boolean value; it determines whether a float in the deferred queue +% is appropriate for placing. In the one-column grid, all floats are so. +% \begin{macrocode} +\def\@floatselect@sw@one#1{\true@sw}% +% \end{macrocode} +% +% \begin{macrocode} +\def\onecolumngrid@push{% + \do@output@MVL{% + \@ifnum{\pagegrid@col=\@ne}{% + \global\let\restorecolumngrid\@empty + }{% + \xdef\restorecolumngrid{% + \noexpand\start@column{\thepagegrid}{\the\pagegrid@col}% + }% + \start@column{one}{\@ne}% + }% + }% +}% +\def\onecolumngrid@pop{% + \do@output@MVL{\restorecolumngrid}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsubsection{Two-column page grid} +% +% \begin{macro}{\twocolumngrid} +% \begin{macro}{\open@column@mlt} +% \begin{macro}{\shut@column@mlt} +% \begin{macro}{\end@column@mlt} +% \begin{macro}{\output@column@mlt} +% \begin{macro}{\@addmarginpar@mlt} +% \begin{macro}{\set@footnotewidth@mlt} +% \begin{macro}{\set@footnotewidth@two} +% \begin{macro}{\compose@footnotes@two} +% Here are all the procedures necessary for the standard page grid named ``mlt'': +% the multi-column page grid. With an argument of "2", it is, +% of course, \LaTeX's familiar \cmd\twocolumn\ layout. +% +% We start with the procedure to switch to the two-column page grid. +% \begin{macrocode} +\newcommand\twocolumngrid{\do@columngrid{mlt}{\tw@}}% +% \end{macrocode} +% +% The corresponding command of \LaTeX\ is obsolete. +% \begin{macrocode} +\let\twocolumn\@undefined +% \end{macrocode} +% +% Of course, \cmd\@topnewpage\ is also obsolete. Just do +%\begin{quote} +% \cmd\clearpage\cmd\onecolumngrid<vertical mode material>\cmd\twocolumngrid. +%\end{quote} +% \begin{macrocode} +\let\@topnewpage\@undefined +% \end{macrocode} +% +% If your document class descends from one of \LaTeX's standard classes.dtx-derived +% classes, it will break. You must expunge from it all such commands. +% +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% +% Bug 571 note: it is not enough to have the \cmd\pagesofar, we must also deal with the \cmd\footsofar. +% At this juncture, we should treat the case where the document has an essentially two-column page grid, +% with occasional excursions into the one-column grid. +% If a footnote is set within the latter grid, its set width should be that of the two-column grid. +% +% When a page is shipped out, if we are currently in a one-column grid, we will compose the footnotes onto the page +% in the form of balanced columns. This is only one way to handle footnotes: \classname{multicol} +% appears to set footnotes on the full text width. +% \begin{macrocode} +\def\open@column@mlt#1{% + \ltxgrid@info@sw{\class@info{\string\open@column@mlt\string#1}}{}% +% \end{macrocode} +% At this point, we must \cmd\insert\ the footnotes back into the Main Vertical List. +% \changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +% \begin{macrocode} + \@ifvoid{\footsofar}{}{% + \insert\footins\bgroup\unvbox\footsofar\egroup + }% +% \end{macrocode} +% Record which page grid we are using. Then calculate the set width (\cmd\hsize) and the goal height (\cmd\vsize). +% +% Klootch: we set the \cmd\count\cmd\footins\ to a magic number. This value is valid whether footnotes are being +% set on the column width or the full text width. +% \begin{macrocode} + \gdef\thepagegrid{mlt}% + \global\pagegrid@col#1% + \global\pagegrid@cur\@ne + \global\count\footins\@m + \set@column@hsize\pagegrid@col + \set@colht +}% +% \end{macrocode} +% +% The procedure \cmd\shut@column@mlt\ ends the current column, balances the columns, and +% salts away all in \cmd\pagesofar. Because it is called in a message handler, +% we are assured that marks are handled properly. +% Attention: because this procedure balances columns, all footnotes are +% held aside in \cmd\footsofar\ for placement at the bottom of the page. +% +% Bug note: the last macro executed by this procedure is \cmd\set@colht, +% but had been erroneously \cmd\set@colroom. +% I now believe that the latter should be changed pretty much everywhere to the former. +% +% This instance of \cmd\@makecolumn\ is building material for \cmd\pagesofar, rather than +% for \cmd\shipout. +% \changes{4.1b}{2008/08/04}{Change \cs{@makecol} to \cs{@makecolumn} with argument} +% \changes{4.1b}{2008/08/04}{Change \cs{@combinepage} to \cs{@combinepage} with argument} +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +% \begin{macrocode} +\def\shut@column@mlt{% + \ltxgrid@info@sw{\class@info{\string\shut@column@mlt}}{}% + \@cclv@nontrivial@sw{% + \@makecolumn\false@sw + \@ifnum{\pagegrid@cur<\pagegrid@col}{% + \expandafter\global\expandafter\setbox\csname col@\the\pagegrid@cur\endcsname\box\@outputbox + \global\advance\pagegrid@cur\@ne + }{}% + }{% + \void@cclv + }% + \@ifnum{\pagegrid@cur>\@ne}{% + \csname balance@\the\pagegrid@col\endcsname + \grid@column\@outputbox{}% + \@combinepage\false@sw + \@combinedblfloats + \global\setbox\pagesofar\box\@outputbox + \show@pagesofar@size + }{}% + \set@colht +}% +% \end{macrocode} +% +% The procedure \cmd\float@column@mlt\ takes care of a float page that has been built by \cmd\@tryfcolumn, +% in the multi-column page grid. It is coincidentally identical to what happens in +% \cmd\do@startpage\ when a page needs to be shipped out. +% \changes{4.1b}{2008/08/04}{New procedure \cs{@output@combined@page}} +% \begin{macrocode} +\def\float@column@mlt{% + \@output@combined@page +}% +% \end{macrocode} +% +% The procedure \cmd\end@column@mlt\ is executed at the end of \cmd\clearpage\ processing, +% if we were in a multi-column page grid, once all permissive float pages have been shipped out. +% If no floats are committed and if no columns are yet filled, we have nothing to do. +% Otherwise, we kick out a column and try again. +% +% Note that in our code to kick out a column, we must deal properly with the case where the column +% is trivial: it will have nothing but \cmd\topskip\ glue plus a protection box. We substitute an ordinary +% \cmd\null\ for the protection box. +% +% \begin{macrocode} +\def\end@column@mlt{% + \@ifx@empty\@toplist{% + \@ifx@empty\@botlist{% + \@ifx@empty\@dbltoplist{% + \@ifx@empty\@deferlist{% + \@ifnum{\pagegrid@cur=\@ne}{% + \false@sw + }{% + \true@sw + }% + }{% + \true@sw + }% + }{% + \true@sw + }% + }{% + \true@sw + }% + }{% + \true@sw + }% + % true = kick out a column and try again + {% + \@cclv@nontrivial@sw{% + \unvbox\@cclv\remove@lastbox + }{% + \unvbox\@cclv\remove@lastbox\unskip\null + }% + \protect@penalty\do@newpage@pen + \protect@penalty\do@endpage@pen + }{% + \unvbox\@cclv\remove@lastbox + }% +}% +% \end{macrocode} +% +% The procedure \cmd\output@column@mlt (cf. \cmd\output@column@one) +% is dispatched from the output routine when +% we have completed a column in a multi-column page grid). +% (It replaces the \cmd\@outputdblcol\ of standard \LaTeX.) +% If a complete set of columns is at hand, it ships out the page and +% lays down an interrupt for \cmd\do@startpage@pen, which will commit the +% full-page-width floats to the next page. +% Like \cmd\output@column@mlt, this is followed by +% an output routine message to prepare a new column. +% +% If a page needs to be shipped out, it uses the same mechanism as \cmd\do@startpage. +% \changes{4.1b}{2008/08/04}{New procedure \cs{@output@combined@page}} +% \changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +% \begin{macrocode} +\def\output@column@mlt{% + \@ifnum{\pagegrid@cur<\pagegrid@col}{% + \expandafter\global\expandafter\setbox\csname col@\the\pagegrid@cur\endcsname\box\@outputbox + \global\advance\pagegrid@cur\@ne + }{% + \set@adj@colht\dimen@ + \grid@column\@outputbox{}% + \@output@combined@page + }% +}% +% \end{macrocode} +% The procedure \cmd\output@column@mlt\ obsoletes \LaTeX's \cmd\@outputdblcol +% \begin{macrocode} +\let\@outputdblcol\@undefined +% \end{macrocode} +% +% The following procedure yields a Boolean value; it determines whether a float in the deferred queue +% is appropriate for placement in the column. In the multi-column grid, only those narrower than \cmd\textwidth\ are so. +% \begin{macrocode} +\def\@floatselect@sw@mlt#1{\@if@notdblfloat{#1}}% +% \end{macrocode} +% +% The following procedure determines which side of the page a marginpar will appear. +% It reproduces the behavior of standard \LaTeX. +% \begin{macrocode} +\def\@addmarginpar@mlt{% emits a boolean + \@ifnum{\pagegrid@cur=\@ne}% +}% +% \end{macrocode} +% +% \cmd\set@footnotewidth@one\ sets the width of type within footnotes to span the full text width; +% \cmd\set@footnotewidth@two\ to span a single column of the two-column grid, and +% more generally \cmd\set@footnotewidth@mlt\ for a multi-column page grid. +% \begin{macrocode} +\def\set@footnotewidth@one{% + \hsize\columnwidth + \linewidth\hsize +}% +\def\set@footnotewidth@two{\set@footnotewidth@mlt\tw@}% +\def\set@footnotewidth@mlt#1{% + \hsize\textwidth + \advance\hsize\columnsep + \divide\hsize#1% + \advance\hsize-\columnsep + \linewidth\hsize +}% +% \end{macrocode} +% +% \cmd\compose@footnotes\ is the procedure for arranging the footnotes for +% placement at the bottom of the page or column. +% In the former case, the material will be shipped out; in the latter, we must allow +% the column to possibly be balanced later on. +% +% \cmd\compose@footnotes@one\ is a no-op, because the footnotes require no rearrangement. +% In a scheme where footnotes are set on the full text width, this would be the procedure called. +% +% \cmd\compose@footnotes@two\ implements the case where a two-column document has been interrupted +% with full-page-width text (e.g., the widetext environment or the end of the document), +% and a natural page break appears. +% +% In either case, we assume that argument \verb+#1+ is an \cmd\insert\ register and must be assigned globally, +% so that when it is accessed with \cmd\box\ or \cmd\unvbox, it will be voided globally as well. +% +% To extend this scheme to a three-column page grid \cmd\compose@footnotes@thr@@\ would be created: +% it would balance the saved up footnotes into three columns. +% +% \begin{macrocode} +\def\compose@footnotes@one#1{% + \ltxgrid@foot@info@sw{\class@info{\string\compose@footnotes@one\string#1}\trace@box#1}{}% +}% +\let\compose@footnotes\compose@footnotes@one +\def\compose@footnotes@two#1{% + \ltxgrid@foot@info@sw{\class@info{\string\compose@footnotes@two\string#1}\trace@box#1}{}% + \setbox\z@\box\@tempboxa + \let\recover@column\recover@column@null + \let\marry@baselines\@empty + \balance@two#1\@tempboxa + \global\setbox#1\hbox to\textwidth{\box#1\hfil\box\@tempboxa}% + \ltxgrid@foot@info@sw{\trace@box#1}{}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsubsection{Page grid utility procedures} +% +% \begin{macro}{\pagegrid@cur} +% \begin{macro}{\pagegrid@col} +% \begin{macro}{\pagegrid@init} +% We take over \LaTeX's \cmd\col@number, and \cmd\@leftcolumn, which are obsolete (\cmd\@holdpg\ could also be taken over). +% We create two counters to hold the columns in the page grid and the current column within. +% We also create the first of a set of box registers to hold the committted columns. +% \begin{macrocode} +\let\pagegrid@cur\col@number +\let\col@number\@undefined +\newcount\pagegrid@col +\pagegrid@cur\@ne +\expandafter\let\csname col@\the\pagegrid@cur\endcsname\@leftcolumn +\let\@leftcolumn\@undefined +% \end{macrocode} +% +% The default is for maximum two columns. +% If your class will require more columns, assign that number to \cmd\pagegrid@col\ +% before \envb{document} time. +% \begin{macrocode} +\pagegrid@col\tw@ +% \end{macrocode} +% +% The procedure \cmd\pagegrid@init\ is a loop, exercising \cmd\newbox\ sufficiently to create the +% boxes for holding the columns in the page grid; these have names like \expandafter\cmd\csname col@1\endcsname, etc. +% \begin{macrocode} +\def\pagegrid@init{% + \advance\pagegrid@cur\@ne + \@ifnum{\pagegrid@cur<\pagegrid@col}{% + \csname newbox\expandafter\endcsname\csname col@\the\pagegrid@cur\endcsname + \pagegrid@init + }{% + }% +}% +\appdef\class@documenthook{% + \pagegrid@init +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\grid@column} +% \changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +% The procedure \cmd\grid@column\ knows how to lay up the columns in a multi-column page grid. +% It uses utility procedures \cmd\append@column@\ and \cmd\box@column. +% +% The first argument is the box register to create, usually \cmd\@outputbox, and provides both input and output. +% The second argument a dimension, allowing us to strut down the depth of the box we create. +% +% \begin{macrocode} +\def\grid@column#1#2{% + \ltxgrid@info@sw{\class@info{\string\grid@column\string#1}}{}% + \global\setbox#1\vbox\bgroup + \hb@xt@\textwidth\bgroup + \vrule\@height\z@\@width\z@\@if@empty{#2}{}{\@depth#2}% + \pagegrid@cur\@ne + \@ifnum{\pagegrid@cur<\pagegrid@col}{\loopwhile{\append@column@\pagegrid@cur\pagegrid@col}}{}% + \box@column#1% + \egroup +% \end{macrocode} +% FIXME: page depth! +% \begin{macrocode} + \vskip\z@skip + \egroup +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\append@column@} +% \begin{macro}{\box@column} +% \begin{macro}{\marry@baselines} +% The procedure \cmd\append@column@\ appends columns for \cmd\grid@column, +% \cmd\box@column\ builds the columns for \cmd\append@column@, +% and \cmd\marry@baselines\ pastes vertical things back together. +% \changes{4.0a}{2001/06/18}{Introduce \cs{marry@height} } +% +% Note that \cmd\box@column\ makes an attempt to prevent excessive \cmd\topskip\ +% or \cmd\baselineskip\ glue +% from being applied by \TeX\ when \cmd\@outputbox\ is contributed to the MVL. +% If this is not done, it is possible to get into an infinite loop in the corner case, +% wherein the page grid is changed to one column and the balanced-up columns are +% already sufficient to fill the page. +% +% Note (AO 0920): I have changed the dimension involved with \cmd\box@column\ from +% \cmd\vsize\ to \cmd\textheight, because the former is certainly not the correct value +% to use: it will change if floats have been placed in the last column of the page. +% I believe \cmd\textheight\ is the correct parameter to use here. +% +% A REVTeX4 user, Sergey Strelkov (strelkov@maik.rssi.ru), wants the option +% of ragged-bottom columns. Implementing this feature properly means reboxing the +% columns to their natural height only if \cmd\raggedcolumn@sw\ is true. +% Otherwise, they get reboxed to their common height (\cmd\@colht?). +% +% Note that the default has hereby changed from ragged to flush. +% It's not clear that anyone but Sergey will notice. +% +% The macro \cmd\marry@skip\ addresses (in a limited way) +% the fact that neither the value of \cmd\baselineskip\ nor that of \cmd\topskip\ +% can be relied upon for the purpose of marrying the baselines of two split columns. +% (Because there might have been a local change to their values at the point where +% the output routine got triggered.) +% +% For best results, your document class should call for grid changes only when in basal text +% settings. The \cmd\marry@baselines\ procedure will use the values appropriate to that point +% when attempting to put the columns back together. +% +% In any case, we are not attempting to solve the more general problem of how to marry baselines +% where the leading can change arbitrarily within the galley or where glue could have been trimmed +% at a page top. +% +% \changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +% Procedure \cmd\append@column@\ composes a column onto the horizontal list along with its \cmd\columnseprule. +% Its arguments are: \verb+#1+---\cmd\pagegrid@cur, and \verb+#2+---\cmd\pagegrid@col +% \begin{macrocode} +\def\append@column@#1#2{% + \expandafter\box@column\csname col@\the#1\endcsname + \hfil\vrule\@width\columnseprule\hfil + \advance#1\@ne +% \end{macrocode} +% This procedure is the argument of \cmd\loopwhile, so it must leave a Boolean (e.g., \cmd\true@sw) in \TeX's scanner. +% \begin{macrocode} + \@ifnum{#1<#2}% +}% +% \end{macrocode} +% \changes{4.1n}{2010/01/02}{(AO, 571) calling sequence of \cs{combine@foot@inserts} and \cs{grid@column} to expose box registers; that of \cs{append@column@} its column counters}% +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +% Procdure \cmd\box@column, used by \cmd\append@column@, puts down a box containing the specified column. +% Its height is adjusted down to \cmd\@colht, if needed; likewise, the width is set to \cmd\columnwidth. +% The rag at the bottom is controlled by \cmd\raggedcolumn@skip. +% \begin{macrocode} +\def\box@column#1{% + \ltxgrid@info@sw{\class@info{\string\box@column\string#1}}{}% + \raise\topskip + \hb@xt@\columnwidth\bgroup + \dimen@\ht#1\@ifdim{\dimen@>\@colht}{\dimen@\@colht}{}% + \count@\vbadness\vbadness\@M + \dimen@ii\vfuzz\vfuzz\maxdimen + \ltxgrid@info@sw{\saythe\@colht\saythe\dimen@}{}% + \vtop to\dimen@\bgroup + \hrule\@height\z@ + \unvbox#1% + \raggedcolumn@skip + \egroup + \vfuzz\dimen@ii + \vbadness\count@ + \hss + \egroup +}% +% \end{macrocode} +% The purpose of procedure \cmd\marry@baselines\ is to ensure that the baseline spacing is correct; +% it does this by making adjustments to the previous line, compensating for its depth, and by adding in +% skip glue in an amount that assumes the added material has \cmd\topskip\ glue above. +% \begin{macrocode} +\def\marry@baselines{% + \begingroup + \setbox\z@\lastbox + \@ifvoid{\z@}{% + \endgroup + }{% + \aftergroup\kern + \aftergroup-% + \expandafter\box\expandafter\z@\expandafter\endgroup\the\dp\z@\relax + }% + \vskip\marry@skip\relax +}% +\gdef\marry@skip{\z@skip}% +\def\set@marry@skip{% + \begingroup + \skip@\baselineskip\advance\skip@-\topskip + \@ifdim{\skip@>\z@}{% + \xdef\marry@skip{\the\skip@}% + }{}% + \endgroup +}% +% \end{macrocode} +% \changes{4.1b}{2008/08/04}{Use \cs{document@inithook} instead of \cs{AtBeginDocument}} +% \begin{macrocode} +\appdef\document@inithook{% + \@ifxundefined\raggedcolumn@sw{\@booleanfalse\raggedcolumn@sw}{}% +}% +\def\raggedcolumn@skip{% + \vskip\z@\raggedcolumn@sw{\@plus.0001fil\@minus.0001fil}{}\relax +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@combinepage} +% The procedure \cmd\@combinepage\ prepends the stored page (\cmd\pagesofar) to \cmd\@outputbox\ and +% employs \cmd\@combineinserts\ to lay down the footnotes. +% The next event will usually be shipping out the made-up page, but not always. +% Therefore the argument of \cmd\@combinepage, which must be a Boolean, determines +% if the footnotes are to be combined into this page. +% +% \changes{4.1b}{2008/08/04}{Change \cs{@combinepage} to \cs{@combinepage} with argument} +% \changes{4.1b}{2008/08/04}{(AO, 452) Support length checking: show size of shipped out text.} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% +% QUERY: In the following, if \cmd\box\cmd\footins\ is not void, its contents are lost. Can this ever happen? +% \begin{macrocode} +\def\@combinepage#1{% + \ltxgrid@foot@info@sw{\class@info{\string\@combinepage\string#1}}{}% + \@ifvoid\pagesofar{}{% + \setbox\@outputbox\vbox{% + \unvbox\pagesofar + \marry@baselines + \unvbox\@outputbox + }% + }% + #1{% + \@ifvoid\footsofar{}{% +% \end{macrocode} +% At this point, \cmd\footins\ is empty; all of the footnotes have been combined into \cmd\footsofar. +% \begin{macrocode} + \show@box@size{Combining page footnotes}\footsofar + \setbox\footins\box\footsofar +% \end{macrocode} +% Depending on the page grid, we compose the footnotes for placement on the page. +% \begin{macrocode} + \compose@footnotes + \@combineinserts\@outputbox\footins + }% + }{% +% \end{macrocode} +%QUERY: The following line was removed, probably to fix a bug. When was this done? +% \begin{verbatim} +% \global\setbox\footins\box\footsofar +% \end{verbatim} +% \begin{macrocode} + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@cflt} +% \begin{macro}{\@cflb} +% \changes{4.1b}{2008/08/04}{} +% We modify \LaTeX's \cmd\@cflt\ and \cmd\@cflb\ to remove the unwanted glue with \cmd\unskip. +% \begin{macrocode} +\def \@cflt{% + \let \@elt \@comflelt + \setbox\@tempboxa \vbox{}% + \@toplist + \setbox\@outputbox \vbox{% + \boxmaxdepth \maxdepth + \unvbox\@tempboxa\unskip + \topfigrule\vskip \textfloatsep + \unvbox\@outputbox + }% + \let\@elt\relax + \xdef\@freelist{\@freelist\@toplist}% + \global\let\@toplist\@empty +}% +\def \@cflb {% + \let\@elt\@comflelt + \setbox\@tempboxa \vbox{}% + \@botlist + \setbox\@outputbox \vbox{% + \unvbox\@outputbox + \vskip \textfloatsep\botfigrule + \unvbox\@tempboxa\unskip + }% + \let\@elt\relax + \xdef\@freelist{\@freelist\@botlist}% + \global \let \@botlist\@empty +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@combinedblfloats} +% We modify \LaTeX's \cmd\@combinedblfloats\ to be more appropriate for incremental page building: +% we \cmd\unvbox\ the \cmd\@outputbox. +% \begin{macrocode} +\def\@combinedblfloats{% + \@ifx@empty\@dbltoplist{}{% + \setbox\@tempboxa\vbox{}% + \let\@elt\@comdblflelt\@dbltoplist + \let\@elt\relax\xdef\@freelist{\@freelist\@dbltoplist}% + \global\let\@dbltoplist\@empty + \setbox\@outputbox\vbox{% + %\boxmaxdepth\maxdepth %% probably not needed, CAR + \unvbox\@tempboxa\unskip + \@ifnum{\@dbltopnum>\m@ne}{\dblfigrule}{}%FIXME: how is \@dbltopnum maintained? + \vskip\dbltextfloatsep + \unvbox\@outputbox + }% + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\set@column@hsize}% +% The procedure \cmd\set@column@hsize\ takes care of setting up the horizontal dimensions +% for the current page grid. The present routine will certainly not be adequate for more +% complex page layouts (e.g., with a side column), but works for the common ones. +% \changes{4.0a}{2001/06/18}{Introduce \cs{set@marry@height} } +% \begin{macrocode} +\def\set@column@hsize#1{% + \pagegrid@col#1% + \global\columnwidth\textwidth + \global\advance\columnwidth\columnsep + \global\divide\columnwidth\pagegrid@col + \global\advance\columnwidth-\columnsep + \global\hsize\columnwidth + \global\linewidth\columnwidth + \skip@\baselineskip\advance\skip@-\topskip + \@ifnum{\pagegrid@col>\@ne}{\set@marry@skip}{}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\set@colht}% +% \begin{macro}{\set@colroom}% +% \begin{macro}{\set@vsize}% +% \begin{macro}{\set@adj@colht}% +% The story of \cmd\textheight, \cmd\@colht, \cmd\@colroom, and \cmd\vsize. +% +% \cmd\textheight---height of the text column. Not a running parameter, however, each time a page is +% shipped out, the \cmd\textheight\ could in principle be altered. This must be done before +% +% \cmd\@colht---\cmd\textheight\ minus the height of any full-page-width floats. The latter are committed +% only just after shipping out, and only if we are in a multicolumn page grid. +% Therefore, \cmd\@colht\ should be set after a \cmd\shipout\ (by \cmd\@outputpage) and +% will be adjusted when full-page-width floats are committed to the fresh page by \cmd\do@startpage. +% +% \cmd\@colroom---\cmd\@colht\ (adjusted by \cmd\pagesofar) minus the height of any column-width floats. +% The latter are committed anywhere on the page, at which point \cmd\@colroom\ must be adjusted. +% Therefore, \cmd\@colroom\ should be set (by \cmd\set@colroom) whenever a column is prepared (by ). +%FIXME: committed (by \cmd\output@column@) and +% will be adjusted (by \cmd\@add@float\ or \cmd\do@startcolumn) whenever a float is committted to the column. +% +% \cmd\vsize---\cmd\@colroom. +% Therefore, \cmd\vsize\ should be set (by \cmd\set@vsize) whenever +% the \cmd\@colroom\ is set (by \cmd\set@colroom) or adjusted (by \cmd\@add@float\ or \cmd\do@startcolumn) +%FIXME: or when the \cmd\pagesofar\ box is changed (after invoking \cmd\open@column@). +% +% Question: what if there are committed floats? Footnotes? +% Answer: full-page-width floats are only committed at top, and they are already reckoned with in \cmd\@colht. +% Column-width committed floats are incorporated by \cmd\@makecolumn. +% +% As to footnotes, our scheme is to keep the \cmd\footins\ insert register up to date, and to use the insert mechanism +% to ensure room for footnotes. +% When a change is made to the page grid, the footnotes will need to be propagated back into the MVL. +% +% Note: FIXME: adjusting for \cmd\pagesofar\ is done at not quite the right time. I need to reexamine \cmd\set@colht, +% because \cmd\@dbltoplist\ and \cmd\pagesofar\ really should be on the same footing. +% Perhaps \cmd\@colht\ and \cmd\@colroom\ should both deal with their respective ``lists'' in the same way? +% +% These concerns will be particularly germane if we ever extend this package to deal with full-page-width floats +% placed at the bottom of the page, or committed on the same page as called out. +% +% It occurs to me that we should ditch \cmd\set@colroom\ and only ever execute \cmd\set@colht, +% which sets \cmd\@colroom\ as a side effect. +% If so, we can make \cmd\@colht\ take \cmd\pagesofar\ into account, as it should. Then \cmd\@colht\ will return to its +% original significance as the value that \cmd\@colroom\ is set to after a column is committed. +% +% On the other hand, why not simply forget all this caching and (re-)calculate \cmd\vsize\ as late as possible? +% Particularly, \cmd\@colht\ is an artifact of the old way of doing things, where once it was set, it would never change. +% +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \begin{macrocode} +\def\set@colht{% + \set@adj@textheight\@colht + \global\let\enlarge@colroom\@empty + \set@colroom +}% +\def\set@adj@textheight#1{% + \ltxgrid@info@sw{\class@info{\string\set@adj@textheight\string#1}\saythe\textheight}{}% + #1\textheight + \def\@elt{\adj@page#1}% + \@booleantrue\firsttime@sw\@dbltoplist + \let\@elt\relax + \global#1#1\relax + \ltxgrid@info@sw{\saythe#1}{}% +}% +\def\set@colroom{% + \ltxgrid@info@sw{\class@info{\string\set@colroom}}{}% + \set@adj@colht\@colroom + \@if@empty\enlarge@colroom{}{% + \global\advance\@colroom\enlarge@colroom\relax + \ltxgrid@info@sw{\saythe\@colroom}{}% + }% + \@ifdim{\@colroom>\topskip}{}{% + \ltxgrid@info{Not enough room: \string\@colroom=\the\@colroom; increasing to \the\topskip}% + \@colroom\topskip + }% + \global\@colroom\@colroom +%<ignore> \ltxgrid@info@sw{\class@info{\string\set@colroom\string\vsize=\string\colroom}\saythe\vsize}{}% + \set@vsize +}% +% +\def\set@vsize{% + \global\vsize\@colroom + \ltxgrid@info@sw{\class@info{\string\set@vsize\string\vsize=\string\colroom}\saythe\vsize}{}% +}% +% \end{macrocode} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \begin{macrocode} +\def\set@adj@colht#1{% + #1\@colht + \ltxgrid@info@sw{\class@info{\string\set@adj@colht\string#1-\string\pagesofar}\saythe#1}{}% + \@ifvoid\pagesofar{}{% + \advance#1-\ht\pagesofar\advance#1-\dp\pagesofar + \ltxgrid@info@sw{\class@info{\string\pagesofar}\saythe#1}{}% + }% + \def\@elt{\adj@column#1}% + \@booleantrue\firsttime@sw\@toplist + \@booleantrue\firsttime@sw\@botlist + \let\@elt\relax +}% +\def\adj@column#1#2{% + \advance#1-\ht#2% + \advance#1-\firsttime@sw{\textfloatsep\@booleanfalse\firsttime@sw}{\floatsep}% + \ltxgrid@info@sw{\class@info{\string\adj@column\string#1-\string#2}\saythe#1}{}% +}% +\def\adj@page#1#2{% + \advance#1-\ht#2% + \advance#1-\firsttime@sw{\dbltextfloatsep\@booleanfalse\firsttime@sw}{\dblfloatsep}% + \ltxgrid@info@sw{\class@info{\string\adj@page\string#1-\string#2}\saythe#1}{}% +}% +\def\set@adj@box#1#2{% + \@ifvoid#2{}{% + \advance#1-\ht#2\advance#1-\dp#2% + \@booleantrue\temp@sw + \ltxgrid@foot@info@sw{\class@info{\string\set@adj@box\string#2}\saythe#1}{}% + }% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@outputpage@tail}% +% \changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@tail} tailpatches \cs{@outputpage}}% +% In \cmd\@outputpage@tail, we set \cmd\@colht\ and the float placement parameters +% (this is the one point where it is appropriate to set \cmd\@colht). +% At \cmd\do@startpage\ time, we adjust \cmd\@colht's value to reflect committed +% full-page-width floats. +% +% Note: with a correctly written output routine, a call to \cmd\@outputpage\ will inevitably be +% followed by a call to \cmd\do@startpage, so these procedure calls would be unneeded. +% \begin{macrocode} +\appdef\@outputpage@tail{% + \set@colht % FIXME: needed? + \@floatplacement % FIXME: needed? + \@dblfloatplacement % FIXME: needed? +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{balance@2} +% \changes{4.1b}{2008/08/04}{Procedure \cs{balance@2} defined more transparently}% +% We define procedures for balancing columns in a multicolumn layout. +% For now, we define only one: a procedure for the two-column grid. +% All others will simply \cmd\relax\ out. +% +% The following code defines \verb+\balance@2+ without all the clunky \cmd\csname\ commands +% in the replacement part, +% which appears on the right-hand side of the assignment to \cmd\toks@. +% +% The method is straightforward: balance the two columns of text, and balance the footnotes. +% Later on, \cmd\@combineinserts\ will be called to place the footnotes after the now-balanced columns. +% +% \changes{4.1f}{2009/07/14}{(AO, 519) \cs{footins} content must be preserved and reintegrated} +% It was necessary to deal with the case where \cmd\box\cmd\footsofar\ was not empty +% upon execution of this balancing code. We store it away in \cmd\box\cmd\footins\ and +% add it back in afterwards. +% +% Here is a conundrum: if we switch between single-, two-, and three-column page grids: +% On what measure should the footnotes be set? +% \begin{macrocode} +\begingroup + \catcode`\1=\cat@letter + \catcode`\2=\cat@letter +% \end{macrocode} +% \cmd\toks@\ contains the repacement part for an effective \cmd\def\cs{balance@2}. +% \begin{macrocode} + \toks@{% +% \end{macrocode} +% \cmd\balance@two, by side effect, strips footnotes into \cmd\box\cmd\footins. +% \begin{macrocode} + \setbox\footins\box\footsofar + \balance@two\col@1\@outputbox +% \end{macrocode} +% We ensure that the box assignments are global. +% \begin{macrocode} + \global\setbox\col@1\box\col@1 + \global\setbox\@outputbox\box\@outputbox +% \end{macrocode} +% The following line puts all footnotes into the footnote galley, \cmd\footsofar. +% \begin{macrocode} + \combine@foot@inserts\footsofar\footins + }% + \aftergroup\def\aftergroup\balance@2\expandafter +\endgroup\expandafter{\the\toks@}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\balance@two} +% The procedure \cmd\balance@two\ takes two columns and balances them; in the process it removes +% any footnotes that may be present to a place of safety \cmd\footsofar, +% for later placement at the foot of the shipped-out page. +% The box register \cmd\box\cmd\@ne\ is the aggregate of all columns. +% The box register \cmd\box\cmd \z@\ is the last column. +% The box register \cmd\box\cmd\tw@\ is the first column. +% The \cmd\dimen\ register \cmd\dimen@\ is the trial value to \cmd\vsplit\ to, +% initially half the height of \cmd\box\cmd\@ne. +% The \cmd\dimen\ register \cmd\dimen@i\ is the increment for the next trial; +% its initial value is equal to the initial value of \cmd\dimen@. +% The \cmd\dimen\ register \cmd\dimen@ii\ is the difference of the heights of the two columns. +% +% The procedure uses a binary search for that value of \cmd\dimen@\ which is stable to within .5\cmd\p@\ and which +% makes the last column be shorter than the others. +% +% This procedure can be extended to multiple columns simply by changing it to execute \cmd\vsplit\ multiple +% times (one less than the total number of columns in the page layout) and to calculating \cmd\dimen@ii\ +% to be the difference of the heights of last column and the \cmd\dimen@. +% Upon termination of the search, one would excute the \cmd\vsplit s once again, this time +% using the actual \cmd\col@\ box registers to store the +% balanced columns, thereby clobbering their former contents. +% +% Bug Note: +% as originally written, this macro had a bug, which is well worth avoiding under similar circumstances anywhere. +% So, learn from the mistakes of others, as they say. +% In trying to remove the depth of the boxes created via \cmd\vsplit\ within the \cmd\loopwhile\ control, +% I originally coded +% \cmd\unvbox +% \cmd\z@\ +% \cmd\setbox +% \cmd\z@ +% \cmd\lastbox\ +% \cmd\dimen@ +% \cmd\dp +% \cmd\z@\ +% \cmd\box +% \cmd\z@\ +% \cmd\vskip-% +% \cmd\dimen@. +% The error here is that the (horizontal) shift of the last box in the vertical list will be lost in the process. +% Simply put, \cmd\setbox\cmd\z@\cmd\lastbox\ fails to retain the shift of the box node in the vertical list, +% and when it is put down again via \cmd\box\cmd\z@, it will no longer have the correct shift. +% +% This bug affected things placed in the MVL with \cmd\moveleft, \cmd\moveright, \cmd\parshape, and +% \cmd\hangindent, as well as things shifted by \TeX's primitive mechanisms. +% +% A superior strategy for removing the depth of the last line of the list is more expensive, but safer: +% make a separate copy of the list, measure the depth of the last box as above, but then discard +% the list, retaining only the value of the dimension. +% +% Note that this procedure will not work if the material within is excessively chunky. +% A particular failure mode exists where none of the material is allocated to the last (right) column. +% We detect this case and revert to unbalanced columns. +% +% Another failure mode is where a large chunk occurs at the beginning of the composite box. +% In this case, the left column may fill up even when \cmd\dimen@\ is very small. +% If this configuration leaves the left column longer than the right, then we are done, +% but \cmd\dimen@\ by no means represents the height of either finished box. +% +% Therefore the last step in the process is to rebox the two columns to a common height determined +% independently of the balancing process. +% +% The dimension involved is checked against the current \cmd\@colroom\ to guard against the case where +% excessive material happens to fall in either column. +% \changes{4.1b}{2008/08/04}{Change \cs{set@colroom} to \cs{set@colht}} +% \changes{4.1n}{2009/12/02}{More diagnostics of column balancing} +% \changes{4.1n}{2010/01/02}{(AO, 571) coding convention: use \cs{bgroup}, \cs{egroup} (instead of braces) when a box is being built}% +% \changes{4.1n}{2010/01/02}{(AO, 571) Footnotes, when columns are balanced or when they are composed with their column}% +% \changes{4.1n}{2010/01/02}{(AO, 571) Change \cs{balance@two}'s balancing algorithm to more successfully balance extremely short columns.} +% \begin{macrocode} +\def\balance@two#1#2{% + \ltxgrid@info@sw{\class@info{\string\balance@two\string#1\string#2}}{}% + \outputdebug@sw{\trace@scroll{\showbox#1\showbox#2}}{}% +% \end{macrocode} +% The first step is to recover the footnotes from the bottoms of the two columns (globally, into \cmd\footsofar) +% and to combine the text into \cmd\box\cmd\@ne, but without voiding either of the argument boxes. +% \begin{macrocode} + \setbox\thr@@\copy\footsofar + \setbox\@ne\vbox\bgroup + \@ifvoid{#1}{}{% + \recover@column#1\footsofar\column@recovered\footins@recovered + \@ifvoid{#2}{}{\marry@baselines}% + }% + \@ifvoid{#2}{}{% + \recover@column#2\footsofar\column@recovered\footins@recovered + }% + \egroup + \outputdebug@sw{\trace@scroll{\showbox\@ne}}{}% + \ltxgrid@foot@info@sw{\trace@scroll{\showbox\footsofar}}{}% +% \end{macrocode} +% Hereunder, \cmd\dimen@\ is the split value. We adjust it until the step size is small enough, while the split is acceptable. +% Also, \cmd\dimen@i\ is the step size. Once this value is greater than a half point, we must iterate. +% \begin{macrocode} + \dimen@\ht\@ne\divide\dimen@\tw@ + \dimen@i\dimen@ + \vbadness\@M + \vfuzz\maxdimen + \splittopskip\topskip + \loopwhile{% + \setbox\z@\copy\@ne\setbox\tw@\vsplit\z@ to\dimen@ + \remove@depth\z@\remove@depth\tw@ +% \end{macrocode} +% The following line would provide a diagnostic of the iterations of column balancing, were we to use it. +% \begin{verbatim} +% \outputdebug@sw{\trace@scroll{\showbox\tw@\showbox\z@}}{}% +% \end{verbatim} +% Hereunder, \cmd\dimen@ii\ is used to reckon the difference in height between the left box and the right. +% \begin{macrocode} + \dimen@ii\ht\tw@\advance\dimen@ii-\ht\z@ + \dimen@i=.5\dimen@i + \ltxgrid@info@sw{\saythe\dimen@\saythe\dimen@i\saythe\dimen@ii}{}% +% \end{macrocode} +% If the columns are within a half-point of each other, +% \begin{macrocode} + \@ifdim{\dimen@ii<.5\p@}{% + \@ifdim{\dimen@ii>-.5\p@}% + }{% + \false@sw + }% +% \end{macrocode} +% The above results in a Boolean, which now chooses between the following two brace-delimited clauses. +% If the step size is less than a half-point, then terminate the loop. +% \begin{macrocode} + {% + \true@sw + }{% + \@ifdim{\dimen@i<.5\p@}% + }% +% \end{macrocode} +% The above results in a Boolean, which now chooses between the following two brace-delimited clauses. +% The true-part terminates the loop, otherwise iterate. +% \begin{macrocode} + {% + \false@sw + }% + {% +% \end{macrocode} +% For the next iteration, the candidate split dimension \cmd\dimen@\ will be one step larger +% if the height of the left box is less than that of the right box. +% Otherwise it will be one step smaller. +% \begin{macrocode} + \advance\dimen@\@ifdim{\dimen@ii<\z@}{}{-}\dimen@i + \true@sw + }% + }% +% \end{macrocode} +% The loop has terminated. +% \begin{macrocode} + \ltxgrid@info@sw{\saythe\dimen@\saythe\dimen@i\saythe\dimen@ii}{}% +% \end{macrocode} +% The algorithm has failed to find a satisfactory result if +% the left column is of non-zero height and the right column is of zero height. +% \begin{macrocode} + \@ifdim{\ht\z@=\z@}{% + \@ifdim{\ht\tw@=\z@}% + }{% + \true@sw + }% +% \end{macrocode} +% The \cmd\false@sw\ branch is executed if the algorithm has failed. +% We restore the original boxes. +% \begin{macrocode} + {% + }{% + \ltxgrid@info{Unsatifactorily balanced columns: giving up}% + \setbox\tw@\box#1% + \setbox\z@ \box#2% + \global\setbox\footsofar\box\thr@@ + }% + \setbox\tw@\vbox{\unvbox\tw@\vskip\z@skip}% + \setbox\z@ \vbox{\unvbox\z@ \vskip\z@skip}% + \set@colht + \dimen@\ht\z@\@ifdim{\dimen@<\ht\tw@}{\dimen@\ht\tw@}{}% + \@ifdim{\dimen@>\@colroom}{\dimen@\@colroom}{}% + \ltxgrid@info@sw{\saythe{\ht\z@}\saythe{\ht\tw@}\saythe\@colroom\saythe\dimen@}{}% + \setbox#1\vbox to\dimen@{\unvbox\tw@\unskip\raggedcolumn@skip}% + \setbox#2\vbox to\dimen@{\unvbox\z@ \unskip\raggedcolumn@skip}% + \outputdebug@sw{\trace@scroll{\showbox#1\showbox#2}}{}% +}% +% \end{macrocode} +% Procedure \cmd\remove@depth\ rearranges the given (vertical) box register so that it has zero depth. +% \begin{macrocode} +\def\remove@depth#1{% + \setbox#1\vbox\bgroup + \unvcopy#1% + \setbox\z@\vbox\bgroup + \unvbox#1% + \setbox\z@\lastbox + \aftergroup\kern\aftergroup-\expandafter + \egroup + \the\dp\z@\relax + \egroup +}% +% \end{macrocode} +% \end{macro} +% +% \changes{4.1n}{2010/01/02}{(AO, 571) Abandon \cs{recover@footins} in favor of \cs{recover@column}}% +% Procedure \cmd\recover@column\ is a utility to separate a column box into text and footnotes; +% the former being contributed to the current (vertical) list, the latter appended to the given register, usually \cmd\footsofar. +% +% Argument \verb+#1+ is the input: it should be a \cmd\vbox, and it remains unaltered. +% Argument \verb+#2+ is the box into which to (globally) add the footnotes, usually \cmd\footsofar. +% Arguments \verb+#3+ and \verb+#4+ are scratch box registers to use in this calculation. +% As a side effect, \verb+#3+ will be unboxed into whatever vertical mode we are in at the moment (should be a \cmd\vbox). +% \begin{macrocode} +\def\recover@column#1#2#3#4{% + \ltxgrid@info@sw{\class@info{\string\recover@column\string#1\string#2\string#3\string#4}}{}% + \setbox#4\vbox{\unvcopy#1}% + \ltxgrid@foot@info@sw{\trace@scroll{\showbox#4}}{}% + \dimen@\ht#4% + \ltxgrid@foot@info@sw{\saythe\dimen@}{}% + \setbox#4\vbox\bgroup + \unvbox#4\unskip +% \end{macrocode} +% We now strip the footnotes from the bottom of this box, adding them to \cmd\footsofar. +% The method relies on a signal, consisting of a complementary pair of kerns, placed at the bottom of the box by \cmd\@combineinserts. +% \begin{macrocode} + \dimen@i\lastkern\unkern\advance\dimen@i\lastkern + \@ifdim{\dimen@i=\z@}{% + \dimen@i\lastkern\unkern + \ltxgrid@foot@info@sw{\saythe\dimen@i}{}% + \aftergroup\dimen@i + \expandafter\egroup\the\dimen@i\relax + }{% + \egroup + }% +% \end{macrocode} +% Split the column into \verb+#3+ and the footnote into \verb+#4+. +% Append the footnote to \verb+#2+. +% \begin{macrocode} + \@ifdim{\dimen@i<\z@}{% + \advance\dimen@\dimen@i + \ltxgrid@foot@info@sw{\saythe\dimen@i\saythe\dimen@}{}% + \splittopskip\z@skip + \global\setbox#3\vsplit#4 to\dimen@ + \global\setbox#4\vbox{\unvbox#4}% + \ltxgrid@foot@info@sw{\trace@scroll{\showbox#1\showbox#2\showbox#3\showbox#4}}{}% + \global\setbox#2\vbox\bgroup\unvbox#2\vskip\z@skip\unvbox#4\egroup + }{% +% \end{macrocode} +% What if \cmd\dimen@i\ is zero? +% In that case, \cmd\setbox\#3\cmd\box\#4, and do not touch \cmd\box\#2. +% \begin{macrocode} + \setbox#3\box#4% + \ltxgrid@foot@info@sw{\trace@scroll{\showbox#1\showbox#2\showbox#3\showbox#4}}{}% + }% + \unvbox#3% + \loopwhile{\dimen@\lastskip\@ifdim{\dimen@>\z@}{\unskip\true@sw}{\false@sw}}% +}% +\def\recover@column@null#1#2#3#4{% + \unvcopy#1% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@begindocumenthook} +% Initialization: +% we initialize to the page grid named ``one''. +% If the class decides to initially set type in a different grid, it +% should execute these same commands, but changing the first to the appropriate procedure. +% +% Note that the point where this sequence is executed would be an excellent place to arrange for +% floats to be committed to the first page of a document. +% That is, we execute \cmd\do@startpage, which triggers \cmd\do@startcolumn. +% +% FIXME: it should be the job of the page grid to determine the procedure to execute at +% the start of the job. Make this a hook. +% \begin{macrocode} +\rvtx@ifformat@geq{2020/10/01}% + {% + \AddToHook{begindocument}{% + \open@column@one\@ne + \set@colht + \@floatplacement + \@dblfloatplacement + }% + }{% + \prepdef\@begindocumenthook{% + \open@column@one\@ne + \set@colht + \@floatplacement + \@dblfloatplacement + }% + } +% \end{macrocode} +% \end{macro} +% +% Comment: our technique of balancing columns is severely limited, because it cannot properly work +% with \env{longtable}, which places material at the bottom and top of the column break. +% +% The proper way to handle a grid change in the middle of the page is to accumulate all the material for +% an entire article (or chapter) and then assemble finished pages therefrom. This approach is fundamentally +% superior for complex layouts: it corresponds to real-world workflows. +% Such a scheme is an excellent subject for another \LaTeX\ package. +% +% +% \subsection{Patches for the longtable package}% +% +% \LaTeX's ``required'' package \classname{longtable} (written by David P. Carlilsle), +% which is part of /latex/required/tools, is incmpatible with both +% \LaTeX's ``required'' package \classname{multicol} and with +% \LaTeX's native \cmd\twocolumn\ capability. There is no essential reason +% for this incompatability, aside from implementation details, and the +% \classname{ltxgrid} package gives us the ability to lift them. +% +% Only four of \classname{longtable}'s procedures require rewriting: +% \cmd\longtable, +% \cmd\endlongtable, +% \cmd\LT@start, and +% \cmd\LT@end@hd@ft. +% The procedure \cmd\switch@longtable\ checks against their expected meanings +% and, if all is as expected, applies the patches. +% In the process, we simplify things considerably and also make them more +% secure. +% +% Why does \classname{longtable} need to access the output routine, anyway? +% What it comes down to, is what happens when a pagebreak falls within a +% long table. If this happens, we would like to append a row at the bottom of +% the broken table and add a row at the top of the next page. +% +% These things can be accomodated easily by the \classname{ltxgrid} output +% routine hooks. +% +% \begin{macro}{\longtable} +% \begin{macrocode} +\def\longtable@longtable{% + \par + \ifx\multicols\@undefined\else\ifnum\col@number>\@ne\@twocolumntrue\fi\fi + \if@twocolumn\LT@err{longtable not in 1-column mode}\@ehc\fi + \begingroup + \@ifnextchar[\LT@array{\LT@array[x]}% +}% +\def\longtable@new{% + \par + \@ifnextchar[\LT@array{\LT@array[x]}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\endlongtable} +% \begin{macrocode} +\def\endlongtable@longtable{% + \crcr + \noalign{% + \let\LT@entry\LT@entry@chop + \xdef\LT@save@row{\LT@save@row}}% + \LT@echunk + \LT@start + \unvbox\z@ + \LT@get@widths + \if@filesw + {\let\LT@entry\LT@entry@write\immediate\write\@auxout{% + \gdef\expandafter\noexpand + \csname LT@\romannumeral\c@LT@tables\endcsname + {\LT@save@row}}}% + \fi + \ifx\LT@save@row\LT@@save@row + \else + \LT@warn{Column \@width s have changed\MessageBreak + in table \thetable}% + \LT@final@warn + \fi + \endgraf\penalty -\LT@end@pen + \endgroup + \global\@mparbottom\z@ + \pagegoal\vsize + \endgraf\penalty\z@\addvspace\LTpost + \ifvoid\footins\else\insert\footins{}\fi +}% +% \end{macrocode} +% \changes{4.1a}{2008/06/29}{Repair error in \cs{endlongtable@new} involving \cs{@ifx}: argument not delimited.} +% \begin{macrocode} +\def\endlongtable@new{% + \crcr + \noalign{% + \let\LT@entry\LT@entry@chop + \xdef\LT@save@row{\LT@save@row}% + }% + \LT@echunk + \LT@start + \unvbox\z@ + \LT@get@widths + \@if@sw\if@filesw\fi{% + {% + \let\LT@entry\LT@entry@write + \immediate\write\@auxout{% + \gdef\expandafter\noexpand\csname LT@\romannumeral\c@LT@tables\endcsname + {\LT@save@row}% + }% + }% + }{}% + \@ifx{\LT@save@row\LT@@save@row}{}{% + \LT@warn{% + Column \@width s have changed\MessageBreak in table \thetable + }\LT@final@warn + }% + \endgraf + \nobreak + \box\@ifvoid\LT@lastfoot{\LT@foot}{\LT@lastfoot}% + \global\@mparbottom\z@ + \endgraf + \LT@post +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\LT@start} +% \begin{macrocode} +\def\LT@start@longtable{% + \let\LT@start\endgraf + \endgraf\penalty\z@\vskip\LTpre + \dimen@\pagetotal + \advance\dimen@ \ht\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi + \advance\dimen@ \dp\ifvoid\LT@firsthead\LT@head\else\LT@firsthead\fi + \advance\dimen@ \ht\LT@foot + \dimen@ii\vfuzz + \vfuzz\maxdimen + \setbox\tw@\copy\z@ + \setbox\tw@\vsplit\tw@ to \ht\@arstrutbox + \setbox\tw@\vbox{\unvbox\tw@}% + \vfuzz\dimen@ii + \advance\dimen@ \ht + \ifdim\ht\@arstrutbox>\ht\tw@\@arstrutbox\else\tw@\fi + \advance\dimen@\dp + \ifdim\dp\@arstrutbox>\dp\tw@\@arstrutbox\else\tw@\fi + \advance\dimen@ -\pagegoal + \ifdim \dimen@>\z@\vfil\break\fi + \global\@colroom\@colht + \ifvoid\LT@foot\else + \advance\vsize-\ht\LT@foot + \global\advance\@colroom-\ht\LT@foot + \dimen@\pagegoal\advance\dimen@-\ht\LT@foot\pagegoal\dimen@ + \maxdepth\z@ + \fi + \ifvoid\LT@firsthead\copy\LT@head\else\box\LT@firsthead\fi +% \end{macrocode} +% At some point before version 4.11, the \cmd\nobreak\ was added. +% \begin{macrocode} +\nobreak +% \end{macrocode} +% +% \begin{macrocode} + \output{\LT@output}% +}% +\def\LT@start@new{% + \let\LT@start\endgraf + \endgraf + \markthr@@{}% + \LT@pre + \@ifvoid\LT@firsthead{\LT@top}{\box\LT@firsthead\nobreak}% + \mark@envir{longtable}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\LT@end} +% \begin{macrocode} +\def\LT@end@hd@ft@longtable#1{% + \LT@echunk + \ifx\LT@start\endgraf + \LT@err{Longtable head or foot not at start of table}{Increase LTchunksize}% + \fi + \setbox#1\box\z@ + \LT@get@widths\LT@bchunk +}% +\def\LT@end@hd@ft@new#1{% + \LT@echunk + \@ifx{\LT@start\endgraf}{% + \LT@err{Longtable head or foot not at start of table}{Increase LTchunksize}% + }% + \global\setbox#1\box\z@ + \LT@get@widths + \LT@bchunk +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\LT@array} +% +% +% \begin{macrocode} +\def\LT@array@longtable[#1]#2{% + \refstepcounter{table}\stepcounter{LT@tables}% + \if l#1% + \LTleft\z@ \LTright\fill + \else\if r#1% + \LTleft\fill \LTright\z@ + \else\if c#1% + \LTleft\fill \LTright\fill + \fi\fi\fi + \let\LT@mcol\multicolumn + \let\LT@@tabarray\@tabarray + \let\LT@@hl\hline + \def\@tabarray{% + \let\hline\LT@@hl + \LT@@tabarray}% + \let\\\LT@tabularcr\let\tabularnewline\\% + \def\newpage{\noalign{\break}}% + \def\pagebreak{\noalign{\ifnum`}=0\fi\@testopt{\LT@no@pgbk-}4}% + \def\nopagebreak{\noalign{\ifnum`}=0\fi\@testopt\LT@no@pgbk4}% + \let\hline\LT@hline \let\kill\LT@kill\let\caption\LT@caption + \@tempdima\ht\strutbox + \let\@endpbox\LT@endpbox + \ifx\extrarowheight\@undefined + \let\@acol\@tabacol + \let\@classz\@tabclassz \let\@classiv\@tabclassiv + \def\@startpbox{\vtop\LT@startpbox}% + \let\@@startpbox\@startpbox + \let\@@endpbox\@endpbox + \let\LT@LL@FM@cr\@tabularcr + \else + \advance\@tempdima\extrarowheight + \col@sep\tabcolsep + \let\@startpbox\LT@startpbox\let\LT@LL@FM@cr\@arraycr + \fi + \setbox\@arstrutbox\hbox{\vrule + \@height \arraystretch \@tempdima + \@depth \arraystretch \dp \strutbox + \@width \z@}% + \let\@sharp##\let\protect\relax + \begingroup + \@mkpream{#2}% + \xdef\LT@bchunk{% + \global\advance\c@LT@chunks\@ne + \global\LT@rows\z@\setbox\z@\vbox\bgroup + \LT@setprevdepth +% \end{macrocode} +% At some point before version 4.11, the \cmd\noexpand\ was added. +% We need not change our own version, because we did it right, back in 1998 (using \cmd\appdef). +% \begin{macrocode} + \tabskip\LTleft \noexpand\halign to\hsize\bgroup + \tabskip\z@ \@arstrut \@preamble \tabskip\LTright \cr}% + \endgroup + \expandafter\LT@nofcols\LT@bchunk&\LT@nofcols + \LT@make@row + \m@th\let\par\@empty + \everycr{}\lineskip\z@\baselineskip\z@ + \LT@bchunk}% +\def\LT@LR@l{\LTleft\z@ \LTright\fill}% +\def\LT@LR@r{\LTleft\fill \LTright\z@ }% +\def\LT@LR@c{\LTleft\fill \LTright\fill}% +\def\LT@array@new[#1]#2{% + \refstepcounter{table}\stepcounter{LT@tables}% + \table@hook + \LTleft\fill \LTright\fill + \csname LT@LR@#1\endcsname + \let\LT@mcol\multicolumn + \let\LT@@hl\hline + \prepdef\@tabarray{\let\hline\LT@@hl}% + \let\\\LT@tabularcr + \let\tabularnewline\\% + \def\newpage{\noalign{\break}}% + \def\pagebreak{\noalign{\ifnum`}=0\fi\@testopt{\LT@no@pgbk-}4}% + \def\nopagebreak{\noalign{\ifnum`}=0\fi\@testopt\LT@no@pgbk4}% + \let\hline\LT@hline + \let\kill\LT@kill + \let\caption\LT@caption + \@tempdima\ht\strutbox + \let\@endpbox\LT@endpbox + \@ifxundefined\extrarowheight{% + \let\@acol\@tabacol + \let\@classz\@tabclassz + \let\@classiv\@tabclassiv + \def\@startpbox{\vtop\LT@startpbox}% + \let\@@startpbox\@startpbox + \let\@@endpbox\@endpbox +% \end{macrocode} +% Because \classname{ltxutil} patches \LaTeX's \cmd\@tabularcr and \cmd\@xtabularcr, +% we must restore these procedures in the scope of \env{longtable}. +% Ironically, the patches in \classname{ltxutil} were for the purpose of extending +% the \env{tabular} environment to prevent pagebreaks with the *-form of \cmd\\, +% just the same as is being done here. But the two mechanisms conflict. +% \changes{4.1a}{2008/06/29}{Change \cs{LT@array@new}: restore \cs{@tabularcr} and \cs{@xtabularcr}} +% \begin{macrocode} + \let\LT@LL@FM@cr\@tabularcr@LaTeX + \let\@xtabularcr\@xtabularcr@LaTeX + }{% + \advance\@tempdima\extrarowheight + \col@sep\tabcolsep + \let\@startpbox\LT@startpbox +% \end{macrocode} +% \changes{4.1a}{2008/06/29}{Change \cs{LT@array@new}: set \cs{LT@LL@FM@cr} to \cs{@arraycr@array} instead of \cs{@arraycr}} +% \begin{macrocode} + \let\LT@LL@FM@cr\@arraycr@array + }% +% + \let\@acoll\@tabacoll + \let\@acolr\@tabacolr + \let\@acol\@tabacol +% + \setbox\@arstrutbox\hbox{% + \vrule + \@height \arraystretch \@tempdima + \@depth \arraystretch \dp \strutbox + \@width \z@ + }% + \let\@sharp##% + \let\protect\relax + \begingroup + \@mkpream{#2}% + \@mkpream@relax + \edef\@preamble{\@preamble}% + \prepdef\@preamble{% + \global\advance\c@LT@chunks\@ne + \global\LT@rows\z@ + \setbox\z@\vbox\bgroup + \LT@setprevdepth + \tabskip\LTleft + \halign to\hsize\bgroup + \tabskip\z@ + \@arstrut + }% + \appdef\@preamble{% + \tabskip\LTright + \cr + }% + \global\let\LT@bchunk\@preamble + \endgroup + \expandafter\LT@nofcols\LT@bchunk&\LT@nofcols + \LT@make@row + \m@th + \let\par\@empty + \everycr{}% + \lineskip\z@ + \baselineskip\z@ + \LT@bchunk +}% +\appdef\table@hook{}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\switch@longtable} +% +% Here is the switch from standard \classname{longtable} to the new, \classname{ltxgrid}-compatible values. +% +% At this point, we extend \env{longtable} with a \env{longtable*} form, which signifies that we want to +% use the full page width for setting the table. +% You can think this way: \env{longtable*} is to \env{longtable} as \env{table*} is to \env{table}. +% +% \begin{macrocode} +\def\switch@longtable{% + \@ifpackageloaded{longtable}{% + \@ifx{\longtable\longtable@longtable}{% + \@ifx{\endlongtable\endlongtable@longtable}{% + \@ifx{\LT@start\LT@start@longtable}{% + \@ifx{\LT@end@hd@ft\LT@end@hd@ft@longtable}{% + \@ifx{\LT@array\LT@array@longtable}{% + \true@sw + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + {% + \class@info{Patching longtable package}% + }{% + \class@info{Patching unrecognized longtable package. (Proceeding with fingers crossed)}% + }% + \let\longtable\longtable@new + \let\endlongtable\endlongtable@new + \let\LT@start\LT@start@new + \let\LT@end@hd@ft\LT@end@hd@ft@new + \let\LT@array\LT@array@new + \newenvironment{longtable*}{% + \onecolumngrid@push + \longtable + }{% + \endlongtable + \onecolumngrid@pop + }% +% \end{macrocode} +% Removed obsolete code. +% \begin{macrocode} + }{}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\LT@pre} +% \begin{macro}{\LT@bot} +% \begin{macro}{\LT@top} +% \begin{macro}{\LT@post} +% \begin{macro}{\LT@adj} +% Note that at the end of the longtable environment, we reestablish the \cmd\mark@envir\ of the +% containing environment. We have left \cmd\curr@envir\ alone, so this will work. +% \begin{macrocode} +\def\LT@pre{\penalty\z@\vskip\LTpre}% +\def\LT@bot{\nobreak\copy\LT@foot\vfil}% +\def\LT@top{\copy\LT@head\nobreak}% +\def\LT@post{\penalty\z@\addvspace\LTpost\mark@envir{\curr@envir}}% +\def\LT@adj{% + \setbox\z@\vbox{\null}\dimen@-\ht\z@ + \setbox\z@\vbox{\unvbox\z@\LT@bot}\advance\dimen@\ht\z@ + \global\advance\vsize-\dimen@ +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{output@init} +% \begin{macro}{output@prep} +% \begin{macro}{output@post} +% \begin{macrocode} +\def\output@init@longtable{\LT@adj}% +\def\output@prep@longtable{\setbox\@cclv\vbox{\unvbox\@cclv\LT@bot}}% +\def\output@post@longtable{\LT@top}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsection{Patches for index processing}% +% +% Another feature that uses the output routine hooks occurs within +% an index, where one wishes to apply a ``continue head'' when a +% column breaks within a primary index entry. +% Some book designs call for the continue head to only be applied +% at a turnpage break. +% +% In any case, it is easy enough for \cmd\output@post@theindex\ +% to do this in conjunction with component marks. +% Only the bare outlines are shown here. +% +% \begin{macro}{\output@init} +% \begin{macro}{\output@prep} +% \begin{macro}{\output@post} +% \begin{macrocode} +\let\output@init@theindex\@empty +\let\output@prep@theindex\@empty +\def\output@post@theindex{% + \@ifodd\c@page{}{% + \@ifnum{\pagegrid@cur=\@ne}{% +% \end{macrocode} +% We have the leftmost column of a verso page: +% Insert the current top-level continued head. +% \begin{macrocode} + }% + }% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \subsection{Checking the auxiliary file}% +% +% We relegate the checking of the auxiliary file to the output routine. +% This task must wait until the last page is shipped out, because otherwise +% the stream might get closed before the last page is shipped out. +% Obviously, we must use \cmd\do@output@MVL\ for the job. +% +% \begin{macro}{\check@aux} +% \begin{macrocode} +\def\check@aux{\do@output@MVL{\do@check@aux}}% +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Dealing with stuck floats and stalled float dequeueing}% +% +% \LaTeX's float placement mechanism is fundamentally flawed, as evidenced by +% its warning message ``too many unprocessed floats'', which users understandably find frustrating. +% The \classname{ltxgrid} package provides tools for ameliorating the situation somewhat. +% +% Two cases require detection and rectification: +% \begin{enumerate} +% \item +% A float is ``stuck'' in the \cmd\@deferlist: for whatever reason, the float fails to be committed, +% even at the start of a fresh page. +% Once this condition prevails, following floats can never be committed, subsequently all of \LaTeX's +% float registers are used up. +% +% If this condition is detected, we reconsider float dequeueing under permissive (\cmd\clearpage-style) processing. +% +% \item +% The \cmd\@freelist\ is exhausted: +% a large concentration of floats, say, uses up all of \LaTeX's float registers all at once. +% This condition commonly occurs when the user collects floats at the end of the document, for some reason. +% +% When a float is encountered, \LaTeX\ uses a float register (allocated from a pool of free registers) to contain it until it can be placed. +% However, no further action is taken until the pagebuilder is visited, so floats can accumulate. +% Also, even after the pagebuilder is visited, deferred floats can accumulate, and these are not committed +% until a column (or page) of text is completed. +% +% Once the last free float register is used, action should be taken that will commit some of the deferred floats, +% even if this might require ending the page right where we are (resulting in a short page). +% +% Perhaps, committed floats should be stored using some mechanism other than a list, as is currently done. +% A feasible alternative storage method would be to use a \cmd\box\ register in place of +% \cmd\@toplist, +% \cmd\@botlist, and +% \cmd\@dbltoplist. +% This is probably just fine, since such committed floats are not reconsidered (I think). +% +% \end{enumerate} +% +% The emergency processing implemented here immediately ends the current page and begins to output float pages under (\cmd\clearpage-style) rules. +% It proceeds until all deferred floats have been flushed. +% +% Users should expect non-optimal page makeup under these circumstances. +% +% Note that there is a weakness in our approach that we have not attempted to repair: if floats are being +% added as part of a paragraph, we will not be able to take these remedial steps until the paragraph ends. +% This means that the approach implemented here cannot fix all \LaTeX\ documents. Users can still construct +% documents that exhaust \LaTeX's pool of float registers! +% +% \begin{macro}{\check@deferlist@stuck} +% \begin{macro}{\@outputpage@tail} +% \changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@tail} tailpatches \cs{@outputpage}}% +% We detect the case where, at the start of a fresh page, there are deferred floats, but none are +% committed. We memorize the \cmd\@deferlist\ at \cmd\shipout\ time, then examine it at the point where +% our efforts to commit floats to the new page are complete. +% If it has not changed, the first float must be stuck, and we +% attempt to fix things via \cmd\force@deferlist@stuck. +% +% This simple approach is comp[letely effective in for typical documents. +% +% Note that we try to avoid an infinite loop by examining the value of \cmd\clearpage@sw: +% if we come here with that boolean true, we are in a loop. +% \begin{macrocode} +\def\check@deferlist@stuck#1{% + \@ifx{\@deferlist@postshipout\@empty}{}{% + \@ifx{\@deferlist@postshipout\@deferlist}{% + \@fltstk + \clearpage@sw{% + \ltxgrid@warn{Deferred float stuck during \string\clearpage\space processing}% + }{% + \force@deferlist@stuck#1% + }% + }{% +% \end{macrocode} +% We have successfully committed float(s) +% \begin{macrocode} + }% + \global\let\@deferlist@postshipout\@empty + }% +}% +\def\@fltstk{% + \@latex@warning{A float is stuck (cannot be placed without \string\clearpage)}% +}% +\appdef\@outputpage@tail{% + \global\let\@deferlist@postshipout\@deferlist +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@next} +% \begin{macro}{\@xnext} +% We rewrite the \LaTeX\ kernel macros that dequeue float registers from, e.g., \cmd\@deferlist, +% providing a test for the condition where the pool of free registers is about to underflow. +% +% In this case, we attempt to fix things via \cmd\force@deferlist@empty. +% \begin{macrocode} +\def\@next#1#2{% + \@ifx{#2\@empty}{\false@sw}{% + \expandafter\@xnext#2\@@#1#2% + \true@sw + }% +}% +\def\@xnext\@elt#1#2\@@#3#4{% + \def#3{#1}% + \gdef#4{#2}% + \def\@tempa{#4}\def\@tempb{\@freelist}% + \@ifx{\@tempa\@tempb}{% + \@ifx{#4\@empty}{% + \force@deferlist@empty%{Float register pool exhausted}% + }{}% + }{}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\force@deferlist@stuck} +% \begin{macro}{\force@deferlist@empty} +% \begin{macro}{\force@deferlist@sw} +% \begin{macro}{\do@forcecolumn@pen} +% \begin{macro}{\do@forcecolumn} +% The procedure \cmd\force@deferlist@empty\ is an attempt to rectify a situation where \LaTeX's float placement mechanism +% may fail (``too many unprocessed floats''). +% +% We put down interrupts that call for the float placement to be redone, but under permissive conditions, +% just the same as if \cmd\clearpage\ had been invoked. +% +% Note that the attempt to rectify the error is contingent on the setting of \cmd\force@deferlist@sw, +% default false. A document class using this package that wishes to enable this error recovery mechanism should +% set this boolean to true. +% +% The interrupt \cmd\do@forcecolumn@pen, which invokes the procedure \cmd\do@forcecolumn, +% does the same as \cmd\do@startcolumn, except under permissive conditions: +% we are trying to empty out the float registers completely. +% +% In order to properly with the case where there is material in \cmd\box\cmd\@cclv, +% \cmd\@toplist, \cmd\@botlist, \cmd\@dbltoplist, etc, +% we do what amounts to \cmd\newpage\ to get things rolling. +% +% In \cmd\force@deferlist@stuck, we take advantage of already being in the output routine: +% simply reinvoke \cmd\do@startcolumn\ under permissive conditions. +% +% \begin{macrocode} +\def\force@deferlist@stuck#1{% + \force@deferlist@sw{% + \@booleantrue\clearpage@sw + \@booleantrue\forcefloats@sw + #1% + }{% + }% +}% +\def\force@deferlist@empty{% + \force@deferlist@sw{% + \penalty-\pagebreak@pen + \protect@penalty\do@forcecolumn@pen + }{% + }% +}% +\@booleanfalse\force@deferlist@sw +\mathchardef\do@forcecolumn@pen=10009 +\@namedef{output@-\the\do@forcecolumn@pen}{\do@forcecolumn}% +\def\do@forcecolumn{% + \@booleantrue\clearpage@sw + \@booleantrue\forcefloats@sw +% \end{macrocode} +% \begin{verbatim} +%\unvbox\@cclv +%\vfil +%\penalty-\pagebreak@pen +% \end{verbatim} +% \begin{macrocode} + \do@startcolumn +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% A more thorough revision of \LaTeX's float placement mechanism would involve substituting a single \cmd\box\ +% register for the \cmd\@deferlist. This way, \LaTeX's ability to have latent floats would be limited by +% box memory alone. +% +% Because only the \cmd\box\ and \cmd\count\ components of the float box register are actually used by \LaTeX, +% our scheme can be accomplished if we can find a way to encode the information held in the \cmd\count\ component. +% +% A first-in, first-out mechanism exists, wherein a box-penalty pair is dequeued by \cmd\lastbox\cmd\lastpenalty\cmd\unpenalty\ and enqueued +% by \cmd\setbox\cmd\foo=\cmd\hbox\cmd\bgroup\cmd\penalty\cmd\floatpenalty\cmd\box\cmd\floatbox\cmd\unhbox\cmd\foo\cmd\egroup. +% +% Note that this scheme is made possible by our change to \LaTeX's float placement mechanism, +% wherein we consolidated the two \cmd\@deferlist s into one. +% +% \section{Support for legacy \LaTeX\ commands} +% +% We provide support for the \cmd\enlargethispage\ command. +% +% Note: using a command of this sort does not automatically enlarge both pages of a spread, which would be the convention in page composition. +% +% Timing Note: In a multicolumn page grid, the user should issue the \cmd\enlargethispage\ command +% while the first column of the page is being typeset. +% We provide a helpful message if the timing is wrong. +% +% This code can serve as a model for introducing commands that need to execute within the safety of the output routine. +% We ensure that the arguments are fully expanded, then execute \cmd\do@output@MVL\ to cause an output procedure, +% \cmd\@@enlargethispage, to execute. When it does execute, the MVL will be exposed. +% +% The \cmd\@@enlargethispage\ procedure simply adjusts the vertical dimensions of the page. +% The adjustment will persist until the column is committed, at which point the page dimension +% will revert to its standard value. +% \begin{macrocode} +\def\enlargethispage{% + \@ifstar{% + \@enlargethispage{}% + }{% + \@enlargethispage{}% + }% +}% +\def\@enlargethispage#1#2{% + \begingroup + \dimen@#2\relax + \edef\@tempa{#1}% + \edef\@tempa{\noexpand\@@enlargethispage{\@tempa}{\the\dimen@}}% + \expandafter\do@output@MVL\expandafter{\@tempa}% + \endgroup +}% +\def\@@enlargethispage#1#2{% + \def\@tempa{one}% + \@ifx{\thepagegrid\@tempa}{% + \true@sw + }{% + \def\@tempa{mlt}% + \@ifx{\thepagegrid\@tempa}{% + \@ifnum{\pagegrid@cur=\@ne}{% +% \end{macrocode} +% OK to adjust this page +% \begin{macrocode} + \gdef\enlarge@colroom{#2}% + \true@sw + }{% +% \end{macrocode} +% Can only adjust this column; give up +% \begin{macrocode} + \ltxgrid@warn{Too late to enlarge this page; move the command to the first column.}% + \false@sw + }% + }{% +% \end{macrocode} +% Unknown page grid +% \begin{macrocode} + \ltxgrid@warn{Unable to enlarge a page of this kind.}% + \false@sw + }% + }% + {% + \class@info{Enlarging page \thepage\space by #2}% + \global\advance\@colroom#2\relax + \set@vsize + }{% +% \end{macrocode} +% Could not adjust this page +% \begin{macrocode} + }% +}% +\let\enlarge@colroom\@empty +% \end{macrocode} +% The \cmd\@kludgeins\ insert register is now unneeded. +% Ensure that packages using this mechanism break (preferrable to subtle bugs). +% \begin{macrocode} +\let\@kludgeins\@undefined +% \end{macrocode} +% +% \subsubsection{Building the page for shipout} +% +% \begin{macro}{\@outputpage@head} +% We set \cmd\@outputpage@head\ to make the \cmd\@outputbox\ be of fixed height. +% \changes{4.1b}{2008/08/04}{Procedure \cs{@outputpage@head} headpatches \cs{@outputpage}}% +% \begin{macrocode} +\@booleantrue\textheight@sw +\prepdef\@outputpage@head{% + \textheight@sw{% + \count@\vbadness\vbadness\@M + \dimen@\vfuzz\vfuzz\maxdimen + \setbox\@outputbox\vbox to\textheight{\unvbox\@outputbox}% + \vfuzz\dimen@ + \vbadness\count@ + }{}% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@outputpage@head} +% For compatibility with David Carlisle's \classname{lscape} package, we need to allow the +% \cmd\LS@rot\ procedure to mung \cmd\@outputbox. +% +% Implementation note: the \classname{lscape} package effectively tailpatches two \LaTeX\ internals to accomplish its purpose, +% an approach that is not robust. It is more robust to headpatch \cmd\@outputpage, which is what we do here. +% \changes{4.1o}{2010/02/02}{(AO, 576) Allow \classname{lscape} to act on \cs{@outputbox} at the right time}% +% \begin{macrocode} +\appdef\@outputpage@head{% + \@ifx{\LS@rot\@undefined}{}{\LS@rot}% +}% +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Warning message} +% +% \begin{macro}{\ltxgrid@info} +% \begin{macro}{\ltxgrid@warn} +% Something has happened that the user might be interested in. +% Print a message to the log, but only if the user selected the verbose option. +% \begin{macrocode} +\def\ltxgrid@info{% + \ltxgrid@info@sw{\class@info}{\@gobble}% +}% +\@booleanfalse\ltxgrid@info@sw +\def\ltxgrid@warn{% + \ltxgrid@warn@sw{\class@warn}{\@gobble}% +}% +\@booleantrue\ltxgrid@warn@sw +\@booleanfalse\ltxgrid@foot@info@sw +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \section{Line-wise processing}% +% Sometimes we wish to process each line of type that will be placed into the galley, +% for example, applying line numbering to a document. +% To accomplish the task, we have to force a visit to the output routine after each such line, whereupon +% we can process it accordingly (in the case of line numbering, we could do as \filename{lineno.sty} and +% append an appropriately formed box to the MVL). +% +% In implementing such a scheme, we will have to instantiate interrupts for the following cases: +% \begin{description} +% +% \item[\cmd\interlinepenalty\ and friends] These include \cmd\clubpenalty, \cmd\widowpenalty, \cmd\displaywidowpenalty, and \cmd\brokenpenalty. +% +% +% \item[Display math penalties] Includes \cmd\predisplaypenalty, \cmd\postdisplaypenalty, and \cmd\interdisplaylinepenalty. +% +% +% \item[\cs{par}] The penalty following the last line of the paragraph. +% +% +% \item[\cmd\vadjust] A trap for any \cmd\vadjust\ command that falls in the paragraph. +% +% \end{description} +% +% \begin{macro}{\def@next@handler} +% \begin{macro}{\def@line@handler} +% Utility procedures \cmd\def@next@handler\ and \cmd\def@line@handler\ help in the creation of +% interrupt handlers. +% +% \cmd\def@next@handler\ increments the scratch count register (argument 1), +% using this value to \cmd\mathchardef\ its second argument +% as the negative of the flag value to be used as a penalty for exciting the interrupt (argument 3). +% As a byproduct, it leaves the given scratch counter incremented. +% \begin{macrocode} +\def\def@next@handler#1#2#3{% + \advance#1\@ne\mathchardef#2\the#1% + \expandafter\def\csname output@-\the#1\endcsname{#3}% +% \end{macrocode} +% The following line is for diagnostic purposes. +% \begin{verbatim} +% \typeout{\string#2(\expandafter\string\csname output@\the#1\endcsname:\expandafter\meaning\csname output@\the#1\endcsname)}% +% \end{verbatim} +% \begin{macrocode} +}% +% \end{macrocode} +% \cmd\def@line@handler\ uses \cmd\int@parpenalty\ as a base. +% The interrupt is the sum of that base with the first argument, +% and the handler is the second argument. +% \begin{macrocode} +\def\def@line@handler#1#2{% + \begingroup + \@tempcnta\int@parpenalty + \advance\@tempcnta-#1% +% \end{macrocode} +% The following line is for diagnostic purposes. +% \begin{verbatim} +% \typeout{Defining: \expandafter\string\csname output@\the\linenopenalty\endcsname}% +% \end{verbatim} +% \begin{macrocode} + \aftergroup\def + \expandafter\aftergroup\csname output@-\the\@tempcnta\endcsname + \endgroup{#2}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\int@parpenalty} +% \begin{macro}{\@handle@line@ltx} +% \begin{macro}{\@@handle@line@ltx} +% We first set \cmd\int@parpenalty\ to our chosen base value${}\le -11012$. +% We then define all the handlers for lines within a paragraph, of which there are 12 different cases. +% \begin{macrocode} +\mathchardef\int@parpenalty11012 +\def@line@handler\z@{\@handle@line@ltx{}{}{}}% +\def@line@handler\@ne{\@handle@line@ltx{}{}{\brokenpenalty@ltx}}% +\def@line@handler\tw@{\@handle@line@ltx{}{\clubpenalty@ltx}{}}% +\def@line@handler\thr@@{\@handle@line@ltx{\clubpenalty@ltx}{}{\brokenpenalty@ltx}}% +\def@line@handler\f@ur{\@handle@line@ltx{\widowpenalty@ltx}{}{}}% +\def@line@handler{5}{\@handle@line@ltx{\widowpenalty@ltx}{}{\brokenpenalty@ltx}}% +\def@line@handler{6}{\@handle@line@ltx{\widowpenalty@ltx}{\clubpenalty@ltx}{}}% +\def@line@handler{7}{\@handle@line@ltx{\widowpenalty@ltx}{\clubpenalty@ltx}{\brokenpenalty@ltx}}% +\def@line@handler{8}{\@handle@line@ltx{\displaywidowpenalty@ltx}{}{}}% +\def@line@handler{9}{\@handle@line@ltx{\displaywidowpenalty@ltx}{}{\brokenpenalty@ltx}}% +\def@line@handler{10}{\@handle@line@ltx{\displaywidowpenalty@ltx}{\clubpenalty@ltx}{}}% +\def@line@handler{11}{\@handle@line@ltx{\displaywidowpenalty@ltx}{\clubpenalty@ltx}{\brokenpenalty@ltx}}% +% \end{macrocode} +% +% The default handler for lines within a paragraph simply +% restores the value of the \cmd\penalty\ to the normal value. +% If something more useful needs to be done, we can change the definition of \cmd\@@handle@line@ltx. +% \begin{macrocode} +\def\@handle@line@ltx#1#2#3{% + \@@handle@line@ltx + \@tempcnta\lastpenalty + \@tempcntb\interlinepenalty@ltx\relax + \@if@empty{#1}{}{\advance\@tempcntb#1\relax}% + \@if@empty{#2}{}{\advance\@tempcntb#2\relax}% + \@if@empty{#3}{}{\advance\@tempcntb#3\relax}% + \penalty\@ifnum{\@tempcnta<\@tempcntb}{\@tempcntb}{\@tempcnta}% +}% +\let\@@handle@line@ltx\@empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\int@postparpenalty} +% \begin{macro}{\int@vadjustpenalty} +% \begin{macro}{\int@whatsitpenalty} +% \begin{macro}{\int@predisplaypenalty} +% \begin{macro}{\int@interdisplaylinepenalty} +% \begin{macro}{\int@postdisplaypenalty} +% \begin{macro}{\@handle@display@ltx} +% \begin{macro}{\@@handle@display@ltx} +% \begin{macro}{\handle@par@ltx} +% We herewith define all the handlers for cases relating to display math: +% last line before a display math, +% last line of a display math, and a line within a display math. +% We also handle the last line of a paragraph, a whatsit node, and a \cmd\vadjust. +% \begin{macrocode} +\@tempcnta\int@parpenalty +\def@next@handler\@tempcnta\int@postparpenalty{\reset@queues@ltx\handle@par@ltx}% +\def@next@handler\@tempcnta\int@vadjustpenalty{\handle@vadjust@ltx}% +\def@next@handler\@tempcnta\int@whatsitpenalty{\handle@whatsit@ltx}% +\def@next@handler\@tempcnta\int@predisplaypenalty{\reset@queues@ltx\@handle@display@ltx{\predisplaypenalty@ltx}}% +\def@next@handler\@tempcnta\int@interdisplaylinepenalty{\@handle@display@ltx{\interdisplaylinepenalty@ltx}}% +\def@next@handler\@tempcnta\int@postdisplaypenalty{\@handle@display@ltx{\postdisplaypenalty@ltx}}% +% \end{macrocode} +% The default handler for display math lines simply +% restores the value of the \cmd\penalty\ to the normal value. +% If something more useful needs to be done, we can change the definition of \cmd\@@handle@display@ltx. +% \begin{macrocode} +\def\@handle@display@ltx#1{% + \@@handle@display@ltx + \@tempcnta\lastpenalty + \@tempcntb#1% + \penalty\@ifnum{\@tempcnta<\@tempcntb}{\@tempcntb}{\@tempcnta}% +}% +\let\@@handle@display@ltx\@empty +% \end{macrocode} +% +% We provide stub definitions for the handlers for the last line of a paragraph, a \cmd\vadjust, and a whatsit node (e.g., \cmd\write, \cmd\special). +% There is no canonical penalty for such cases. +% \begin{macrocode} +\def\handle@par@ltx{}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% Note that a whatsit needs to be handled differently from a \cmd\vadjust: +% a whatsit node does not affect the (crucial) depth of \cmd\box\cmd\@cclv, while the more +% general \cmd\vadjust\ may cause any kind of vertical mode material to be interposed just below the line +% we are trying to trap, in particular \cmd\vskip s and \cmd\penalty s. +% +% \begin{macro}{\set@linepenalties} +% \begin{macro}{\restore@linepenalties} +% \begin{macro}{\set@displaypenalties} +% Now we define utility procedures that set up for a paragraph to be broken into lines, +% restoring the penalties afterwards. +% +% Utility procedure \cmd\set@linepenalties\ systematically sets the penalties of paragraph breaking +% to flag values, meanwhile storing away the normal values for access by the output routine. +% \begin{macrocode} +\def\set@linepenalties{% + \expandafter\def\expandafter\interlinepenalty@ltx\expandafter{\the\interlinepenalty}% + \interlinepenalty-\int@parpenalty + \expandafter\def\expandafter\brokenpenalty@ltx\expandafter{\the\brokenpenalty}% + \brokenpenalty\@ne + \expandafter\def\expandafter\clubpenalty@ltx\expandafter{\the\clubpenalty}% + \clubpenalty\tw@ + \expandafter\def\expandafter\widowpenalty@ltx\expandafter{\the\widowpenalty}% + \widowpenalty\f@ur + \expandafter\def\expandafter\displaywidowpenalty@ltx\expandafter{\the\displaywidowpenalty}% + \displaywidowpenalty8\relax +}% +% \end{macrocode} +% +% Utility procedure \cmd\restore@linepenalties\ restores the values of the penalty parameters that were +% modified by \cmd\set@linepenalties. +% \begin{macrocode} +\def\restore@linepenalties{% + \interlinepenalty\interlinepenalty@ltx + \brokenpenalty\brokenpenalty@ltx + \clubpenalty\clubpenalty@ltx + \widowpenalty\widowpenalty@ltx + \displaywidowpenalty\displaywidowpenalty@ltx + \relax +}% +% \end{macrocode} +% +% In the following, the first argument should be a boolean (either \cmd\true@sw\ or \cmd\false@sw). +% \begin{macrocode} +\def\set@displaypenalties#1{% + \expandafter\def\expandafter\predisplaypenalty@ltx\expandafter{\the\predisplaypenalty}% + \expandafter\def\expandafter\interdisplaylinepenalty@ltx\expandafter{\the\interdisplaylinepenalty}% + \expandafter\def\expandafter\postdisplaypenalty@ltx\expandafter{\the\postdisplaypenalty}% + \@ifhmode{\predisplaypenalty-\int@predisplaypenalty\relax}{}% + #1{\interdisplaylinepenalty-\int@interdisplaylinepenalty\relax}{}% + #1{\postdisplaypenalty-\int@postdisplaypenalty\relax}{}% +}% +% \end{macrocode} +% We provide no procedure to restore the respective penalties, because they are altered within a group: +% \TeX 's context stack will automatically restore things. +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\enqueue@whatsit@ltx}% +% \begin{macro}{\handle@whatsit@ltx}% +% \begin{macro}{\do@whatsit}% +% \begin{macro}{\@g@pop@ltx}% +% Here is a facility for dealing with whatsit nodes while we are trapping paragraph lines. +% We simply enqueue a macro that will create the desired whatsit node, dequeueing it in the output routine. +% \begin{macrocode} +\def\enqueue@whatsit@ltx#1{% + \gappdef\g@whatsit@queue{{#1}}% + \vadjust{\penalty-\int@whatsitpenalty}% +}% +\def\handle@whatsit@ltx{% + \unvbox\@cclv + \g@pop@ltx\g@whatsit@queue\@tempa + \expandafter\do@whatsit\expandafter{\@tempa}% +}% +\def\do@whatsit#1{}% +\def\g@pop@ltx#1#2{% + \expandafter\@g@pop@ltx#1{}{}\@@#1#2% +}% +\def\@g@pop@ltx#1#2\@@#3#4{% + \gdef#3{#2}% + \def#4{#1}% +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\vspace}% +% \begin{macro}{\pagebreak}% +% \begin{macro}{\nopagebreak}% +% \begin{macro}{\\}% +% \begin{macro}{\@arrayparboxrestore}% +% We wish to prevent \filename{lineno.sty} from patching \cmd\vspace\ and \cmd\pagebreak, +% because that package does it through global assignments, which is prone to failure. +% +% We also wish to prevent that package from patching \cmd\@arrayparboxrestore, because +% it prevents us from \cmd\unvbox ing vertical mode material into the MVL and numbering those +% lines. +% +% We start by retaining the original definitions of these commands, so we can restore them +% if \filename{lineno.sty} does get loaded. +% \begin{macrocode} +\let\vspace@ltx\vspace +\let\pagebreak@ltx\pagebreak +\let\nopagebreak@ltx\nopagebreak +\let\endline@ltx\\ +\let\@arrayparboxrestore@ltx\@arrayparboxrestore +% \end{macrocode} +% +% Next, we provide for line-wise processing by patching the procedures associated with these same three commands. +% +% Depending on the running version of \LaTeX, these commands use \cs{vskip} (before 2020-10-01), or +% \cs{@vspace@calcify} to add \textsf{calc}-like support in the kernel. To avoid duplicating the tests, +% define a macro \cs{@tempa} that takes the right form of the primitive spacing command and defines \LaTeX's +% spacing macros accordingly. +% \begin{macrocode} +\def\@tempa#1{% +% \end{macrocode} +% +% There are exactly four core \LaTeX\ procedures that use \cmd\vadjust\ to insert vertical mode material +% into the main vertical list: \cmd\vspace, \cmd\pagebreak, \cmd\nopagebreak, and \cmd\\. +% Other commands may use \cmd\vadjust, but they are inserting an interrupt (via a penalty${}<10000$), +% and such a thing does not mask the depth of \cmd\box\cmd\@cclv, hence is permissible. +% +% In each case, we replace the core \LaTeX\ procedure with one that itself replaces \cmd\vadjust\ with +% \cmd\ex@vadjust@ltx. The meaning of this procedure can be left as \cmd\vadjust, or it can be changed to +% one that accomplishes the equivalent without masking the depth of \cmd\box\cmd\@cclv. +% +% The first procedure is \cmd\@vspace, here shown in original form and in the patched alternative form. +% This procedure and \cmd\@vspacer\ implement the \cmd\vspace\ command. +% +% \begin{macrocode} +\def\@vspace@org ##1{% + \ifvmode + #1% \vskip #1 + \vskip\z@skip + \else + \@bsphack + \vadjust{\@restorepar + #1% \vskip #1 + \vskip\z@skip + }% + \@esphack + \fi +}% +\def\@vspace@ltx##1{% + \@ifvmode{% + #1% \vskip #1 + \vskip\z@skip + }{% + \@bsphack + \ex@vadjust@ltx{% + \@restorepar + \nobreak + #1% \vskip #1 + \vskip\z@skip + }% + \@esphack + }% +}% +% \end{macrocode} +% +% The second procedure is \cmd\@vspacer. +% \begin{macrocode} +\def\@vspacer@org##1{% + \ifvmode + \dimen@\prevdepth + \hrule \@height\z@ + \nobreak + #1%\vskip #1 + \vskip\z@skip + \prevdepth\dimen@ + \else + \@bsphack + \vadjust{\@restorepar + \hrule \@height\z@ + \nobreak + #1%\vskip #1 + \vskip\z@skip}% + \@esphack +\fi +}% +\def\@vspacer@ltx##1{% + \@ifvmode{% + \dimen@\prevdepth + \hrule\@height\z@ + \nobreak + #1%\vskip#1 + \vskip\z@skip + \prevdepth\dimen@ + }{% + \@bsphack + \ex@vadjust@ltx{% + \@restorepar + \hrule\@height\z@ + \nobreak + #1%\vskip#1 + \vskip\z@skip + }% + \@esphack + }% +}% +% \end{macrocode} +% +% Now define the macros above conditionally depending on the \LaTeX version. +% \begin{macrocode} +} +\rvtx@ifformat@geq{2020/10/01}% + {\@tempa{\@vspace@calcify{#1}}}% + {\@tempa{\vskip #1 }}% +% \end{macrocode} +% +% The procedure \cmd\@no@pgbk\ implements both \cmd\pagebreak\ and \cmd\nopagebreak. +% \begin{macrocode} +\def\@no@pgbk@org #1[#2]{% + \ifvmode + \penalty #1\@getpen{#2}% + \else + \@bsphack + \vadjust{\penalty #1\@getpen{#2}}% + \@esphack + \fi +}% +\def\@no@pgbk@ltx#1[#2]{% + \@ifvmode{% + \penalty#1\@getpen{#2}% + }{% + \@bsphack + \ex@vadjust@ltx{% + \penalty#1\@getpen{#2}% + }% + \@esphack + }% +}% +% \end{macrocode} +% +% The command to end a line of type, \cmd\\, is defined via \cmd\DeclareRobustCommand, +% so we must proceed carefully: +% A procedure is defined whose \cmd\long\cmd\csname\ is contructed via the incantation: +% \cmd\csname\cmd\expandafter\cmd\@gobble\cmd\string\cmd\\ \cmd\endcsname. +% Note the non-trivial space character after the \cmd\\: it is incorporated into +% the \cmd\csname. +% +% Here is the original core \LaTeX\ definition for +% the procedure involved, along with our revised version. +% \changes{2020/09/30}{4.2d}{Conditionally use \cs{protected} or \cs{long} to track \LaTeX{} changes.} +% \begin{macrocode} +\rvtx@ifformat@geq{2020/02/02}% +{\protected}{\long}\def\end@line@org{% + \let\reserved@e\relax + \let\reserved@f\relax + \@ifstar{% + \let\reserved@e\vadjust + \let\reserved@f\nobreak + \@xnewline + }% + \@xnewline +}% +\rvtx@ifformat@geq{2020/02/02}% +{\protected}{\long}\def\end@line@ltx{% + \let\reserved@e\relax + \let\reserved@f\relax + \@ifstar{% + \let\reserved@e\ex@vadjust@ltx + \let\reserved@f\nobreak + \@xnewline + }{% + \@xnewline + }% +}% +% \end{macrocode} +% An additional procedure requiring patching has the following original core \LaTeX\ +% definition; we modify it correspondingly. +% \begin{macrocode} +\def\@tempa#1{% + \def\@newline@org[##1]{% + \let\reserved@e\vadjust + \@gnewline{#1}% \vskip#1 + }% + \def\@newline@ltx[##1]{% + \let\reserved@e\ex@vadjust@ltx + \@gnewline{#1}% \vskip#1 + }% +} +\rvtx@ifformat@geq{2020/10/01}% + {\@tempa{\@vspace@calcify{#1}}}% + {\@tempa{\vskip #1}}% +% \end{macrocode} +% We now install our patches. +% If some package overrides these macros, we will detect and complain. +% +% \begin{macrocode} + \@ifx{\@vspace\@vspace@org}{% + \@ifx{\@vspacer\@vspacer@org}{% + \@ifx{\@no@pgbk\@no@pgbk@org}{% + \@ifx{\@newline\@newline@org}{% + \expandafter\@ifx\expandafter{% + \csname\rvtx@ifformat@geq{2020/02/02}% + {\expandafter\@gobble\string\\}% + {\expandafter\@gobble\string\\ }\endcsname + \end@line@org + }{% + \true@sw + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + {% + \class@info{Overriding \string\@vspace, \string\@vspacer, \string\@no@pgbk, \string\@newline, and \string\\ }% + \let\@normalcr\end@line@ltx + \expandafter\let + \csname\rvtx@ifformat@geq{2020/02/02}% + {\expandafter\@gobble\string\\}% + {\expandafter\@gobble\string\\ }\endcsname\@normalcr + \let\@newline\@newline@ltx + \let\@vspace\@vspace@ltx + \let\@vspacer\@vspacer@ltx + \let\@no@pgbk\@no@pgbk@ltx + }{% + \class@warn{% + Failed to recognize \string\@vspace, \string\@vspacer, \string\@no@pgbk, \string\@newline, and \string\\; + no patches applied. Please get a more up-to-date class, + }% + }% +% \end{macrocode} +% Note that we have assigned the same meaning to \cmd\@normalcr, which is necessary to \LaTeX. +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\ex@vadjust@ltx} +% \begin{macro}{\enqueue@vadjust@ltx} +% \begin{macro}{\handle@vadjust@ltx} +% \begin{macro}{\g@vadjust@line} +% \begin{macro}{\reset@queues@ltx} +% Here we give the default definition for \cmd\ex@vadjust@ltx\ along with +% the definitions for the alternative version and its the associated handler. +% \begin{macrocode} +\let\ex@vadjust@ltx\vadjust +\def\enqueue@vadjust@ltx#1{% + \gappdef\g@vadjust@queue{{#1}}% + \vadjust{\penalty-\int@vadjustpenalty}% +}% +\def\handle@vadjust@ltx{% + \unvbox\@cclv + \g@pop@ltx\g@vadjust@queue\@tempa + \expandafter\gappdef\expandafter\g@vadjust@line\expandafter{\@tempa}% +}% +\let\g@vadjust@line\@empty +% \end{macrocode} +% Procedure \cmd\reset@queues@ltx\ resets the whatsit queue and the \cmd\vadjust\ queues +% to their empty state. This should be done whenever we leave horizontal mode and +% complete the processing of these queues: upon executing, effectively, primitive \cmd\par\ +% or interrupting a paragraph with display math. +% \begin{macrocode} +\def\reset@queues@ltx{% + \global\let\g@whatsit@queue\@empty + \global\let\g@vadjust@queue\@empty +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \section{Patching the lineno.sty package} +% +% \filename{lineno.sty} is a \LaTeX\ package that applies line numbering to a document. +% The basic method is to give \cmd\interlinepenalty\ and like penalties such a value as +% to force a visit to the output routine, where the line of type is given its number. +% In order to properly measure the depth of \cmd\box\cmd\@cclv, it defers \cmd\vadjust\ +% commands that may insert \cmd\vskip\ or \cmd\penalty\ nodes. +% +% The implementation of that package, however, manipulates \cmd\holdinginserts\ in a dangerous +% way: outside the safety of the output routine. It also alters the meaning of \cmd\vadjust\ +% using global assignments. We patch its code to avoid these problems. The \filename{ltxgrid} +% package already has the needed mechanisms in place to do these jobs correctly. +% +% The methods we use can accomodate any values of penalties like \cmd\clubpenalty, etc: +% we do not make assumptions about the range of values these penalty parameters could take. +% +% +% \begin{macro}{\linenomathWithnumbers} +% \begin{macro}{\linenomathNonumbers} +% \begin{macro}{\endlinenomath} +% \begin{macro}{\linenumberpar} +% Here are the definitions of procedures in \filename{lineno.sty} +% that alter \cmd\holdinginserts. They are current as of version v4.41, 2005/11/02. +% We patch them to avoid doing this: in ltxgrid-based classes like REVTeX, the output routine properly manages \cmd\holdinginserts, so packages should not attempt to do so. +% Also, we will want \cmd\linenumberpar\ to set \cmd\interlinepenaly\ to dispatch to \cmd\MakeLineNo. +% +% \begin{macrocode} +\newcommand\linenomathWithnumbers@LN{% + \ifLineNumbers + \ifnum\interlinepenalty>-\linenopenaltypar + \global\holdinginserts\thr@@ + \advance\interlinepenalty \linenopenalty + \ifhmode + \advance\predisplaypenalty \linenopenalty + \fi + \advance\postdisplaypenalty \linenopenalty + \advance\interdisplaylinepenalty \linenopenalty + \fi + \fi + \ignorespaces +}% +\newcommand\linenomathNonumbers@LN{% + \ifLineNumbers + \ifnum\interlinepenalty>-\linenopenaltypar + \global\holdinginserts\thr@@ + \advance\interlinepenalty \linenopenalty + \ifhmode + \advance\predisplaypenalty \linenopenalty + \fi + \fi + \fi + \ignorespaces +}% +\def\endlinenomath@LN{% + \ifLineNumbers + \global\holdinginserts\@LN@outer@holdins + \fi + \global\@ignoretrue +} +\def\linenumberpar@LN{% + \ifvmode \@@@par \else + \ifinner \@@@par \else + \xdef\@LN@outer@holdins{\the\holdinginserts}% + \advance \interlinepenalty \linenopenalty + \linenoprevgraf \prevgraf + \global \holdinginserts \thr@@ + \@@@par + \ifnum\prevgraf>\linenoprevgraf + \penalty-\linenopenaltypar + \fi + \@LN@parpgbrk + \global\holdinginserts\@LN@outer@holdins + \advance\interlinepenalty -\linenopenalty + \fi + \fi +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\class@documenthook} +% We patch only if we recognize the definitions of all the procedures we are to patch. +% \begin{macrocode} +\appdef\class@documenthook{% + \@ifpackageloaded{lineno}{% + \@ifx{\linenomathWithnumbers\linenomathWithnumbers@LN}{% + \@ifx{\linenomathNonumbers\linenomathNonumbers@LN}{% + \@ifx{\endlinenomath\endlinenomath@LN}{% + \@ifx{\linenumberpar\linenumberpar@LN}{% + \true@sw + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + }{\false@sw}% + {% + \class@info{Overriding lineo.sty, restoring output routine,}% +% \end{macrocode} +% We commence overriding the procedures of \filename{lineno.sty}. +% \begin{macrocode} + \let\linenumberpar\linenumberpar@ltx + \let\endlinenomath\endlinenomath@ltx + \expandafter\let\csname endlinenomath*\endcsname\endlinenomath@ltx + \let\linenomathWithnumbers\linenomathWithnumbers@ltx + \let\linenomathNonumbers\linenomathNonumbers@ltx +% \end{macrocode} +% Override \filename{lineno.sty}'s equipment for \cmd\vadjust\ and \cmd\linelabel: +% we have existing interrupts and handlers for these purposes. +% \begin{macrocode} + \let\ex@vadjust@ltx\ex@vadjust@line + \let\@LN@postlabel\enqueue@whatsit@ltx + \let\do@whatsit\write@linelabel +% \end{macrocode} +% Redirect handlers to those provided by \filename{lineno.sty}, and +% give an appropriate meaning to the respective headpatch within the handlers. +% \begin{macrocode} + \let\handle@par@ltx\handle@par@LN + \let\@@handle@line@ltx\Make@LineNo@ltx + \let\@@handle@display@ltx\Make@LineNo@ltx +% \end{macrocode} +% Next, we undo the action taken by \filename{lineno.sty} wherein it +% took over the output routine. Instead, we service \filename{lineno.sty} +% existing equipment of \filename{ltxgrid}. +% We also revert the core \LaTeX\ definitions of +% \cmd\vspace, \cmd\pagebreak, \cmd\nopagebreak, and \cmd\\, +% which that package takes over (we have our own ways of doing these things). +% \begin{macrocode} + \output@latex{\natural@output}% + \let\vspace\vspace@ltx + \let\pagebreak\pagebreak@ltx + \let\nopagebreak\nopagebreak@ltx + \let\@arrayparboxrestore\@arrayparboxrestore@ltx + \let\\\endline@ltx +% \end{macrocode} +% \changes{4.1f}{2009/07/07}{(AO, 515) Prevent line numbering within a footnote} +% When line numbering is in effect, we must avoid any attempt to number the lines of a footnote. +% \begin{macrocode} + \appdef\set@footnotefont{% + \let\par\@@@par + \let\@@par\@@@par + }% +% \end{macrocode} +% At last, we detect if the \cmd\linenumbers\ command has already been given; +% if so, we do its assignments again, because we have changed the meaning of \cmd\linenumberpar. +% \begin{macrocode} + \@if@sw\ifLineNumbers\fi{% + \class@info{Reinvoke \string\linenumbers}% + \let\@@par\linenumberpar + \@ifx{\@par\linenumberpar@LN}{\let\@par\linenumberpar}{}% + \@ifx{\par\linenumberpar@LN}{\let\par\linenumberpar}{}% + }{% + \class@info{Line numbering not turned on yet}% + }% +% \end{macrocode} +% Here ends the ``true branch'' of the patch code. +% \begin{macrocode} + }{% +% \end{macrocode} +% If the \filename{lineno.sty} package is loaded, but we fail to patch it, notify the user. +% \begin{macrocode} + \class@warn{Failed to recognize lineno.sty procedures; no patches applied. Please get a more up-to-date class.}% + }% + }{% +% \end{macrocode} +% \filename{lineno.sty} is not loaded, so no patches are needed. +% \begin{macrocode} + }% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\linenumberpar} +% \begin{macro}{\@linenumberpar} +% Procedure \cmd\linenumberpar\ takes the place of \cmd\par\ when line numbering is in effect; +% It executes the \cmd\par\ primitive if we are in vertical mode. +% Otherwise we are in horizontal mode in the MVL and wish to end the current paragraph, +% or we have \cmd\unvbox ed material onto the MVL. +% +% \begin{macrocode} +\def\linenumberpar@ltx{\@ifvmode{\@@@par}{\@linenumberpar}}% +% \end{macrocode} +% +% Procedure \cmd\@linenumberpar +% \begin{macrocode} +\def\@linenumberpar{% +% \end{macrocode} +% Prepare for our trip into the output routine by +% saving away the current value of \cmd\prevgraf. +% \begin{macrocode} + \linenoprevgraf\prevgraf +% \end{macrocode} +% The following will be used in the output routine dispatcher +% to sense that we came from here. +% \begin{macrocode} + \set@linepenalties +% \end{macrocode} +% Finally, call primitive \cmd\par\ with the signal value of \cmd\interlinepenalty\ and friends. +% \begin{macrocode} + \@@@par +% \end{macrocode} +% We are now in vertical mode. +% If lines of type were contributed to the MVL (non-trivial paragraph), +% we must force another trip into the output routine to apply +% line numbering to the last line of the paragraph. +% \begin{macrocode} + \@ifnum{\prevgraf>\linenoprevgraf}{ + \penalty-\int@postparpenalty + }{}% +% \end{macrocode} +% Execute procedure \cmd\@LN@parpgbrk, which has been set up in the +% output routine for us to invoke here. +% +% \begin{macrocode} + \@LN@parpgbrk +% \end{macrocode} +% To wrap things up, we restore the original value of \cmd\interlinepenalty\ and friends. +% +% Query: why not employ \TeX's context stack to do the restore? +% Would there be something wrong with executing primitive \cmd\par\ within a group? +% \begin{macrocode} + \restore@linepenalties +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\linenomathWithnumbers} +% \begin{macro}{\linenomathNonumbers} +% Here are the patched definitions for the commands enabling +% line numbering in display math. +% \begin{macrocode} +\newcommand\linenomathWithnumbers@ltx{\@linenomathnumbers@ltx\true@sw}% +\newcommand\linenomathNonumbers@ltx{\@linenomathnumbers@ltx\false@sw}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\@linenomathnumbers} +% \begin{macro}{\endlinenomath} +% We have just begun a display math, and any paragraph we are setting will now end. +% We set all relevant penalties to interrupt values; in the visit to the output routine, +% we will replace the penalty with its normal value. +% \begin{macrocode} +\def\@linenomathnumbers@ltx#1{% + \@if@sw\ifLineNumbers\fi{% + \set@linepenalties + \set@displaypenalties#1% + }{}% + \ignorespaces +}% +\def\endlinenomath@ltx{% + \global\@ignoretrue +}% +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% We provide a handler for the last line of a paragraph. +% \begin{macrocode} +\def\handle@par@LN{% + \Make@LineNo@ltx +% \end{macrocode} +% After setting the line number, we arrange for an appropriate penalty to +% be laid down after this visit to the output routine ends. +% +% Query: why not contribute the penalty right here in the visit to the output routine? +% \begin{macrocode} + \@tempcnta\lastpenalty + \@ifnum{\@tempcnta=\z@}{}{% + \expandafter\gdef + \expandafter\@LN@parpgbrk + \expandafter{% + \expandafter\penalty + \the\@tempcnta +% \end{macrocode} +% When \cmd\@LN@parpgbrk\ is executed, it resets itself to the default value, +% \cmd\@LN@screenoff@pen. +% +% Query: \cmd\@LN@screenoff@pen\ appears to try to restore the depth of the last box: +% why is this being done outside the safety of the output routine? +% \begin{macrocode} + \global\let\@LN@parpgbrk\@LN@screenoff@pen + }% + }% +}% +% \end{macrocode} +% +% \begin{macro}{\Make@LineNo} +% The procedure \cmd\Make@LineNo\ sets the box containing the line number itself. +% \begin{macrocode} +\def\Make@LineNo@ltx{% + \@LN@maybe@normalLineNumber +% \end{macrocode} +% We measure the depth of \cmd\box\cmd\@cclv\ and unbox it. +% At this point, it is crucial that that box have the same depth as that of the last +% box within it. +% +% In the simple case, \cmd\box\cmd\@cclv\ is +% a \cmd\vbox\ containing as its last box the \cmd\hbox\ of the paragraph we are processing. +% +% Query: under what circumstances will this \emph{not} be the case? +% \begin{macrocode} + \boxmaxdepth\maxdimen\setbox\z@\vbox{\unvbox\@cclv}% + \@tempdima\dp\z@ + \unvbox\z@ +% \end{macrocode} +% Then we create the box with the line number, setting its height to zero. +% \begin{macrocode} + \sbox\@tempboxa{\hb@xt@\z@{\makeLineNumber}}% + \ht\@tempboxa\z@ +% \end{macrocode} +% With these preparations, we invoke \cmd\@LN@depthbox, which +% lays that box down (with its depth appropriately set): +% this procedure depends on our having set \cmd\@tempdima\ and \cmd\@tempboxa +% (kinda kludgy way of passing arguments, really). +% \begin{macrocode} + \@LN@depthbox +% \end{macrocode} +% Now increment the line number. I have relocated this token past \cmd\@LN@depthbox: +% this may induce a bug, but I am going to hereby force the issue: +% why split up the procedure that lays down boxes with a procedure that sets a register value? +% \begin{macrocode} + \stepLineNumber +% \end{macrocode} +% Finally, execute the \cmd\vadjust s that fell within the line that we just handled. +% +% Note that \cmd\enqueue@vadjust@ltx\ had queued up all the \cmd\vadjust\ commands for the paragraph +% into \cmd\g@vadjust@queue, laying down an (\cmd\int@vadjustpenalty) interrupt in each ones' place. +% The interrupts associated with this line of the paragraph have now moved the tokens to \cmd\g@vadjust@line, +% which we now expand and execute. +% \begin{macrocode} + \g@vadjust@line + \global\let\g@vadjust@line\@empty +}% +% \end{macrocode} +% +% \begin{macrocode} +\def\write@linelabel#1{% + \protected@write\@auxout{}{% + \string\newlabel{#1}{{\theLineNumber}{\thepage}{}{}{}}% + }% +}% +% \end{macrocode} +% +% \begin{macrocode} +\def\ex@vadjust@line{% + \@if@sw\ifLineNumbers\fi{\enqueue@vadjust@ltx}{\vadjust}% +}% +% \end{macrocode} +% \end{macro} +% +% Note that the \cmd\linelabel\ commands use a mechanism different from \cmd\vadjust, +% embodied in the procedure \cmd\enqueue@vadjust@ltx, wherein the +% \cmd\write\ primitives are enqueued while the paragraph is being processed, each replaced with +% an interrupt, then dequeued and executed by the interrupt handler, leaving a \cmd\write\ node +% in place of the interrupt (just where the \cmd\vadjust 's vertical mode material would had been) +% just below the box containing the line of type. This \cmd\write, like all whatsits, +% does not affect the depth of \cmd\box\cmd\@cclv, unlike the case of general vertical mode material, +% which could have interfered. +% +% \section{End of the \file{ltxgrid} {\sc docstrip} module} +% Here ends the module. +% \begin{macrocode} +%</kernel> +% \end{macrocode} +% +% \Finale +% %Here ends the programmer's documentation. +% \endinput +% +\endinput +%%EOF |