summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/revtex/ltxgrid.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/revtex/ltxgrid.dtx')
-rw-r--r--Master/texmf-dist/source/latex/revtex/ltxgrid.dtx4815
1 files changed, 4815 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/revtex/ltxgrid.dtx b/Master/texmf-dist/source/latex/revtex/ltxgrid.dtx
new file mode 100644
index 00000000000..ab0209ed098
--- /dev/null
+++ b/Master/texmf-dist/source/latex/revtex/ltxgrid.dtx
@@ -0,0 +1,4815 @@
+% \iffalse ltxdoc klootch
+% ltxgrid.dtx: package to change page grid, MVL.
+% Copyright (c) 1999 Arthur Ogawa
+%
+% Disclaimer
+% This file is distributed WITHOUT ANY WARRANTY;
+% without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+% ReadMe
+% For the documentation and more detailed instructions for
+% installation, typeset this document with \LaTeX.
+% \fi
+% \GetFileInfo{ltxgrid.dtx}\CheckSum{4234}
+%
+% \iffalse ltxdoc klootch
+%<*ltxgrid>
+%%% @LaTeX-file{
+%%% filename = "ltxgrid.dtx",
+%%% version = "1.0rc5",
+%%% date = "2001/07/26",
+%%% time = "12:23:00 GMT+8",
+%%% checksum = "4234",
+%%% author = "Arthur Ogawa (mailto:ogawa@teleport.com),
+%%% commissioned by the American Physical Society.
+%%% ",
+%%% copyright = "Copyright (C) 1999, 2000 Arthur Ogawa,
+%%% distributed under the terms of the
+%%% LaTeX Project Public License, see
+%%% ftp://ctan.tug.org/macros/latex/base/lppl.txt
+%%% ",
+%%% address = "Arthur Ogawa,
+%%% USA",
+%%% telephone = "",
+%%% FAX = "",
+%%% email = "ogawa@teleport.com",
+%%% codetable = "ISO/ASCII",
+%%% keywords = "latex, page grid, main vertical list",
+%%% supported = "yes",
+%%% abstract = "package to change page grid, MVL",
+%%% docstring = "The checksum field above generated by ltxdoc",
+%%% }
+%</ltxgrid>
+% \fi
+%
+% \iffalse ltxdoc klootch
+% The following references the \file{00readme.txt} 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*}{00readme.txt}" to locate it.
+% \fi\input{00readme.txt}%
+%
+% \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}
+%00readme.txt 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}
+%<*doc|ltxgrid>
+\NeedsTeXFormat{LaTeX2e}[1995/12/01]%
+%</doc|ltxgrid>
+% \end{macrocode}
+% As desired, the following modules all
+% take common version information:
+% \begin{macrocode}
+%<ltxgrid>\ProvidesFile{ltxgrid.sty}%
+%<*doc>
+\expandafter\ProvidesFile\expandafter{\jobname.dtx}%
+%</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.
+% \begin{macrocode}
+%<*doc|ltxgrid>
+ [2001/07/26 1.0rc5 page grid package]% \fileversion
+%</doc|ltxgrid>
+% \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{00readme.txt} 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}
+%<*doc>
+% \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
+% \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 installer file}
+%
+% The installer \file{ltxgrid.ins} appears here.
+% If you have retrieved the standard distribution of this package,
+% the installer file is already on your filesystem.
+% If you are bootstrapping,
+% the first typesetting of the \file{.dtx} file
+% will cause the installer to be generated.
+%
+% The following modules are used to direct
+% {\sc docstrip} in generating the external files:
+% \begin{center}
+% \begin{tabular}{lll}
+% \textbf{Module}&\textbf{File}&\textbf{Description}\\
+% doc &\file{ltxgrid.drv}&driver for programmer's documentation\\
+% ltxgrid,ltxgrid-krn &\file{ltxgrid.sty}&this package\\
+% ltxgrid-krn& &the portion of this package suitable for inclusion within another package
+% \end{tabular}
+% \end{center}
+%
+% \begin{macrocode}
+\begin{filecontents}{ltxgrid.ins}
+%% 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 00readme.txt.
+
+Copyright notice.
+
+ These files are distributed
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+\endpreamble
+\keepsilent
+ \generate{%
+ \file{ltxgrid.drv}{\from{ltxgrid.dtx}{doc}}%
+ \file{ltxgrid.sty}{%
+ \from{ltxgrid.dtx}{ltxgrid,ltxgrid-krn}%
+ }%
+ }%
+\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/ao/.}
+\Msg{*}
+\Msg{* To produce the documentation,
+ run ltxgrid.dtx through LaTeX.}
+\Msg{*}
+\Msg{* Happy TeXing}
+\Msg{***********************************************************}
+}
+\endbatchfile
+\end{filecontents}
+% \end{macrocode}
+% Note that, because all of the files generated by the installer
+% are part of the standard distribution, it will
+% be necessary to run the installer only when bootstrapping
+% (or, of course, during development).
+% Note, too, that it is rare to generate the \file{doc}
+% module because it suffices to simply typeset the \file{.dtx} file itself.
+%
+% \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*}{00readme.txt}
+\title{%
+ A \LaTeX\ Package for changing the page grid and MVL%
+ \thanks{%
+ This file has version number \fileversion,
+ last revised \filedate.%
+ % For version number and date,
+ % search on "\fileversion" in the .dtx file,
+ % or see the end of the 00readme.txt file.
+ }%
+}%
+
+\author{%
+Arthur Ogawa (\texttt{mailto:ogawa@teleport.com}),
+\fileversion\\Copyright (C) 1999, 2000 Arthur Ogawa
+}%
+\maketitle
+
+This file embodies the \classname{ltxgrid} package,
+the implementation and its user documentation.
+
+The distribution point for this work is
+\url{ftp://ftp.teleport.com/users/ogawa/macros/latex/contrib/supported/ltxgrid...},
+which contains fully unpacked, prebuilt runtime files and documentation.
+
+The \classname{ltxgrid} package was commissioned by the American Physical Society
+and is distributed under the terms of the \LaTeX\ Project Public License,
+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/ao/.}
+
+To use, read the user documentation \file{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.ins|.
+The typeset documentation that you are now reading is generated from
+the 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 \LaTeX\ or pdflatex;
+you will obtain the typeset documentation you are now reading,
+along with
+the installer \file{ltxgrid.ins},
+and the file \file{00readme.txt}.
+
+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
+Now typeset \file{ltxgrid.ins},
+thereby generating the package file \file{ltxgrid.sty}.
+\item
+Install \classname{ltxgrid.sty}
+by moving it to a location
+in your filesystem where they will be found by \LaTeX.
+\end{enumerate}
+\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}%
+\expandafter\DocInput\expandafter{\jobname.dtx}%
+% ^^A\PrintChanges
+\end{document}
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</doc>
+% \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{ftp://ftp.teleport.com/users/ogawa/macros/latex/contrib/supported/ltxutil/}.
+%
+% 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\@makecol.
+% 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 esablishes 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 is 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 mark it as discarded.
+% (Implementors of NTS, 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@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}
+%<*ltxgrid>
+\def\package@name{ltxgrid}%
+\expandafter\PackageInfo\expandafter{\package@name}{%
+ Page grid for \protect\LaTeXe,
+ by A. Ogawa (ogawa@teleport.com)%
+}%
+\RequirePackage{ltxutil}%
+%</ltxgrid>
+% \end{macrocode}
+%
+% \subsection{Banner}%
+% Credit where due.
+% \begin{macrocode}
+%<*ltxgrid-krn>
+\typeout{%
+ ltxgrid: portions licensed from W. E. Baxter (web@superscript.com)%
+}%
+% \end{macrocode}
+%
+% \subsection{Sundry}%
+% Here are assorted macro definitions.
+% \begin{macro}{\lineloop}
+% The document-level command \cmd\lineloop\ sets numbered lines until the
+% specified count is reached.
+% This command is mainly used to construct test documents.
+% \begin{macrocode}
+\newcounter{linecount}
+\def\lineloop#1{%
+ \loop
+ \ifnum\c@linecount<#1\relax
+ \global\advance\c@linecount\@ne
+ \par
+ \hb@xt@\hsize{%
+ \ifnum\c@linecount<100 0\fi\ifnum\c@linecount<10 0\fi\number\c@linecount
+ \vrule depth2.5\p@
+ \leaders\hrule\hfil
+ }%
+ \penalty\interlinepenalty
+ \repeat
+}%
+% \end{macrocode}
+% \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@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 shipping out (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}
+% 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\output
+ \@@nil
+ }%
+\newtoks\output
+\output\expandafter{\the\toks@}%
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\dispatch@output}
+% We now install our own output routine in place of the
+% old one, 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\ tokens.
+% \begin{macrocode}
+\primitive@output{\dispatch@output}%
+\def\dispatch@output{%
+ \let\par\@@par
+ \expandafter\let\expandafter\@tempa\csname output@\the\outputpenalty\endcsname
+ \outputdebug@sw{%
+ \saythe\badness
+ \saythe\outputpenalty
+ \saythe\holdinginserts
+ \say\thepagegrid
+ \saythe\pagegrid@col
+ \saythe\pagegrid@cur
+ %\say\bot@envir
+ \saythe\insertpenalties
+ %\say\@@topmark
+ %\say\saved@@topmark
+ %\say\@@firstmark
+ %\say\saved@@firstmark
+ \say\@@botmark
+ %\say\saved@@botmark
+ \saythe\pagegoal
+ \saythe\pagetotal
+ \saythe{\badness\@cclv}%
+ \expandafter\@ifx\expandafter{\csname output@-\the\execute@message@pen\endcsname\@tempa}{%
+ \say\@message@saved
+ }{%
+ \expandafter\say\csname output@\the\outputpenalty\endcsname
+ }%
+ \say\@toplist
+ \say\@botlist
+ \say\@dbltoplist
+ \say\@deferlist
+ {\tracingall\scrollmode
+ \showbox\@cclv
+ \showbox\@cclv@saved
+ \showbox\pagesofar
+ \showbox\footbox
+ \showbox\footins@saved
+ \showbox\footins
+ \showlists
+ }%
+ }{}%
+ \@ifnotrelax\@tempa{\@tempa}{\the\output}%
+}%
+\@ifxundefined{\outputdebug@sw}{%
+ \@booleanfalse\outputdebug@sw
+}{}%
+% \end{macrocode}
+% \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.
+%
+% 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 code \cmd\move@insert@sw\ tells whether we are on our first visit to
+% the output routine (with \cmd\holdinginserts\ still set), or our second
+% (with \cmd\holdinginserts\ cleared). The output routine will toggle the
+% setting.
+%
+% The commands \cmd\hold@insertions\ and \cmd\move@insertions\ respectively
+% clear and set the state of \cmd\move@insert@sw, 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 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\@makecol, 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}{\output}
+% Here is what has become of the output routine of \LaTeX.
+% It 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.
+%
+% \begin{macrocode}
+\output={\toggle@insert\output@holding\output@moving}%
+% \end{macrocode}
+%
+% 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.
+%
+% \begin{macrocode}
+\def\output@holding{%
+ \csname output@init@\bot@envir\endcsname
+%\vbadness\@M
+%\vfuzz\maxdimen
+ \@if@exceed@pagegoal{\unvcopy\@cclv}{%
+ \setbox\z@\vbox{\unvcopy\@cclv}%
+ \outputdebug@sw{{\tracingall\scrollmode\showbox\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{{\tracingall\scrollmode\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}
+%
+% 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 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}
+%
+% \begin{macrocode}
+\def\output@moving{%
+ \set@top@firstmark
+ \@ifnum{\outputpenalty=\do@newpage@pen}{%
+ \setbox\@cclv\vbox{%
+ \unvbox\@cclv
+ \setbox\z@\lastbox
+ \@ifdim{\ht\z@=\ht\@protection@box}{\box\lastbox}{\unskip}%
+ }%
+ }{}%
+ \@cclv@nontrivial@sw{%
+ \csname output@prep@\bot@envir \endcsname
+ \@makecol\csname output@column@\thepagegrid\endcsname
+ \protect@penalty\do@startcolumn@pen
+ \clearpage@sw{%
+ \protect@penalty\do@endpage@pen
+ }{}%
+ \csname output@post@\bot@envir \endcsname
+ }{%
+ {\setbox\z@\box\@cclv}%
+ }%
+ \set@colroom
+ \global\@mparbottom\z@
+ \global\@textfloatsheight\z@ %FIXME: this legacy LaTeX variable is set, but never queried!
+}%
+% \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 whatit nodes followed by topskip and a protection box.
+% This is what happens under normal circumstances at the end of \cmd\clearpage\ processing.
+% \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{%
+ \unvbox\z@
+ \setbox\z@\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
+ }%
+ }%
+ {%
+ \false@sw % Normal for \clearpage
+ }{%
+ \true@sw
+ }%
+ }{%
+ \@ifdim{\ht\z@=\z@}{%
+ \ltxgrid@info{Found trivial column. Discarding it}%
+ \outputdebug@sw{{\tracingall\scrollmode\showbox\@cclv}}{}%
+ \false@sw
+ }{%
+ \true@sw
+ }%
+ }%
+ }%
+ }{%
+ \true@sw
+ }%
+ }{%
+ \true@sw
+ }%
+ }{%
+ \true@sw
+ }%
+}%
+% \end{macrocode}
+%
+%
+% \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
+ \setbox\z@\lastbox % Remove protection box
+ \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.
+% \begin{macrocode}
+\def\output@init@document{%
+ \@ifvoid\footbox{}{%
+ \global\advance\vsize-\ht\footbox
+ \global\advance\vsize-\dp\footbox
+ }%
+}%
+\def\output@prep@document{%
+ \@ifvoid\footbox{}{%
+% {\tracingall\scrollmode\showbox\footbox\showbox\footins}%
+ \setbox\footins\vbox{\unvbox\footbox\unvbox\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}{\@makecol}
+% The procedure \cmd\@makecol\ 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.
+% \begin{macrocode}
+\def\@makecol{%
+ \setbox\@outputbox\vbox{%
+ \boxmaxdepth\@maxdepth
+ \@tempdima\dp\@cclv
+ \unvbox\@cclv
+ \vskip-\@tempdima
+ }%
+ \xdef\@freelist{\@freelist\@midlist}\global\let\@midlist\@empty
+ \@combinefloats
+ \@combineinserts\@outputbox\footins
+%\@ifvbox\@kludgeins{%
+% \@makespecialcolbox
+%}{%
+ \set@adj@colht\dimen@
+ \count@\vbadness
+ \vbadness\@M
+ \setbox\@outputbox\vbox to\dimen@{%
+ \@texttop
+ \dimen@\dp\@outputbox
+ \unvbox\@outputbox
+ \vskip-\dimen@
+ \@textbottom
+ }%
+ \vbadness\count@
+%}%
+ \global\maxdepth\@maxdepth
+}%
+\let\@makespecialcolbox\@undefined
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@combineinserts}
+% We split out the procedure to add the \cmd\footins\ insertions to the packaged-up page.
+% Any other non-trivial insertions should also be dealt with at this time.
+% \begin{macrocode}
+\def\@combineinserts#1#2{%
+ \setbox#1\vbox{%
+ \unvbox#1%
+% {\tracingall\scrollmode\showbox#2}%
+ \vbox{%
+ \@ifvoid#2{}{%
+ \vskip\skip\footins
+ \color@begingroup
+ \normalcolor
+ \footnoterule
+ \nointerlineskip
+ \box#2%
+ \color@endgroup
+ }{}%
+ }%
+ }%
+}%
+% \end{macrocode}
+% \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''.
+% \begin{macrocode}
+\mathchardef\do@startcolumn@pen=10005
+\@namedef{output@-\the\do@startcolumn@pen}{\do@startcolumn}%
+\def\do@startcolumn{%
+ \setbox\@cclv\vbox{\unvbox\@cclv\setbox\z@\lastbox\unskip}%
+ \clearpage@sw{\@clearfloatplacement}{\@floatplacement}%
+ \set@colroom
+ \@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}%
+% \csname float@column@\thepagegrid\endcsname
+% \csname output@column@\thepagegrid\endcsname
+ \outputpenalty-\pagebreak@pen % ask for a return visit, this time with insertions and all.
+ \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}{\@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.
+% \begin{macrocode}
+\mathchardef\do@startpage@pen=10006
+\@namedef{output@-\the\do@startpage@pen}{\do@startpage}%
+\def\do@startpage{%
+ \setbox\@cclv\vbox{\unvbox\@cclv\setbox\z@\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}%
+ \@combinepage
+ \@combinedblfloats
+ \@outputpage
+ \global\pagegrid@cur\@ne
+ \protect@penalty\do@startpage@pen
+ }{%
+ \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
+%\set@colroom
+}%
+\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}
+%
+% \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\footbox.
+%
+% 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 furhter 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 all of the float placement parameters
+% to completely permissive values. The standard values appear as comments.
+% \begin{macrocode}
+\def\@clearfloatplacement{%
+ \global\@topnum \maxdimen % \c@topnumber
+ \global\@toproom \maxdimen % \topfraction\@colht
+ \global\@botnum \maxdimen % \c@bottomnumber
+ \global\@botroom \maxdimen % \bottomfraction\@colht
+ \global\@colnum \maxdimen % \c@totalnumber
+%\global\@fpmin \z@ % \floatpagefraction\@colht
+ \global\@dbltopnum \maxdimen % \c@dbltopnumber
+ \global\@dbltoproom \maxdimen % \dbltopfraction\@colht
+ \global\@textmin \z@ % \@colht\advance \@textmin -\@dbltoproom
+ \global\@fpmin \z@ % \dblfloatpagefraction\textheight
+ \let\@testfp\@gobble
+ \appdef\@setfloattypecounts{\@fpstype16\advance\@fpstype\m@ne}%
+}%
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@doclearpage}
+% The \cmd\@doclearpage\ procedure is now obsoleted, as is \cmd\@makefcolumn, which it invoked.
+% \begin{macrocode}
+\let\@doclearpage\@undefined
+\let\@makefcolumn\@undefined
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\clr@top@firstmark}
+% \begin{macro}{\set@top@firstmark}
+% \begin{macro}{\@outputpage}
+% 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.
+% \LaTeX\ has exactly one procedure \cmd\@outputpage\ that does \cmd\shipout,
+% which is as it should be: we tailpatch it, and the job is done.
+% \begin{macrocode}
+\appdef\@outputpage{%
+ \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.
+%
+% \begin{macrocode}
+\def\@float#1{%
+ \@ifnextchar[{%}]{%Brace-matching klootch
+ \@yfloat\width@float{#1}%
+ }{%
+ \@ifxundefined@cs{fps@#1}{%
+ \edef\reserved@a{\noexpand\@yfloat\noexpand\width@float{#1}[\csname fps@\endcsname]}\reserved@a
+ }{%
+ \edef\reserved@a{\noexpand\@yfloat\noexpand\width@float{#1}[\csname fps@#1\endcsname]}\reserved@a
+ }%
+ }%
+}%
+\def\@dblfloat#1{%
+ \@ifnum{\pagegrid@col=\@ne}{%
+ \@float{#1}%
+ }{%
+ \@ifnextchar[{%}]{%Brace-matching klootch
+ \@yfloat\widthd@float{#1}%
+ }{%
+ \@ifxundefined@cs{fpsd@#1}{%
+ \edef\reserved@a{\noexpand\@yfloat\noexpand\widthd@float{#1}[\csname fpsd@\endcsname]}\reserved@a
+ }{%
+ \edef\reserved@a{\noexpand\@yfloat\noexpand\widthd@float{#1}[\csname fpsd@#1\endcsname]}\reserved@a
+ }%
+ }%
+ }%
+}%
+\def\@yfloat#1#2[#3]{%
+ \@xfloat{#2}[#3]%
+ \hsize#1\linewidth\hsize
+ \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\ trys to catch cases where the float placement options
+% are such that the float can never be placed.
+% \begin{macrocode}
+\def\end@float{%
+ \end@@float{%
+ \check@currbox@count
+ }%
+}%
+\def\end@dblfloat{%
+ \@ifnum{\pagegrid@col=\@ne}{%
+ \end@float
+ }{%
+ \end@@float{%
+ \@boxfpsbit\@currbox{1}\@ifodd\@tempcnta{\global\advance\count\@currbox\m@ne}{}%
+ \@boxfpsbit\@currbox{4}\@ifodd\@tempcnta{\global\advance\count\@currbox-4\relax}{}%
+ \global\wd\@currbox\textwidth % Klootch
+ \check@currbox@count
+ }%
+ }%
+}%
+\def\end@@float#1{%
+ \minipagefootnote@here
+%\minipagefootnotes
+ \@endfloatbox
+ #1%
+ \@ifnum{\@floatpenalty <\z@}{%
+ \@largefloatcheck
+ \@cons\@currlist\@currbox
+ \@ifnum{\@floatpenalty <-\@Mii}{%
+ \do@output@cclv{\@add@float}%
+ }{%
+ \vadjust{\do@output@cclv{\@add@float}}%
+ \@Esphack
+ }%
+ }{}%
+}%
+\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}%
+ }{}%
+ }{%
+ % Is a \marginpar
+ }%
+}%
+\providecommand\minipagefootnote@init{}%
+\providecommand\minipagefootnote@here{}%
+% \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
+ \advance \@pageht \vsize \advance \@pageht -\pagegoal % do not assume \holdinginserts is cleared!
+% \@ifvbox\@kludgeins{%
+% \@ifdim{\wd\@kludgeins=\z@}{%
+% \advance \@pageht \ht\@kludgeins
+% }{}%
+% }{}%
+% \@reinserts
+ \@addtocurcol % Commit an h float
+ }{%
+% \@reinserts
+ \@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.
+% \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%
+}%
+\AtBeginDocument{%
+ \@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$. 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}{%"40000000
+ \deadcycles\z@
+%\showbox\@cclv
+ \setbox\z@\box\@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
+ \setbox\z@\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{%
+ \setbox\z@\box\@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 regular output routine, it executes in two phases,
+% first with \cmd\holdinginserts\ set, then with it 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.
+% \begin{macrocode}
+\def\savecolumn@holding{%
+ \@if@exceed@pagegoal{\unvcopy\@cclv\setbox\z@\lastbox}{%
+ \setbox\z@\vbox{\unvcopy\@cclv\setbox\z@\lastbox}%
+ \outputdebug@sw{{\tracingall\scrollmode\showbox\z@}}{}%
+ \dimen@\ht\@cclv\advance\dimen@-\ht\z@
+ \dead@cycle@repair@protected\dimen@
+ }{%
+ \dead@cycle
+ }%
+}%
+% \end{macrocode}
+% 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).
+% 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{%
+ \@cclv@nontrivial@sw{%
+ \save@column
+ }{%
+ {\setbox\z@\box\@cclv}%
+ }%
+ \@ifvoid\footins{}{%
+ \outputdebug@sw{{\tracingall\scrollmode\showbox\footins}}{}%
+ \global\setbox\footins@saved\vbox{\unvbox\footins@saved\marry@baselines\unvbox\footins}%
+ \protect@penalty\save@column@insert@pen
+ }%
+}%
+\newbox\footins@saved
+% \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 havin the
+% message.
+% But if we came here via \cmd\penalty 10017, there might be an \cmd\insert\ node here as well, because
+% a footnote 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{%
+ \setbox\z@\box\@cclv %FIXME: what if \box\@cclv is not empty?
+ \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 (not the 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 %Implicit #2
+}%
+% \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.
+% \begin{macrocode}
+\def\execute@message@insert#1{%
+ \@execute@message\save@column@insert@pen{\setbox\footins\box\footins@saved#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
+% \hbox{\vrule\@height\z@\@width\z@\@depth\dimen@}%
+ \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}{% 10000 is a TeX magic number!
+ \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
+ \setbox\z@\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}
+% \begin{macro}{\move@insert@sw}
+% 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\move@insert@sw{\@ifnum{\holdinginserts=\z@}}%
+\def\toggle@insert#1#2{%
+ \@ifnum{\holdinginserts=\z@}{\hold@insertions#2}{\move@insertions#1}%
+}%
+% \end{macrocode}
+% \end{macro}
+% \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\footbox\ (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\@makecol\
+% is a good way to 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\footbox\ 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}{\footbox}
+% \begin{macrocode}
+\newbox\pagesofar
+\newbox\footbox
+% \end{macrocode}
+% \end{macro}
+% \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.
+% \begin{macrocode}
+\def\open@column@one#1{%
+ \unvbox\pagesofar
+ \gdef\thepagegrid{one}%
+ \global\pagegrid@col#1%
+ \global\pagegrid@cur\@ne
+ \set@colht
+%\set@colroom
+ \set@column@hsize\pagegrid@col
+}%
+% \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.
+% \begin{macrocode}
+\def\shut@column@one{%
+ \@makecol
+ \global\setbox\pagesofar\vbox{\unvbox\@outputbox\recover@footins}%
+ \set@colht
+%\set@colroom
+}%
+% \end{macrocode}
+%
+% 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.
+% \begin{macrocode}
+\def\float@column@one{%
+ \@makecol
+ \@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\setbox\z@\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\ of standard \LaTeX,
+% which has been retained (it is needed also in \cmd\output@column@mlt,
+% and in any case should remain as the sole procedure in \LaTeX\ where \cmd\shipout\ is performed).
+% It will be followed up with an output routine message to prepare a new column.
+% \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}
+% 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.
+%
+% \begin{macrocode}
+\def\open@column@mlt#1{%
+ \gdef\thepagegrid{mlt}%
+ \global\pagegrid@col#1%
+ \global\pagegrid@cur\@ne
+ \set@column@hsize\pagegrid@col
+ \set@colht
+%\set@colroom
+}%
+% \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\footbox\ 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.
+% \begin{macrocode}
+\def\shut@column@mlt{%
+ \@cclv@nontrivial@sw{%
+ \@makecol
+ \@ifnum{\pagegrid@cur<\pagegrid@col}{%
+ \expandafter\global\expandafter\setbox\csname col@\the\pagegrid@cur\endcsname\box\@outputbox
+ \global\advance\pagegrid@cur\@ne
+ }{}%
+ }{%
+ {\setbox\z@\box\@cclv}%
+ }%
+ \@ifnum{\pagegrid@cur>\@ne}{%
+ \csname balance@\the\pagegrid@col\endcsname
+ \grid@column{}%
+ \@combinepage
+ \@combinedblfloats
+ \global\setbox\pagesofar\box\@outputbox
+ }{}%
+ \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.
+% \begin{macrocode}
+\def\float@column@mlt{%
+ \@combinepage
+ \@combinedblfloats
+ \@outputpage
+ \global\pagegrid@cur\@ne
+ \protect@penalty\do@startpage@pen
+}%
+% \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\setbox\z@\lastbox
+ }{%
+ \unvbox\@cclv\setbox\z@\lastbox\unskip\null
+ }%
+ \protect@penalty\do@newpage@pen
+ \protect@penalty\do@endpage@pen
+ }{%
+ \unvbox\@cclv\setbox\z@\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.
+% \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@
+% \advance\dimen@-\topskip
+ \grid@column{}%{\dimen@}%
+ \@combinepage
+ \@combinedblfloats
+ \@outputpage
+ \global\pagegrid@cur\@ne
+ \protect@penalty\do@startpage@pen
+ }%
+}%
+% \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}
+% \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}{\col@}
+% \begin{macro}{\pagegrid@init}
+% We take over \LaTeX's \cmd\col@number\ and \cmd\@leftcolumn, which are obsolete.
+% 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\ exercises \cmd\newbox\ sufficiently to create the
+% boxes for holding the columns in the page grid.
+% \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}
+% \end{macro}
+%
+% \begin{macro}{\grid@column}
+% 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.
+%
+% \begin{macrocode}
+\def\grid@column#1{%
+ \global\setbox\@outputbox\vbox{%
+ \hb@xt@\textwidth{%
+ \vrule\@height\z@\@width\z@\@if@empty{#1}{}{\@depth#1}%
+ \pagegrid@cur\@ne
+ \append@column
+ \box@column\@outputbox
+ }%
+ \vskip\z@skip % FIXME: page depth!
+ }%
+}%
+% \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{v4.0rc1}{2001/06/18}
+% {Introoduce \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 beta 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.
+% \begin{macrocode}
+\def\append@column{%
+ \@ifnum{\pagegrid@cur<\pagegrid@col}{%
+ \expandafter\box@column\csname col@\the\pagegrid@cur\endcsname
+ \hfil
+ \vrule \@width\columnseprule
+ \hfil
+ \advance\pagegrid@cur\@ne
+ \append@column
+ }{%
+ }%
+}%
+\def\box@column#1{%
+ \raise\topskip
+ \hb@xt@\columnwidth{%
+ \dimen@\ht#1\@ifdim{\dimen@>\@colht}{\dimen@\@colht}{}%
+% \advance\dimen@-\topskip
+ \count@\vbadness\vbadness\@M
+ \dimen@ii\vfuzz\vfuzz\maxdimen
+ \outputdebug@sw{\saythe\@colht\saythe\dimen@}{}%
+ \vtop to\dimen@
+% \@ifdim{\ht#1>\textheight}{to\textheight}{}%
+ {\hrule\@height\z@
+ \unvbox#1%
+ \raggedcolumn@skip
+ }%
+ \vfuzz\dimen@ii
+ \vbadness\count@
+ \hss
+ }%
+}%
+\def\marry@baselines{%
+%{\tracingall\scrollmode\showlists}%
+%\skip@\baselineskip\advance\skip@-\topskip %FIXME: cannot assume \baselineskip nor \topskip
+ \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
+}%
+\AtBeginDocument{%
+ \@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 to \cmd\@outputbox.
+% \begin{macrocode}
+\def\@combinepage{%
+ \@ifvoid\pagesofar{}{%
+ \setbox\@outputbox\vbox{%
+ \unvbox\pagesofar
+ \marry@baselines
+ \unvbox\@outputbox
+ }%
+ }%
+ \@ifvoid\footbox{}{%
+ \setbox\@outputbox\vbox{%
+ \unvbox\@outputbox
+ \marry@baselines
+ \unvbox\footbox
+ }%
+ }%
+}%
+% \end{macrocode}
+% \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{v4.0rc1}{2001/06/18}
+% {Introoduce \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\@makecol; footnotes need help.
+%
+% 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?
+% Paticularly, \cmd\@colht\ is an artifact of the old way of doing things, where once it was set, it would never change.
+%
+% \begin{macrocode}
+\def\set@colht{%
+ \set@adj@textheight\@colht
+ \global\let\enlarge@colroom\@empty
+ \set@colroom
+}%
+\def\set@adj@textheight#1{%
+ #1\textheight
+ \def\@elt{\adj@page#1}%
+ \@booleantrue\firsttime@sw\@dbltoplist
+ \let\@elt\relax
+%\@ifvoid\pagesofar{}{%
+% \advance#1-\ht\pagesofar\advance#1-\dp\pagesofar
+%}%
+ \global#1#1\relax
+ \outputdebug@sw{\saythe#1}{}%
+}%
+\def\set@colroom{%
+ \set@adj@colht\@colroom
+ \@if@empty\enlarge@colroom{}{%
+ \global\advance\@colroom\enlarge@colroom\relax
+ }%
+ \outputdebug@sw{\saythe\@colroom}{}%
+ \@ifdim{\@colroom>\topskip}{}{%
+ \ltxgrid@info{Not enough room: \string\@colroom=\the\@colroom; increasing to \the\topskip}%
+ \@colroom\topskip
+ }%
+ \global\@colroom\@colroom
+ \set@vsize
+}%
+%
+\def\set@vsize{%
+ \global\vsize\@colroom
+ \outputdebug@sw{\saythe\vsize}{}%
+}%
+%
+\def\set@adj@colht#1{%
+ #1\@colht
+ \@ifvoid\pagesofar{}{%
+ \advance#1-\ht\pagesofar\advance#1-\dp\pagesofar
+ }%
+ \@ifvoid\footbox{}{%
+ \advance#1-\ht\footbox\advance#1-\dp\footbox
+ }%
+ \def\@elt{\adj@column#1}%
+ \@booleantrue\firsttime@sw\@toplist
+ \@booleantrue\firsttime@sw\@botlist
+ \let\@elt\relax
+ \outputdebug@sw{\saythe#1}{}%
+}%
+\def\adj@column#1#2{%
+ \advance#1-\ht#2%
+ \advance#1-\firsttime@sw{\textfloatsep\@booleanfalse\firsttime@sw}{\floatsep}%
+}%
+\def\adj@page#1#2{%
+ \advance#1-\ht#2%
+ \advance#1-\firsttime@sw{\dbltextfloatsep\@booleanfalse\firsttime@sw}{\dblfloatsep}%
+}%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\@outputpage}%
+% At the tail of \cmd\@outputpage, 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{%
+ \set@colht % FIXME: needed?
+ \@floatplacement % FIXME: needed?
+ \@dblfloatplacement % FIXME: needed?
+}%
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{balance@2}
+% 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.
+% \begin{macrocode}
+\@namedef{balance@2}{%
+ \expandafter\balance@two\csname col@1\endcsname\@outputbox
+ % Avoid a bug by preventing a restore when leaving this group
+ \global\setbox\csname col@1\endcsname\box\csname col@1\endcsname
+ \@ifvoid\footbox{}{%
+ \global\setbox\footbox\vbox{%
+ \setbox\z@\box\@tempboxa
+ \let\recover@footins\relax
+ \balance@two\footbox\@tempboxa
+ \hb@xt@\textwidth{\box\footbox\hfil\box\@tempboxa}%
+ }%
+ }%
+}%
+% \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, 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 balance 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 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.
+% \begin{macrocode}
+\def\balance@two#1#2{%
+ \outputdebug@sw{{\tracingall\scrollmode\showbox#1\showbox#2}}{}%
+ \setbox\@ne\vbox{%
+ \@ifvoid#1{}{%
+ \unvcopy#1\recover@footins
+ \@ifvoid#2{}{\marry@baselines}%
+ }%
+ \@ifvoid#2{}{%
+ \unvcopy#2\recover@footins
+ }%
+ }%
+ \dimen@\ht\@ne\divide\dimen@\tw@
+ \dimen@i\dimen@
+ \vbadness\@M
+ \vfuzz\maxdimen
+ \loopwhile{%
+ \dimen@i=.5\dimen@i
+ \outputdebug@sw{\saythe\dimen@\saythe\dimen@i\saythe\dimen@ii}{}%
+ \setbox\z@\copy\@ne\setbox\tw@\vsplit\z@ to\dimen@
+ \setbox\z@ \vbox{%
+ \unvcopy\z@
+ \setbox\z@\vbox{\unvbox\z@ \setbox\z@\lastbox\aftergroup\vskip\aftergroup-\expandafter}\the\dp\z@\relax
+ }%
+ \setbox\tw@\vbox{%
+ \unvcopy\tw@
+ \setbox\z@\vbox{\unvbox\tw@\setbox\z@\lastbox\aftergroup\vskip\aftergroup-\expandafter}\the\dp\z@\relax
+ }%
+ \dimen@ii\ht\tw@\advance\dimen@ii-\ht\z@
+ \@ifdim{\dimen@i>.5\p@}{%
+ \advance\dimen@\@ifdim{\dimen@ii<\z@}{}{-}\dimen@i
+ \true@sw
+ }{%
+ \@ifdim{\dimen@ii<\z@}{%
+ \advance\dimen@\tw@\dimen@i
+ \true@sw
+ }{%
+ \false@sw
+ }%
+ }%
+ }%
+ \outputdebug@sw{\saythe\dimen@\saythe\dimen@i\saythe\dimen@ii}{}%
+ \@ifdim{\ht\z@=\z@}{%
+ \@ifdim{\ht\tw@=\z@}{%
+ \true@sw
+ }{%
+ \false@sw
+ }%
+ }{%
+ \true@sw
+ }%
+ {%
+ }{%
+ \ltxgrid@info{Unsatifactorily balanced columns: giving up}%
+ \setbox\tw@\box#1%
+ \setbox\z@ \box#2%
+ }%
+ \setbox\tw@\vbox{\unvbox\tw@\vskip\z@skip}%
+ \setbox\z@ \vbox{\unvbox\z@ \vskip\z@skip}%
+ \set@colroom
+ \dimen@\ht\z@\@ifdim{\dimen@<\ht\tw@}{\dimen@\ht\tw@}{}%
+ \@ifdim{\dimen@>\@colroom}{\dimen@\@colroom}{}%
+ \outputdebug@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{{\tracingall\scrollmode\showbox#1\showbox#2}}{}%
+}%
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\recover@footins}
+% The procedure \cmd\recover@footins\ is the utility procedure for recovering the footnotes
+% from the bottom of a column. It is used when the page grid is changed, so that footnotes can be
+% set at the bottom of the shipped out page.
+% \begin{macrocode}
+\def\recover@footins{%
+ \skip\z@ \lastskip\unskip
+ \skip\@ne\lastskip\unskip
+ \setbox\z@\lastbox
+ \@ifvbox\z@{%
+ \setbox\z@\vbox{%
+ \unvbox\z@
+ \setbox\z@\lastbox
+% \outputdebug@sw{{\tracingall\showbox\lastbox}}{}%
+ \@ifvoid\z@{}{%
+ \global\setbox\footbox\vbox{%
+ \unvbox\footbox
+ \@ifvbox\z@{%
+ \unvbox\z@
+ }{%
+ \box\z@
+ }%
+ }%
+ }%
+ }%
+ }{}%
+ \outputdebug@sw{{\tracingall\scrollmode\showbox\footbox}}{}%
+}%
+% \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}
+\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
+}%
+\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
+ \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
+ \tabskip\LTleft\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
+ \let\LT@LL@FM@cr\@tabularcr
+ }{%
+ \advance\@tempdima\extrarowheight
+ \col@sep\tabcolsep
+ \let\@startpbox\LT@startpbox
+ \let\LT@LL@FM@cr\@arraycr
+ }%
+%
+ \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}.
+%
+%FIXME: the following is no longer true:
+%% Note that it is not enough to define the environment itself; we also have to create the corresponding
+%% \cmd\output\ routine procedures, which provide for continued footers and headers
+%% (the very feature of \env{longtable} requiring support in the output routine).
+%
+%% This same consideration would arise in defining any syntactic extension to \env{longtable}, because
+%% the environment name itself is exposed in the output routine.
+%
+% \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
+ }%
+% \expandafter\let\csname output@init@longtable*\endcsname\output@init@longtable
+% \expandafter\let\csname output@prep@longtable*\endcsname\output@prep@longtable
+% \expandafter\let\csname output@post@longtable*\endcsname\output@post@longtable
+ }{}%
+}%
+% \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}{% we have the leftmost column of a verso page
+ % insert the current top-level continued head
+ }%
+ }%
+}%
+% \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}
+% 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%
+ }%
+ }{%
+ %Successfully committed float(s)
+ }%
+ \global\let\@deferlist@postshipout\@empty
+ }%
+}%
+\def\@fltstk{%
+ \@latex@warning{A float is stuck (cannot be placed without \string\clearpage)}%
+}%
+\appdef\@outputpage{%
+ \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{%
+% \ltxgrid@info{#1, attempting rectification}%
+ \penalty-\pagebreak@pen
+ \protect@penalty\do@forcecolumn@pen
+ }{%
+% \ltxgrid@info{#1}%
+ }%
+}%
+\@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
+%\unvbox\@cclv
+%\vfil
+%\penalty-\pagebreak@pen
+ \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 is questionable.
+% Instead, people should enlarge the entire spread.
+%
+% 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}{% OK to adjust this page
+ \gdef\enlarge@colroom{#2}%
+ \true@sw
+ }{% Can only adjust this column; give up
+ \ltxgrid@warn{Too late to enlarge this page; move the command to the first column.}%
+ \false@sw
+ }%
+ }{% Unknown page grid
+ \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
+ }{%
+ % Could not adjust this page
+ }%
+}%
+\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}
+% The procedures that build \cmd\@outputbox\ just before a page is shipped out by \cmd\@outputpage\ are:
+% \cmd\@makecol,
+% \cmd\@combinepage, and
+% \cmd\@combinedblfloats.
+% We headpatch \cmd\@outputpage\ to make the \cmd\@outputbox\ be of fixed height.
+% \begin{macrocode}
+\@booleantrue\textheight@sw
+\prepdef\@outputpage{%
+ \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}
+%
+% \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
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \section{End of the \file{ltxgrid} {\sc docstrip} module}
+% Here ends the module.
+% \begin{macrocode}
+%</ltxgrid-krn>
+% \end{macrocode}
+%
+% \Finale
+% %Here ends the programmer's documentation.
+% \endinput
+%
+\endinput
+%%EOF