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