% \iffalse meta-comment % % % This file is part of the Standard LaTeX `Tools Bundle'. % ------------------------------------------------------- % % It may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % https://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % The list of all files belonging to the LaTeX `Tools Bundle' is % given in the file `manifest.txt'. % % \fi % % \iffalse This is a METACOMMENT % %% Package `multicol' to use with LaTeX2e %% Copyright 1989-2024 Frank Mittelbach %% %% In addition to the terms of LPPL any distributed version %% (unchanged or modified) of multicol has to keep the statement %% about the moral obligation for using multicol. In case of major %% changes where this would not be appropriate the author of the %% changed version should contact the copyright holder. %% %% %% Moral obligation for using multicol: %% ------------------------------------ %% %% Users of multicol who wish to include or use multicol or a modified %% version in a proprietary and commercially market product are asked %% under certain conditions (see below) for the payment of a license %% fee. The size of this fee is to be determined, in each instance, %% by the commercial user, depending on his/her judgment of the value of %% multicol for his/her product. %% %% %% The conditions for this are as follows: %% %% The producer of a proprietary and commercially market product %% that involves typesetting using multicol is asked to determine %% the value of a license fee for using multicol if %% %% - the product is a document and the producer has decided to %% include multicol to typeset (parts of) the document or has %% directed the author of the document to include multicol (for %% example, by providing a class file to be used by the author) %% %% - the product is a LaTeX class or package that includes multicol %% %% %% There is no moral obligation in case %% %% - the product is a document but producer has not directed %% the author to include multicol (in that case the moral obligation %% lies with the author of the document) %% %% - the product does not involve typesetting, e.g., consists, for %% example, of distributing multicol and its documentation. %% %% - the product is not proprietary, i.e., is made available as free %% software itself (which doesn't prohibit its commercial marketing) %% %% - multicol is used for non-commercial purposes %% %% %% Determining a license fee might result in a license fee of zero %% (i.e., no payment) in case a producer has determined that the use %% of multicol has no enhancing effect on the product. This is a %% plausible scenario, i.e., in the above two cases the producer is %% only asked to evaluate the value of multicol for the product %% not for the payment of a license fee per se (which might or might %% not follow from this evaluation). %% %% The license fee, if any, can be paid either to the LaTeX fund %% (see ltx3info.txt in the base LaTeX distribution) or to the author of %% the program who can be contacted at %% %% Frank.Mittelbach@latex-project.org %% %<*dtx> \ProvidesFile{multicol.dtx} % % % For any rollback before 2017 load the 2017 version and hope for the best: %\DeclareRelease{}{1994-06-01}{multicol-2017-04-11.sty} % %\DeclareRelease{}{2017-04-11}{multicol-2017-04-11.sty} %\DeclareRelease{v1.8}{2019-10-01}{multicol-2019-10-01.sty} %\DeclareRelease{v1.9}{2021-11-15}{multicol-2024-05-23.sty} %\DeclareCurrentRelease{}{2021-11-15} % %\ProvidesPackage{multicol} % \ProvidesFile{multicol.drv} % \fi % \ProvidesFile{multicol.dtx} [2024/11/21 v2.0a multicolumn formatting (FMi)] % % % % % \changes{v1.9c}{2021/11/30}{Added rollback to v1.8} % \changes{v1.5n}{1997/06/05}{Applied improvement of documentation, % kindly done by Robin Fairbairns.} % \changes{v1.4h}{1992/06/04}{Added mark tracing with % tracingmulticols$\ge2$} % \changes{v1.4a}{1992/02/11}{Added support for multicol in inner mode} % \changes{v1.0d}{1989/05/17}{All lines shortened to 72 or less.} % \changes{v1.0e}{1989/06/21}{Redefinition of description env. to use % \cs{descriptionmargin}\quotechar=5pt % in documentation.} % \changes{v1.0f}{1989/07/11}{Changed \cs{z@} to 0pt in redefinition of % description.} % \changes{v1.1a}{1989/09/20}{\cs{multicolssep} changed to \cs{multicolsep}.} % \changes{v1.9b}{2021/10/22}{Swap names \cs{mult@gfirstbox} % and \cs{mult@firstbox} (gh/701)} % % \def\description{\list{}{\labelwidth 0pt \leftmargin\descriptionmargin % \itemindent-\leftmargin \let\makelabel\descriptionlabel}} % \newdimen\descriptionmargin \descriptionmargin=5pt % % \DoNotIndex{\@M,\@Mi,\@bsphack,\@cclv,\@colht,\@currlist,\@deferlist} % \DoNotIndex{\@elt,\@esphack,\@floatplacement} % \DoNotIndex{\@ifundefined,\@ifnextchar,\@makecol} % \DoNotIndex{\@ne,\@outputpage,\@scolelt,\@spaces,\@tempb,\@tempcnta} % \DoNotIndex{\@width} % \DoNotIndex{\addvspace,\advance,\allowbreak} % \DoNotIndex{\baselineskip,\begingroup,\box,\columnsep,\copy,\count} % \DoNotIndex{\count@,\def,\dimen@,\divide,\docdate} % \DoNotIndex{\edef,\eject,\egroup,\else,\endgroup,\endinput} % \DoNotIndex{\fi,\fileversion,\filedate} % \DoNotIndex{\gdef,\global} % \DoNotIndex{\hbox,\hfil,\hrule,\ht,\hss} % \DoNotIndex{\ifdim,\ifnum,\ifvoid,\ignorespaces,\insert,\immediate} % \DoNotIndex{\let,\loop} % \DoNotIndex{\@maxdepth,\message,\multiply} % \DoNotIndex{\newbox,\newcount,\newdimen,\newskip,\number,\newpage} % \DoNotIndex{\outputpenalty,\p@,\penalty} % \DoNotIndex{\relax,\repeat,\setbox,\skip,\space,\splitmaxdepth} % \DoNotIndex{\splittopskip,\string,\sixt@@n} % \DoNotIndex{\the,\thepage,\thr@@,\topskip,\tw@,\typeout} % \DoNotIndex{\unvbox,\vbox,\vfill,\vsplit,\voidb@x,\vrule} % \DoNotIndex{\write,\wd} % \DoNotIndex{\z@} % % \MakeShortVerb{\|} % \newcommand{\mc}{\textsf{multicols}} % \newcommand{\TUB}{{\sl TUGboat\/}} % \newcommand{\TB}{{\sl\TeX book\/}} % % % \setcounter{StandardModuleDepth}{2} % \setcounter{collectmore}{3} % % \GetFileInfo{multicol.dtx} % \title{An environment for multicolumn output\thanks{This file % has version number \fileversion, last % revised \filedate.}% % \thanks{Note: This package is released under terms which affect % its use in commercial applications. Please see the details at % the top of the source file.}} % \author{Frank Mittelbach\\ % {\rm Email:} see top of the source file} % \date{Printed \today} % % \MaintainedByLaTeXTeam{tools} % \maketitle % % \begin{abstract} % This article describes the use and the implementation of the \mc{} % environment. This environment allows switching between % one and multicolumn format on the same page. Footnotes are handled % correctly (for the most part), but will be placed at the bottom of % the page and not under each column. \LaTeX{}'s float mechanism, % however, is partly disabled in this implementation. At the % moment only page-wide floats (i.e., star-forms) can be used within % the scope of the environment. % \end{abstract} % % \begin{multicols}{3}[\section*{Preface to versions 1.9 + 2.0}] % % Version 1.9 added tagging support and also a number of smaller % enhancements, such as an optional argument to % \cs{columnbreak} to allow for conditional breaks instead of % forced ones. The min column depth was also made customizable % (previously it was hardwired to the depth of \enquote{p}) to support % special cases and in particular languages that do not have % characters with any noticeable depth such as, for example, Japanese. % % Verson 2.0 then simplified and improved the mark handling, by % fully supporting the new mark mechanism of \LaTeX. % % \end{multicols} % % % % \begin{multicols}{3}[\section*{Preface to version 1.8}] % The 1.8 release improves on the balancing approach. If due to a % limited number of break points (e.g., due to large objects) the % balanced columns exceed the available vertical space, then % balancing is canceled and a normal page is produced first. Some % overflow is allowed (controlled by the parameter % |\maxbalancingoverflow| which defaults to 12pt). This ensures % that we only cut a normal page if we get enough material carried % over to next page. % % Also added was support for |\enlargethispage|. This means it is % now possible to request a page to be artificially enlarged or % shortened. Note that if you enlarge pages by more than one line % you may have to increase the \textsf{collectmore} counter value to % ensure that enough material is being picked up. % % This command was used on the second page of this manual to shorten % it by one line, in order to get rid of a number of widow lines on % the following pages. % % There are also some small enhancements to the balancing algorithm % including a ways to require a minimum number of rows in the result. % % Finally, version 1.8 adds the command |\docolaction| to help with % more complicated actions that depend on the current column. This % command expects 3 arguments: code that is executed if we are in % the ``first'' column, code to execute if we end up in any % ``middle'' column (if there are more than two) and finally code to % execute if we are in the ``last'' column. Thus %\begin{verbatim} % \docolaction{first} % {middle}{last} %\end{verbatim} % would typeset a different word depending the type of column this % code is executed. Using it like this is probably pointless, but % you can imagine applications like writing something into the % nearest margin, etc. % % As this feature needs at least two \LaTeX{} runs to produce correct % results and as it adds to the processing complexity it is only % made available if one add the option \texttt{colaction} when % loading the package. % % \end{multicols} % % % \begin{multicols}{3}[\section*{Preface to version 1.7 % (right to left support)}] % The 1.7 release adds support for languages that are typeset % right-to-left. For those languages the order of the columns on the page % also need to be reversed---something that wasn't supported before. The next % paragraph demonstrates the result (as it is typeset as if we are writing % in a left-to-right language--- so read the rightmost column % first). The change is initialized via % |\RLmulticolcolumns| and returning to left-right (default) % is done via |\LRmulticolcolumns|. % \end{multicols} % % \RLmulticolcolumns % % \begin{multicols}{3} % Right-to-left typesetting will only reverse the column orders. Any % other support needed will have to be provided by other means, % e.g., using appropriate fonts and reversing the writing directions % within the columns. As footnotes are typeset in full measure the % footnote rule needs to be redefined as if they are below a single % column, i.e., using |\textwidth| not |\columnwidth|. For example: %\begin{verbatim} %\renewcommand \footnoterule{% % \kern-3pt\hbox to\textwidth % {\hskip .6\textwidth % \hrulefill }% % \kern2.6pt} %\end{verbatim} % \end{multicols} % % \LRmulticolcolumns % % \begin{multicols}{3}[\section*{Preface to version 1.5 + 1.6}] % \hbadness=10000 % The 1.5 release contains two major changes: \mc{} will now % support up to 10 columns and two more tuning possibilities have % been added to the balancing routine. The balancing routine now % checks the badness % of the resulting columns and rejects solutions that are larger % than a certain threshold. % At the same time \mc{} has been upgraded to run under \LaTeXe{}. % % Later changes to 1.5 include |\columnbreak| and |multicols*|. % % For version 1.6 micro-spacing around the boxes produced by \mc{} % has been improved to allow for baseline-grid typesetting. % \end{multicols} % % % \setcounter{collectmore}{2} % \begin{multicols}{3}[\section{Introduction}] % \hbadness=10000 % Switching between two-column and one-column layout is possible in % \LaTeX{}, but every use of |\twocolumn| or |\onecolumn| % starts a new page. Moreover, the last page of two-column output % isn't balanced and this often results in an empty, or nearly % empty, right column. When I started to write macros for % \textsf{doc.sty} (see ``The \texttt{doc}--Option'', \TUB\ % volume 10~\#2, pp.~245--273) I thought that it would be nice to % place the index % on the same page as the bibliography. And balancing the last page % would not only look better, it also would save space; provided of % course that it is also possible to start the next article on the % same page. Rewriting the index environment was comparatively easy, % but the next goal, designing an environment which takes care of % footnotes, floats, etc., was a harder task. It took me a whole % weekend\footnote{I started with the algorithm given in the \TeX % book on page 417. Without this help a weekend would not have been % enough. (This remark was made in the documentation of the initial % release, since then several hundreds more hours went into % improving the original code.)} to get together the few lines of % code below and there is % still a good chance that I missed something after all. % % Try it and, hopefully, enjoy it; and {\em please\/} direct bug % reports and suggestions back to Mainz. % \end{multicols} % % % \setcounter{collectmore}{0} % \begin{multicols}{3}[\section{The User Interface}] % \hbadness=10000 % To use the environment one simply says\\*[2mm] % \hspace*{2mm}|\begin{multicols}{|\meta{number}|}| % \hspace*{12mm}\meta{multicolumn text}\\ % \hspace*{2mm}|\end{multicols}|\\[2mm] % where \meta{number} is the required number of columns and %^^A\meta{multicolumn text} % $\langle${\it multi\-column text\/}$\rangle$ may contain arbitrary % \LaTeX{} commands, except that floats and marginpars are not % allowed in the current implementation\footnote{This is dictated by % lack of time. To implement floats one has to reimplement the % whole \LaTeX{} output routine.}. % % \enlargethispage{-1\baselineskip} % % \DescribeMacro\premulticols % As its first action, the \textsf{multicols} environment measures the % current page to determine whether there is enough room for some % portion of multicolumn output. This is controlled by the % \meta{dimen} variable |\premulticols| which can be changed by % the user with ordinary \LaTeX{} commands. % \DescribeMacro\multicolsep % If the space is less than |\premulticols|, a new page is % started. Otherwise, a |\vskip| of |\multicolsep| is % added.\footnote{Actually the added space may be less because we use % \cs{addvspace} (see the \LaTeX{} manual for further % information about this command).} % % \DescribeMacro\postmulticols % When the end of the \mc{} environment is encountered, an % analogous mechanism is employed, but now we test whether there is a % space larger than |\postmulticols| available. Again we add % |\multicolsep| or start a new page. % % It is often convenient to spread some text over all columns, just % before the multicolumn output, without any page break in between. To % achieve this the \mc{} environment has an optional second % argument which can be used for this purpose. For example, the text % you are now reading was started with % \begin{verbatim} % \begin{multicols}{3} % [\section{The User % Interface}] ... %\end{verbatim} % If such text is unusually long (or short) the value of % |\premulticols| might need adjusting to prevent a bad page % break. We therefore provide a third argument which can be used to % overwrite the default value of |\premulticols| just for this % occasion. So if you want to combine some longer single column text % with a multicols environment you could write % \begin{verbatim} % \begin{multicols}{3} % [\section{Index} % This index contains ...] % [6cm] % ... %\end{verbatim} % % % \DescribeMacro\columnsep % The space between columns is controlled by the length parameter % |\columnsep|. The width for the individual columns is automatically % calculated from this parameter and the current |\linewidth|. In this % article a value of \textsf{\the\columnsep} was used. % % % \DescribeMacro\columnseprule % Separation of columns with vertical rules is achieved by setting the % parameter |\columnseprule| to some positive value. In this % article a value of \textsf{.4pt} was used. % % \DescribeMacro\columnseprulecolor % The color of the rules separating the columns can be specified through % |\columnseprulecolor|. The default value is |\normalcolor|. % % \DescribeMacro\multicolbaselineskip % Since narrow columns tend to need adjustments in interline spacing % we also provide a \meta{skip} parameter called % |\multicolbaselineskip| which is added to the % |\baselineskip| parameter inside the \mc{} % environment. Please use this parameter with care or leave it alone; % it is intended only for package file designers since even small % changes might produce totally unexpected changes to your document. % % % \subsection{Balancing columns} % % % Besides the previously mentioned parameters, some others are % provided to influence the layout of the columns generated. % % Paragraphing in \TeX{} is controlled by several parameters. One of % the most important is called |\tolerance|: this controls the % allowed `looseness' (i.e.\ the amount of blank space between words). % Its default value is 200 (the \LaTeX{} |\fussy|) which is too % small for narrow columns. % Setting it to \texttt{10000} (a.k.a.\ $\infty$) means arbitrary bad % lines are possible. With that setting \LaTeX{} will make most lines % perfect but intermix them with really bad lines. This was the % setting originally used by \cs{sloppy} (nowadays it is a bit more % cautious and used \texttt{9999} which makes a huge % difference).\footnote{Look at the next paragraph, it was set with % the \cs{tolerance}\texttt{=10000}.} % % \begin{sloppypar}\tolerance=10000 % \DescribeMacro\multicoltolerance \DescribeMacro\multicolpretolerance % We therefore use a |\multicoltolerance| parameter for the % |\tolerance| value inside the \mc{} environment. Its default value % is 9999 which is less than infinity but `bad' enough for most % paragraphs in a multicolumn environment. Changing its value should % be done outside the \mc{} environment. Since |\tolerance| is set % to |\multicoltolerance| at the beginning of every \textsf{multicols} % environment one can locally overwrite this default by assigning % \cs{tolerance}\texttt{=}\meta{desired value}. There also exists a % |\multicolpretolerance| parameter holding the value for % |\pretolerance| within a \mc{} environment. Both parameters are % usually used only by package or class designers. % \end{sloppypar} % % Generation of multicolumn output can be divided into two parts. In % the first part we are collecting material for a page, shipping it % out, collecting material for the next page, and so on. As a second % step, balancing will be done when the end of the \mc{} environment % is reached. % In the first step \TeX{} might consider more material whilst % finding the final column content than it actually uses when shipping out the % page. This might cause a problem if a footnote is encountered in % the part of the input considered, but not used, on the current page. % In this case the footnote might show up on the current page, while the % footnotemark corresponding to this footnote might be set on the next % one.\footnote{The reason behind this behavior is the asynchronous % character of the \TeX{} {\it page\_builder}. % However, this % could be avoided by defining very complicated output % routines which don't use \TeX{} primitives like % \cs{insert} but do everything by hand. % This is clearly beyond the scope of a weekend problem.} % Therefore the \mc{} environment gives a warning % message\footnote{This message will be generated even if there are no % footnotes in this part of the text.} whenever it is unable to use % all the material considered so far. % % If you don't use footnotes too often the chances of something % actually going wrong are very slim, but if this happens you can help % \TeX{} by using a |\pagebreak| command in the final document. % Another way to influence the behavior of \TeX{} in this respect is % given by the counter variable `\textsf{collectmore}'. If you use the % |\setcounter| declaration to set this counter to \meta{number}, % \TeX{} will consider \meta{number} more (or less) lines before % making its final decision. So a value of $-1$ may solve all your % problems at the cost of slightly less optimal columns. % % % In the second step (balancing columns) we have other bells and % whistles. First of all you can say |\raggedcolumns| if you % don't want the bottom lines to be aligned. % The default is |\flushcolumns|, so \TeX{} will normally try to % make both % the top and bottom baselines of all columns align. % % If there is only a small amount of material available for balancing % then you may end up with very few lines per column. In an extreme % case there may be only one line which looks distinctly odd. In that % case it might be better to have more material distributed to the % earlier columns even if that means that later columns are empty or % partially empty. This is controlled through the counter % `\textsf{minrows}' (default 1). If set to a higher value then the % balancing will have at least that many rows in the first column (and % also all further columns until it runs outs of material). % % Additionally you can set another counter, the `\textsf{unbalance}' % counter, to some positive \meta{number}. This will make all but the % right-most column \meta{number} of lines longer than they would % normally have been. `Lines' in this context refer to normal text % lines (i.e.\ one |\baselineskip| apart); thus, if your columns % contain displays, % for example, you may need a higher \meta{number} % to shift something from one column into another. A negative value can make sense if % you have set \textsf{minrows} and want to locally adjust that. % % Unlike `\textsf{collectmore},' the `\textsf{unbalance}' counter is reset % to zero at the end of the environment so it only applies to one % \mc{} environment. % % The two methods may be combined but I suggest using these features % only when fine tuning important publications. % % Two more general tuning possibilities were added with version~1.5. % \TeX{} allows to measure the badness of a column in terms of an % integer value, where 0 means optimal and any higher value means a % certain amount of extra white space. 10000 is considered to be % infinitely bad (\TeX{} does not distinguish any further). In addition % the special value 100000 means overfull (i.e., the column contains % more text than could possibly fit into it). % % The new release now measures every generated column and ignores % solutions where at least one column has a badness being larger than % the value of the counter \textsf{columnbadness}. The default value for % this counter is 10000, thus \TeX{} will accept all solutions except % those being overfull. % By setting the counter to a smaller value you can force the algorithm % to search for solutions that do not have columns with a lot of white % space. % % However, if the setting is too low, the algorithm may not find any % acceptable solution at all and will then finally choose the extreme % solution of placing all text into the first column. % % Often, when columns are balanced, it is impossible to find a solution % that distributes the text evenly over all columns. If that is the case % the last column usually has less text than the others. In the earlier % releases this text was stretched to produce a column with the same % height as all others, sometimes resulting in really ugly looking % columns. % % In the new release this stretching is only done if the badness of % the final column is not larger than the value of the counter % \textsf{finalcolumnbadness}. The default setting is 9999, thus preventing % the stretching for all columns that \TeX{} would consider infinitely % bad. In that case the final column is allowed to run short which gives % a much better result. % % And there are two more parameters of some experimental nature, one % called |\multicolovershoot| the other |\multicolundershoot|. They % control the amount of space a column within the \mc{} environment is % allowed to be ``too full'' or ``too short'' without affecting the % column badness. They are set to 0pt and 2pt, respectively. % % Finally, when doing the balancing at the end, columns may become % higher than the remaining available space. In that case the % algorithm aborts and instead generates a normal page. However, if the % amount is not too large, e.g., a line or so, then it might be better to % keep everything on the same page instead of starting a new page with % just one line after balancing. So the parameter % |\maxbalancingoverflow| governs this process: only when the excess % gets larger than its value balancing is aborted. % % \subsection{Not balancing the columns} % % Although this package was written to solve the problem of balancing % columns, I got repeated requests to provide a version where all % white space is automatically placed in the last column or % columns. Since version v1.5q this now exists: if you use % \texttt{multicols*} instead of the usual environment the columns on % the last page are not balanced. Of course, this environment only % works on top-level, e.g., inside a box one has to balance to % determine a column height in absence of a fixed value. % % % \subsection{Manually breaking columns} % % Another request often voiced was: ``How do I tell \LaTeX{} that it % should break the first column after this particular line?''. The % |\pagebreak| command (which works with the two-column option of % \LaTeX{}) is of no use here since it would end the collection phase % of \mc{} and thus all columns on that page. So with version 1.5u % the |\columnbreak| command was added. If used within a paragraph it % marks the end of the current line as the desired breakpoint. You can % observe its effect on % the previous page where three lines of text have been artificially % forced into the second column (resulting in some white % space between paragraphs in the first column). % % From version 1.9 onwards \cs{columnbreak} accepts an optional % argument (just like \cs{pagebreak}) in which you can specify the % desirability to break the column at that point: supported values are % \texttt{0} (slightly desirable) to \texttt{4} (forced). % This version also adds \cs{newcolumn} % which forces a column break but runs the column short (comparable to % \cs{newpage}). % % \subsection{Floats inside a \mc{} environment} % % Within the \mc{} environment the usual star float commands are % available but their function is somewhat different as in the % two-column mode of standard \LaTeX. Stared floats, e.g., % \texttt{figure*}, denote page wide floats that are handled in a similar % fashion as normal floats outside the \mc{} environment. However, % they will never show up on the page where they are encountered. In % other words, one can influence their placement by specifying a % combination of \texttt{t}, \texttt{b}, and/or \texttt{p} in their optional % argument, but \texttt{h} doesn't work because the first possible place % is the top of the next page. One should also note, that this means % that their placement behavior is determined by the values of % |\topfraction|, etc.\ rather than by |\dbl...|. % % % \subsection{Support for right-to-left typesetting} % % In right-to-left typesetting the order of the columns on the page % also need to be reversed, i.e., the first column has to appear on the far % right and the last column on the left. This is supported through the % commands |\RLmulticolcolumns| (switching to right-to-left typesetting) % and |\LRmulticolcolumns| (switching to left-to-right typesetting) the % latter being the default. % % \subsection{Warnings} % % Under certain circumstances the use of the \mc{} environment may % result in some % warnings from \TeX{} or \LaTeX{}. Here is a list % of the important ones and the possible cause: % \begin{description} % % \item[] {\hspace*{-\labelsep}\tt Underfull \string\hbox\space % (badness ...)} % % As the columns are often very narrow \TeX{} wasn't able to find a % good way to break the paragraph. Underfull denotes a loose line but % as long as the badness value is below $10000$ the result is probably % acceptable. % % \item[] % {\hspace*{-\labelsep}\tt Underfull \string\vbox\space ... while % \string\output\space is active} % % If a column contains a character with an unusual depth, for % example a `(', in the bottom line then this message may show up. It % usually has no significance as long as the value is not more than a % few points. % % \item[] {\hspace*{-\labelsep}\tt LaTeX Warning: I moved some lines % to the next page} % % As mentioned above, \mc{} sometimes screws up the footnote % numbering. As a precaution, whenever there is a footnote on a % page where \mc{} had to leave a remainder for the following % page this warning appears. Check the footnote numbering on this % page. If it turns out that it is wrong, you have to manually break % the page using |\newpage| or |\pagebreak[..]|. % % \item[] {\hspace*{-\labelsep}\tt Floats and marginpars not allowed % inside `multicols' environment!} % % This message appears if you try to use the |\marginpar| command or % an unstarred version of the \textsf{figure} or \textsf{table} environment. % Such floats will disappear! % % \item[] {\hspace*{-\labelsep}\tt Very deep columns! % Grid alignment might be broken} % % This message can only appear if the option \texttt{grid} was % chosen. In that case it will show up if a column has a very large % depth so that \mc{} is unable to back up to its baseline. This % is only relevant if one tries to produce a document where all % text lines are aligned at an invisible grid, something that % requires careful adjustment of many parameters and macros, e.g., % heading definitions. % % \end{description} % % % \subsection{Tracing the output} % % To understand the reasoning behind the decisions \TeX{} makes when % processing a \mc{} environment, a tracing mechanism is provided. % If you set the counter `\texttt{tracingmulticols}' % to a positive \meta{number} you then % will get some tracing information on the terminal and in the % transcript file: % \begin{description} % \item[$\meta{number}=1$.] \TeX{} will now tell you, whenever it % enters or leaves a \mc{} environment, the number of columns it % is working on and its decision about starting a new page before % or after the environment. % \item[$\meta{number}=2$.] % In this case you also get information from the balancing routine: % the heights tried for the left and right-most columns, % information about shrinking if the |\raggedcolumns| % declaration is in force and the value of the `\textsf{unbalance}' % counter if positive. % \item[$\meta{number}= 3$.] Setting \meta{number}\pagebreak[2] to % this value will additionally trace the mark handling % algorithm. It will show what marks are found, what marks are % considered, etc. To fully understand this information you will % probably have to read carefully through the implementation. % \item[$\meta{number}\geq 4$.] Setting \meta{number}\pagebreak[2] to % such a high value will additionally place an |\hrule| into your % output, separating the part of text which had already been % considered on the previous page from the rest. Clearly this % setting should {\em not\/} be used for the final output. It will % also activate even more debugging code for mark handling. % \end{description} % % % \end{multicols} % % \begin{multicols}{3}[\section{Prefaces to older versions} % \subsection{Preface to version 1.4}] % \hbadness=10000 % Beside fixing some bugs as mentioned in the \textsf{multicol.bug} file % this new release enhances the \mc{} environment by allowing for % balancing in arbitrary contexts. It is now, for example, possible % to balance text within a \mc{} or a \textsf{minipage} as shown in % \ref{tab:newcmds} where a \textsf{multicols} environment within a % \textsf{quote} environment was used. It is now even possible to nest % \mc{} environments. % % The only restriction to such inner \mc{} environments (nested, or % within \TeX's internal vertical mode) is that such variants will % produce a box with the balanced material in it, so that they can % not be broken across pages or columns. % % Additionally I rewrote the algorithm for balancing so that it will % now produce slightly better results. % % I updated the source documentation but like to apologize in % advance for some `left over' parts that slipped through the % revision. % % A note to people who like to improve the balancing algorithm of % \mc{}: The balancing routine is now placed into a single macro % which is called |\balance@columns|. This means that one can easily % try different balancing routines by rewriting this macro. The % interface for it is explained in table \ref{tab:balance}. There are % several improvements possible, one can think of integrating the % |\badness| function of \TeX3, define a faster algorithm for finding % the right column height, etc. If somebody thinks he/she has an % enhancement I would be pleased to learn about it. But please obey % the copyright notice and don't change \textsf{multicol.dtx} directly! % \begin{table*} % \begin{quote} % \begin{multicols}{2} % \raggedcolumns % The macro |\balance@columns| that contains the code for balancing % gathered material is a macro without parameters. It assumes that % the material for balancing is stored in the box |\mult@box| which % is a |\vbox|. It also ``knows'' about all parameters set up by the % \mc{} environment, like |\col@number|, etc. It can also assume % that |\@colroom| is the still available space on the current page. % % When it finishes it must return the individual columns in boxes % suitable for further processing with |\page@sofar|. This means % that the left column should be stored in box register % |\mult@firstbox|, the next % in register |\mult@firstbox|${}+2$, \ldots, % only the last one as an exception in % register |\mult@grightbox|. % \end{multicols} % \end{quote} % \vspace*{-3ex} % \vspace*{-0ex} % \caption{Interface description for \cs{balance@columns}} % \label{tab:balance} % \end{table*} % \end{multicols} % % \begin{multicols}{3}[\subsection{Preface to version 1.2}] % \hbadness=10000 % After the article about the \mc{} environment was published in % \TUB\ 10\#3, I got numerous requests for these macros. However, I % also got a changed version of my style file, together with a % letter asking me if I would include the changes to get better % paragraphing results in the case of narrow lines. The main % differences to my original style option were additional parameters % (like |\multicoladjdemerits| to be used for |\adjdemerits|, etc.) % which would influence the line breaking algorithm. % % But actually resetting such parameters to zero or even worse to a % negative value won't give better line breaks inside the \mc{} % environment. \TeX{}s line breaking algorithm will only look at % those possible line breaks which can be reached without a badness % higher than the current value of |\tolerance| (or |\pretolerance| % in the first pass). If this isn't possible, then, as a last % resort, \TeX{} will produce overfull boxes. All those (and only % those) possible break points will be considered and finally the % sequence which results in the fewest demerits will be chosen. This % means that a value of $-1000$ for |\adjdemerits| instructs \TeX{} % to prefer visibly incompatible lines instead of producing better % line breaks. % % However, with \TeX{} 3.0 it is possible to get decent line breaks % even in small columns by setting |\emergencystretch| to an % appropriate value. I implemented a version which is capable of % running both in the old and the new \TeX{} (actually it will % simply ignore the new feature if it is not available). The % calculation of |\emergencystretch| is probably incorrect. I % made a few tests but of course one has to have much more experience % with the new possibilities to achieve the maximum quality. % % Version 1.1a had a nice `feature': the penalty for using the % forbidden floats was their ultimate removal from \LaTeX{}s % |\@freelist| so that after a few |\marginpar|s inside the \mc{} % environment floats where disabled forever. (Thanks to Chris % Rowley for pointing this out.) I removed this misbehavior and at % the same time decided to allow at least floats spanning all % columns, e.g., generated by the |figure*| environment. You can % see the new functionality in table~\ref{tab:newcmds} which was % inserted at this very point. % \begin{table*} % \small % \setlength{\multicolsep}{0pt} % \begin{quote} % \begin{multicols}{2} % |\setemergencystretch|: This is a hook for people who like % to play around. It is supposed to set the % |\emergencystretch| \meta{dimen} register provided in the % new \TeX{} 3.0. The first argument is the number of columns and % the second one is the current |\hsize|. At the moment the % default definition is $4\texttt{pt} \times |#1|$, i.e.\ the % |\hsize| isn't used at all. But maybe there are better % formulae. % % \setlength{\emergencystretch}{20pt} |\set@floatcmds|: This is % the hook for the experts who like to implement a full float % mechanism for the \mc{} environment. The |@| in the name % should signal that this might not be easy. % \end{multicols} % \end{quote} % \vspace*{-1ex} % \vspace*{-0ex} % \caption[]{The new commands of \textsf{multicol.sty} version 1.2. % Both commands might be removed if good solutions to these % open problems are found. I hope that these commands will % prevent that nearly identical style files derived from % this one are floating around.} % \label{tab:newcmds} % \end{table*} % However single column floats are still forbidden and I don't think % I will have time to tackle this problem in the near future. As an % advice for all who want to try: wait for \TeX{} 3.0. It has a few % features which will make life much easier in multi-column % surroundings. Nevertheless we are working here at the edge of % \TeX{}s capabilities, really perfect solutions would need a % different approach than it was done in \TeX{}s page builder. % % The text below is nearly unchanged, I only added documentation at % places where new code was added. % \end{multicols} % % \changes{v1.5l}{1996/01/13}{Try hard to explain unresolved reference % that happens if \cs{OnlyDescription} is used} % % \MaybeStop{\PrintIndex \PrintChanges % \ifx\Finale\relax % \typeout{**********************************} % \typeout{* Info: Typesetting this document with % \protect\OnlyDescription\space will} % \typeout{* Info: result in one unresolved % reference to `sec:v14'.} % \typeout{* Info: --- tough, it's just not there in this case!} % \typeout{**********************************} % \fi % } % % % \begin{multicols}{2}[\section{The Implementation} % We are now switching to two-column output to show the % abilities of this environment (and bad layout decisions). % \subsection{The documentation driver file} % ][10\baselineskip] % % \hbadness=10000 % % % The next bit of code contains the documentation driver file for % \TeX{}, i.e., the file that will produce the documentation you are % currently reading. It will be extracted from this file by the \texttt{docstrip} program. % Since this is the first code in this file one can produce the % documentation % simply by running \LaTeX{} on the \texttt{.dtx} file. % \begin{macrocode} %<*driver> \documentclass{ltxdoc} % \end{macrocode} % We use the \texttt{balancingshow} option when loading \mc{} so % that full tracing is produced. This has to be done before the % \texttt{doc} package is loaded, since \texttt{doc} otherwise % requires \mc{} without any options. % \begin{macrocode} \usepackage{multicol}[1999/05/25] \usepackage{doc} % \end{macrocode} % First we set up the page layout suitable for % this article. % \begin{macrocode} \setlength{\textwidth}{39pc} \setlength{\textheight}{54pc} \setlength{\parindent}{1em} \setlength{\parskip}{0pt plus 1pt} \setlength{\oddsidemargin}{0pc} \setlength{\marginparwidth}{0pc} \setlength{\topmargin}{-2.5pc} \setlength{\headsep}{20pt} \setlength{\columnsep}{1.5pc} % \end{macrocode} % We want a rule between columns. % \begin{macrocode} \setlength\columnseprule{.4pt} % \end{macrocode} % We also want to ensure that a new \mc{} environment finds enough % space at the bottom of the page. % \begin{macrocode} \setlength\premulticols{6\baselineskip} % \end{macrocode} % When balancing columns we disregard solutions that % are too bad. Also, if the last column is too bad % we typeset it without stretch. % \begin{macrocode} \setcounter{columnbadness}{7000} \setcounter{finalcolumnbadness}{7000} % \end{macrocode} % The index is supposed to come out in four columns. % And we don't show macro names in the margin. % \begin{macrocode} \setcounter{IndexColumns}{4} % \end{macrocode} % % The following redefinitions have to be moved until after the % preamble because version 3 of \pkg{doc} resets them after the % preamble (this is tmp, because \pkg{hypdoc} is not yet % integrated, but as we all know, tmp solutions have a tendency to % survive for a long time\ldots). % \begin{macrocode} \AddToHook{begindocument}{% \let\DescribeMacro\SpecialUsageIndex \let\DescribeEnv\SpecialEnvIndex \renewcommand\PrintMacroName[1]{}% } % \end{macrocode} % % \begin{macrocode} \CodelineIndex %\DisableCrossrefs % Partial index \RecordChanges % Change log % \end{macrocode} % Line numbers are very small for this article. % \begin{macrocode} \renewcommand{\theCodelineNo} {\scriptsize\rm\arabic{CodelineNo}} \settowidth\MacroIndent{\scriptsize\rm 00\ } \begin{document} \typeout {**************************************** ^^J* Expect some Under- and overfull boxes. ^^J****************************************} \DocInput{multicol.dtx} \end{document} % % \end{macrocode} % % % \end{multicols} % % \begin{multicols}{2}[\subsection{Identification and % option processing}] % % % We start by identifying the package. Since it makes use of features % only available in \LaTeXe{} we ensure that this format is available. % (Now this is done earlier in the file.) % \begin{macrocode} %<*package> % \NeedsTeXFormat{LaTeX2e} % \ProvidesPackage{multicol}[..../../.. % v... multicolumn formatting] % \end{macrocode} % % %^^A \subsection{Option processing} % % Next we declare options supported by \mc{}. Two-column mode % and \mc{} do not work together so we warn about possible % problems. However, since you can revert to |\onecolumn| % in which case \mc{} does work, we don't make this an error. % \begin{macrocode} \DeclareOption{twocolumn} {\PackageWarning{multicol}{May not work with the twocolumn option}} % \end{macrocode} % Tracing is done using a counter. However % it is also possible to invoke the tracing % using the options declared below. % \begin{macrocode} \newcount\c@tracingmulticols \DeclareOption{errorshow} {\c@tracingmulticols\z@} \DeclareOption{infoshow} {\c@tracingmulticols\@ne} \DeclareOption{balancingshow} {\c@tracingmulticols\tw@} % \end{macrocode} % % \changes{v2.0a}{2024/11/10}{Add \cs{DebugMarksOn} to the show options} % \begin{macrocode} \DeclareOption{markshow} {\c@tracingmulticols\thr@@ \DebugMarksOn } \DeclareOption{debugshow} {\c@tracingmulticols5\relax \DebugMarksOn } % \end{macrocode} % The next option is intended for typesetting on a |\baselineskip| % grid. Right now it doesn't do anything other than warning if it % thinks that the grid got lost. % \changes{v1.6a}{2003/03/15}{New option grid} % \changes{v1.8x}{2019/10/15}{Use \cs{@maxdepth} not \cs{maxdepth} (gh/190)} % \begin{macrocode} \let\mc@gridwarn\maxdimen \DeclareOption{grid} {\def\mc@gridwarn{\@maxdepth}} % \end{macrocode} % % \changes{v1.8e}{2014/04/23}{Support \cs{docolaction}} % Next option enables the |\docolaction| command. As this changes % the \texttt{.aux} file content this is not automatically enabled. % \begin{macrocode} \DeclareOption{colaction}{% \def\mc@col@status@write{% \protected@write\@auxout{}% {\string\mc@col@status {\ifmc@firstcol 1\else 2\fi}}% \mc@firstcolfalse}% \def\mc@lastcol@status@write{% \protected@write\@auxout{}% {\string\mc@col@status{3}}}% } \let\mc@col@status@write\relax \let\mc@lastcol@status@write\relax % \end{macrocode} % % \begin{macrocode} \ProcessOptions % \end{macrocode} % % % \end{multicols} % % \begin{multicols}{2}[\subsection{Starting and % Ending the \mc{} Environment}] % % % % % \begin{macro}{\multicols} % As mentioned before, the \mc{} environment has one mandatory % argument (the number of columns) and up to two optional ones. We % start by reading the number of columns into the |\col@number| % register. % \begin{macrocode} \def\multicols#1{\col@number#1\relax % \end{macrocode} % If the user forgot the argument, \TeX{} will complain about a % missing number at this point. The error recovery mechanism will % then use zero, which isn't a good choice in this case. So we % should now test whether everything is okay. The minimum is two % columns at the moment. % \changes{v1.3b}{1990/10/09}{Minimum of two columns} % \begin{macrocode} \ifnum\col@number<\tw@ \PackageWarning{multicol}% {Using `\number\col@number' columns doesn't seem a good idea.^^J I therefore use two columns instead}% \col@number\tw@ \fi % \end{macrocode} % We have only enough box registers for twenty columns, so we need to % check that the user hasn't asked for more. % \changes{v1.4k}{1992/06/27}{Maximum of 5 columns (temp)} % \changes{v1.5a}{1992/11/04}{Allow 10 columns again} % \changes{v1.8y}{2019/12/09}{Allow for 20 columns (gh/237)} % \begin{macrocode} \ifnum\col@number>20 \PackageError{multicol}% {Too many columns}% {Current implementation doesn't support more than 20 columns.% \MessageBreak I therefore use 20 columns instead}% \col@number20 \fi % \end{macrocode} % Within the environment we need a special version of the % kernel |\@footnotetext| command since the original sets the % the |\hsize| to |\columnwidth| which is not correct in the % multicol environment. Here |\columnwidth| refers to the width of % the individual column and the footnote should be in |\textwidth|. % Since |\@footnotetext| has a different definition inside a % minipage environment we do not redefine it directly. Instead we % locally set |\columnwidth| to |\textwidth| and call the original % (current) definition stored in |\orig@footnotetext|. % \changes{v1.5p}{1997/12/14}{Redefinition of \cs{@footnotetext} % only within env pr/2689.} % \changes{v1.5r}{1998/08/17}{Use \cs{@footnotetext} but with % local change to \cs{columnwidth}.} % \changes{v1.5w}{1999/10/21}{Make \cs{@footnotetext} long to allow % multi-paragraph footnotes.} % If the \mc{} environment is nested inside another \mc{} % environment then the redefinition has already happened. So be % better test for this situation. Otherwise, we will get a \TeX{} % stack overflow as this would generate a self-referencing definition. % \changes{v1.6e}{2004/02/14}{Avoid self-referencing definition of % \cs{@footnotetext} (pr/3618)} % \begin{macrocode} \ifx\@footnotetext\mult@footnotetext \else \let\orig@footnotetext\@footnotetext \let\@footnotetext\mult@footnotetext \fi % \end{macrocode} % Now we can safely look for the optional arguments. % \begin{macrocode} \@ifnextchar[\mult@cols{\mult@cols[]}} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\mult@footnotetext} % % \begin{macrocode} \long\def\mult@footnotetext#1{\begingroup \columnwidth\textwidth \orig@footnotetext{#1}\endgroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\mult@cols} % The |\mult@cols| macro grabs the first optional argument % (if any) and looks for the second one. % \begin{macrocode} \def\mult@cols[#1]{\@ifnextchar[% % \end{macrocode} % This argument should be a \meta{dimen} denoting the minimum free % space needed on the current page to start the environment. If the % user didn't supply one, we use |\premulticols| as a % default. % \begin{macrocode} {\mult@@cols{#1}}% {\mult@@cols{#1}[\premulticols]}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\mult@@cols} % After removing all arguments from the input we are able % to start with |\mult@@cols|. % \begin{macrocode} \def\mult@@cols#1[#2]{% % \end{macrocode} % First thing we do is to decide whether or not this is an % unbounded multicols environment, i.e. one that may split across % pages, or one that has to be typeset into a box. If we are in % \TeX's ``inner'' mode (e.g., inside a box already) then we have a % boxed version of multicols therefore we set the |@boxedmulticols| % switch to true. The \mc{} should start in vertical mode. If we % are not already there we now force it with |\par| since otherwise % the test for ``inner'' mode wouldn't show if we are in a box. % \changes{v1.4f}{1992/04/28}{\cs{par} added to allow for correct inner test} % \begin{macrocode} \par \ifinner \@boxedmulticolstrue % \end{macrocode} % Otherwise we check |\doublecol@number|. This counter is zero % outside a multicols environment but positive inside (this happens % a little later on). In the second case we need to process the % current multicols also in ``boxed mode'' and so change the switch % accordingly. % \begin{macrocode} \else \ifnum \doublecol@number>\z@ \@boxedmulticolstrue \fi \fi % \end{macrocode} % Then we look to see if statistics are requested: % \begin{macrocode} \mult@info\z@ {Starting environment with \the\col@number\space columns% % \end{macrocode} % In boxed mode we add some more info. % \changes{v1.4f}{1992/04/28}{\cs{on@line} added to tracing info} % \begin{macrocode} \if@boxedmulticols\MessageBreak (boxed mode)\fi }% % \end{macrocode} % Then we measure the current page to see whether a useful portion % of the multicolumn environment can be typeset. This routine % might start a new page. % \changes{v1.4a}{1992/02/14}{Forgotten braces added} % \begin{macrocode} \enough@room{#2}% % \end{macrocode} % Now we output the first argument and produce vertical space % above the columns. (Note that this argument corresponds to the % first optional argument of the \textsf{multicols} environment.) % For many releases this argument was typeset in a group to get % a similar effect as |\twocolumn[..]| where the argument is % also implicitly surrounded by braces. However, this conflicts % with local changes done by things like sectioning commands (which % account for the majority of commands used in that argument) % messing up vertical spacing etc.\ later in the document so that % from version v1.5q on this argument is again typeset at the outer % level. % \changes{v1.4e}{1992/03/16}{Typeset optional arg inside group} % \changes{v1.5q}{1998/01/19}{And removed the group again six years later} % \begin{macrocode} #1\par\addvspace\multicolsep % \end{macrocode} % When the last line of a paragraph had a positive depth then this % depth normally taken into account by the baselineskip calculation % for the next line. However, the columns produced by a following % \texttt{multicol} are rigid and thus the distance from the % baseline of a previous text line to the first line in a % \texttt{multicol} would differ depending on the depth of the % previous line. To account for this we add a negative space unless % the depth is \texttt{-1000pt} which signals something special to % \TeX and is not supposed to be a real depth. % \changes{v1.5z1}{2003/02/17}{Add a kern to cancel potential depth of % previous line} % \begin{macrocode} \ifdim \prevdepth = -\@m\p@ \else % \end{macrocode} % The actual generation of this corrective space is a little bit % more complicated as it doesn't make sense to always back up to % the previous baseline (in case an object with a very large depth % was placed there, e.g., a centered tabular). So we only back up % to the extend that we are within the |\baselineskip| grid. We % know that the box produced by \mc{} has |\topskip| at its top so % that also needs to be taken into account. % \changes{v1.6a}{2003/03/15}{Adjust spacing} % \begin{macrocode} \@tempcnta\prevdepth \@tempcntb\baselineskip \divide\@tempcnta\@tempcntb \advance\@tempcnta\@ne \dimen@\prevdepth \advance\dimen@ -\@tempcnta\baselineskip \advance\dimen@ \topskip \kern-\dimen@ \fi % \end{macrocode} % We start a new grouping level to hide all subsequent changes % (done in |\prepare@multicols| for example). % \begin{macrocode} \begingroup \prepare@multicols % \end{macrocode} % If we are in boxed mode we now open a box to typeset all material % from the multicols body into it, otherwise we simply go ahead. % \changes{v1.4g}{1992/05/07}{\cs{global} was probably wrong but at least % unnecessary} % \begin{macrocode} \if@boxedmulticols \setbox\mult@box\vbox\bgroup % \end{macrocode} % % \changes{v1.8c}{2013/11/03}{Add \cs{color@setgroup} to prevent color leak} % \begin{macrocode} \color@setgroup % \end{macrocode} % \changes{v1.5?}{1994/?/?}{Penalty moved to later point} % We may have to reset some parameters at this point, % perhaps |\@parboxrestore| % would be the right action but I leave it for the moment. % \changes{v1.4l}{1992/08/17}{\cs{@totalleftmargin} now in % \cs{prepare@multicols}} % \begin{macrocode} \fi % \end{macrocode} % We finish by suppressing initial spaces. % \begin{macrocode} \ignorespaces} % \end{macrocode} % \end{macro} % % \begin{macro}{\if@boxedmulticols} % Here is the switch and the box for ``boxed'' multicols code. % \begin{macrocode} \newif\if@boxedmulticols \@boxedmulticolsfalse \newbox\mult@box % \end{macrocode} % \end{macro} % % \begin{macro}{\enough@room} % \changes{v1.0c}{1989/05/12}{Penalty 0 added to empty the contribution % list.} % The |\enough@room| macro used % above isn't perfect but works reasonably well in this context. We % measure the free space on the current page by subtracting % |\pagetotal| from |\pagegoal|. This isn't entirely % correct since it doesn't take the `shrinking' (i.e.\ % |\pageshrink|) into account. The `recent contribution list' % might be nonempty so we start with |\par| and an explicit % |\penalty|.\footnote{See the documentation of % \cs{endmulticols} for further details.} % Actually, we use |\addpenalty| to ensure that a following % |\addvspace| will `see' the vertical space that might be % present. % The use of |\addpenalty| will have the effect that all items from % the recent contributions will be moved to the main vertical list % and the |\pagetotal| value will be updated correctly. However, % the penalty will be placed in front of any dangling glue item % with the result that the main vertical list may already be % overfull even if \TeX{} is not invoking the output routine. % \changes{v1.3b}{1990/10/09}{Do \cs{penalty} with \cs{addpenalty}} % \changes{v1.4e}{1992/03/16}{But ignore \cs{@nobreak} in \cs{addpenalty}} % \begin{macrocode} \def\enough@room#1{% % \end{macrocode} % Measuring makes only sense when we are not in ``boxed mode'' so % the routine does nothing if the switch is true. % \begin{macrocode} \if@boxedmulticols\else \par % \end{macrocode} % \label{mac:enoughroom} % To empty the contribution list the first release contained a % penalty zero but this had the result that |\addvspace| couldn't % detect preceding glue. So this was changed to |\addpenalty|. But % this turned out to be not enough as |\addpenalty| will not add a % penalty when |@nobreak| is true. Therefore we force this switch % locally to false. As a result there may be a break between % preceding text and the start of a multicols environment, but this % seems acceptable since there is the optional argument for exactly % this reason. % \begin{macrocode} \bgroup\@nobreakfalse\addpenalty\z@\egroup \page@free \pagegoal \advance \page@free -\pagetotal % \end{macrocode} % To be able to output the value we need to assign it to a register % first since it might be a register (default) in which case we % need to use |\the| or it might be a plain value in which case % |\the| would be wrong. % \changes{v1.5e}{1994/05/26}{Assign arg to skip register to be able % to output value} % \begin{macrocode} \@tempskipa#1\relax % \end{macrocode} % Now we test whether tracing information is required: % \begin{macrocode} \mult@info\z@ {Current page:\MessageBreak height=% \the\pagegoal: used \the\pagetotal \space -> free=\the\page@free \MessageBreak needed \the\@tempskipa \space(for #1)}% % \end{macrocode} % Our last action is to force a page break if there isn't enough % room left. % \begin{macrocode} \ifdim \page@free <#1\newpage \fi \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\prepare@multicols} % When preparing for multicolumn output several things must % be done. % \begin{macrocode} \def\prepare@multicols{% % \end{macrocode} % We start saving the current |\@totalleftmargin| and then % resetting the |\parshape| in case we are inside some list % environment. The correct indentation for the \mc{} environment in % such a case will be produced by moving the result to the right by % |\multicol@leftmargin| later on. If we would use the value of % |\@totalleftmargin| directly then lists inside the \mc{} % environment could cause a shift of the output. % \changes{v1.4l}{1992/08/17}{saved \cs{@totalleftmargin}} % \begin{macrocode} \multicol@leftmargin\@totalleftmargin \@totalleftmargin\z@ \parshape\z@ % \end{macrocode} % We also set the register |\doublecol@number| for later use. This % register should contain $2\times |\col@number|$. This is also an % indicator that we are within a \mc{} environment as mentioned % above. % \changes{v1.5a}{1992/11/04}{Add offset to \cs{doublecolnumber}} % \begin{macrocode} \doublecol@number\col@number \multiply\doublecol@number\tw@ \advance\doublecol@number\mult@rightbox % \end{macrocode} % % \begin{macrocode} \mc@prepare@mark@regions % \end{macrocode} % % \begin{macrocode} \if@boxedmulticols \else % \end{macrocode} % We add an empty box to the main vertical list to ensure that we % catch any insertions (held over or inserted at the top of the % page). Otherwise it might happen that the |\eject| is discarded % without calling the output routine. Inside the output routine we % remove this box again. Again this code applies only if we are on % the main vertical list and not within a box. % However, it is not enough to turn off interline spacing, we also % have to clear |\topskip| before adding this box, since |\topskip| % is always inserted before the first box on a page which would % leave us with an extra space of |\topskip| if \mc{} start on a % fresh sheet. % \changes{v1.3c}{1991/03/03}{\cs{null} inserted and removed in output} % \changes{v1.4a}{1992/02/11}{Conditional code for boxed mode added.} % \changes{v1.4o}{1992/11/22}{\cs{topskip} locally zeroed.} % \begin{macrocode} \nointerlineskip {\topskip\z@\null}% \output{% \global\setbox\partial@page\vbox {% % \end{macrocode} % Now we have to make sure that we catch one special situation which % may result in loss of text! If the user has a huge amount of % vertical material within the first optional argument that is larger % then |\premulticols| and we are near the bottom of the page then it % can happen that not the |\eject| is triggering this special output % routine but rather the overfull main vertical list. In that case % we get another breakpoint through the |\eject| penalty. As a result % this special output routine would be called twice and the contents % of |\partial@page|, i.e.\ the material before the \mc{} % environment gets lost. There are several solutions to avoid this % problem, but for now we will simply detect this and inform the user % that he/she has to enlarge the |\premulticols| by using a suitable % value for the second argument. % \changes{v1.4a}{1992/02/11}{Checking for text losses.} % \begin{macrocode} %<*check> \ifvoid\partial@page\else \PackageError{multicol}% {Error saving partial page}% {The part of the page before the multicols environment was nearly full with^^Jthe result that starting the environment will produce an overfull page. Some^^Jtext may be lost! Please increase \premulticols either generally or for this% ^^Jenvironment by specifying a suitable value in the second optional argument to^^Jthe multicols environment.} \unvbox\partial@page \box\last@line \fi % \unvbox\@cclv \global\setbox\last@line\lastbox }% }\eject % \end{macrocode} % The next thing to do is to assign a new value to |\vsize|. % \LaTeX{} maintains the free room on the page (i.e.\ the page % height without the space for already contributed floats) in the % register |\@colroom|. We must subtract the height of % |\partial@page| to put the actual free room into this % variable. % \begin{macrocode} \advance\@colroom-\ht\partial@page % \end{macrocode} % Then we have to calculate the |\vsize| value to use during column % assembly. |\set@mult@vsize| takes an argument which allows to % make the setting local (|\relax|) or global (|\global|). The % latter variant is used inside the output routine below. At this % point here we have to make a local change to |\vsize| because we % want to get the original value for |\vsize| restored in case % this \mc{} environment ends on the same page where it has started. % \changes{v1.4p}{1992/11/26}{Use different \cs{vsize} setting} % \changes{v1.4p}{1992/11/26}{Code moved to \cs{set@mult@vsize}} % \begin{macrocode} \set@mult@vsize\relax % \end{macrocode} % Now we switch to a new |\output| routine which will be used % to put the gathered column material together. % \begin{macrocode} \output{\multi@column@out}% % \end{macrocode} % Finally we handle the footnote insertions. We have to multiply % the magnification factor and the extra skip by the number of % columns since each footnote reduces the space for every column % (remember that we have page-wide footnotes). If, on the other % hand, footnotes are typeset at the very end of the document, our % scheme still works since |\count\footins| is zero then, so it % will not change. % To allow even further customization the setting of the |\footins| % parameters is done in a separate macro. % \changes{v1.5?}{1994/?/?}{Use \cs{init@mult@footins}} % \begin{macrocode} \init@mult@footins % \end{macrocode} % For the same reason (page-wide footnotes), the \meta{dimen} % register controlling the maximum space used for footnotes isn't % changed. Having done this, we must reinsert all the footnotes % which are already present (i.e.\ those encountered when the % material saved in |\partial@page| was first processed). This % will reduce the free space (i.e.\ |\pagetotal|) by the % appropriate amount since we have changed the magnification % factor, etc.\ above. % \begin{macrocode} \reinsert@footnotes % \end{macrocode} % Inside \mc{} a |\clearpage| is fairly useless as we aren't supporting % floats. In fact, it can cause harm as it doesn't know about the % |\partial@page| and may therefore result in making columns too long. % So we change that to behave like |\newpage| but also check if there % are any deferred floats. If so, perhaps the user tried to place them through % that |\clearpage| (but that needs to be done before starting the \mc{} % environment. % \changes{v1.8q}{2017/04/11}{Make \cs{clearpage} behave like \cs{newpage} (pr/4511)} % \begin{macrocode} \def\clearpage{% \ifx\@deferlist\@empty\else \PackageError{multicol}% {Deferred floats not cleared}% {A \string\clearpage\space inside multicols acts like \string\newpage\space and doesn't clear floats.\MessageBreak Move it before the multicols environment if you need it.}% \fi \newpage}% % \end{macrocode} % All the code above was only necessary for the unrestricted \mc{} % version, i.e.\ the one that allows page breaks. If we are within % a box there is no point in setting up special output routines or % |\vsize|, etc. % \begin{macrocode} \fi % \end{macrocode} % But now we are coming to code that is necessary in all cases. We % assign new values to |\vbadness|, |\hbadness| and |\tolerance| % since it's rather hard for \TeX{} to produce `good' paragraphs % within narrow columns. % \changes{v1.2a}{1990/02/05}{\cs{vbadness} 10001 now.} % \begin{macrocode} \vbadness\@Mi \hbadness5000 \tolerance\multicoltolerance % \end{macrocode} % Since nearly always the first pass will fail we ignore it % completely telling \TeX{} to hyphenate directly. In fact, we now % use another register to keep the value for the multicol % pre-tolerance, so that a designer may allow to use % |\pretolerance|. % \changes{v1.2a}{1990/02/05}{\cs{pretolerance} -1 because it nearly never % succeeds.} % \changes{v1.4e}{1992/03/20}{Using} % \begin{macrocode} \pretolerance\multicolpretolerance % \end{macrocode} % For use with the new \TeX{} we set |\emergencystretch| to % $|\col@number| \times 4pt$. However this is only a guess % so at the moment this is done in a macro % |\setemergencystretch| which gets the current |\hsize| % and the number of columns as arguments. Therefore users are able % to figure out their own formula. % \changes{v1.2a}{1990/02/05}{\cs{setemergencystretch} added.} % \begin{macrocode} \setemergencystretch\col@number\hsize % \end{macrocode} % Another hook to allow people adding their own extensions without % making a new package is |\set@floatcmds| which handles any % redefinitions of \LaTeX{}s internal float commands to work with % the \mc{} environment. At the moment it is only used to redefine % |\@dblfloat| and |\end@dblfloat|. % \changes{v1.2a}{1990/02/05}{\cs{set@floatcmds} added.} % \begin{macrocode} \set@floatcmds % \end{macrocode} % Additionally, we advance |\baselineskip| by % |\multicolbaselineskip| to allow corrections for narrow % columns. % \begin{macrocode} \advance\baselineskip\multicolbaselineskip % \end{macrocode} % \changes{v1.0e}{1989/06/21}{\cs{textwidth} changed to \cs{linewidth}.} % \changes{v1.0e}{1989/06/21}{So this file will % work with the `twocolumn' command.} % The |\hsize| of the columns is given by the formula: % \[ % { |\linewidth| - (|\col@number|-1) % \times % |\columnsep| % \over % |\col@number|} % \] % The formula above has changed from release to release. We now % start with the current value of |\linewidth| so that the column % width is properly calculated when we are inside a minipage or a % list or some other environment. % This will be achieved with: % \begin{macrocode} \hsize\linewidth \advance\hsize\columnsep \advance\hsize-\col@number\columnsep \divide\hsize\col@number % \end{macrocode} % We also set |\linewidth| and |\columnwidth| to |\hsize| In the past % |\columnwidth| was left unchanged. This is inconsistent, % but |\columnwidth| is used only by floats (which % aren't allowed in their current implementation) and by the % |\footnote| macro. Since we want page-wide % footnotes\footnote{I'm not sure that I really want page-wide % footnotes. But balancing of the last page can % only be achieved with this approach or with a % multi-path algorithm which is complicated and % slow. But it's a challenge to everybody to % prove me wrong! Another possibility is to % reimplement a small part of the {\it % fire\_up\/} procedure in \TeX{} (the program). % I think that this is the best solution if you % are interested in complex page makeup, but it % has the disadvantage that the resulting % program cannot be called \TeX{} thereafter.} % this simple trick saved us from rewriting the |\footnote| % macros. However, some applications referred to |\columnwidth| as % the ``width of the current column'' to typeset displays % (the \texttt{amsmath} package, for example) and to allow the use % of such applications together with \texttt{multicol} this is now % changed. % % Before we change |\linewidth| to the new value we record its old % value in some register called |\full@width|. This value is % used later on when we package all columns together. % \changes{v1.0e}{1989/06/21}{Setting of \cs{columnwidth} removed.} % \changes{v1.5o}{1997/11/16}{Setting of \cs{columnwidth} added again % pr/2664.} % \begin{macrocode} \full@width\linewidth \linewidth\hsize \columnwidth\hsize } % \end{macrocode} % \end{macro} % % \begin{macro}{\init@mult@footins} % This macro is used to set up the parameters associated % with footnote floats. It can be redefined by applications that % require different amount of spaces when typesetting footnotes. % \begin{macrocode} \def\init@mult@footins{% \multiply\count\footins\col@number \multiply\skip \footins\col@number } % \end{macrocode} % \end{macro} % % \begin{macro}{\set@mult@vsize} % % Since we have to set |\col@umber| columns on one page, % each with a height of |\@colroom|, we have to assign % $ % |\vsize| = |\col@number| \times |\@colroom| % $ % in order to collect enough material before entering the % |\output| routine again. In fact we have to add another % $ % (|\col@number|-1) \times (|\baselineskip|-|\topskip|) % $ % if you think about it. % \changes{v1.4p}{1992/11/26}{Macro added.} % \begin{macrocode} \def\set@mult@vsize#1{% \vsize\@colroom \@tempdima\baselineskip \advance\@tempdima-\topskip \advance\vsize\@tempdima \vsize\col@number\vsize \advance\vsize-\@tempdima % \end{macrocode} % But this might not be enough since we use |\vsplit| later to % extract the columns from the gathered material. Therefore we add % some `extra lines,' one for each column plus a corrective action % depending on the value of the `\texttt{collectmore}' counter. % The final value is assigned globally if |#1| is |\global| because % we want to use this macro later inside the output routine too. % \changes{v1.6c}{2003/04/08}{Collect one line per column more} % \begin{macrocode} \advance\vsize\col@number\baselineskip #1\advance\vsize \c@collectmore\baselineskip} % \end{macrocode} % \end{macro} % % % \begin{macro}{\multicol@leftmargin} % Here is the dimen register we need for saving away the outer % value of |\@totalleftmargin|. % \begin{macrocode} \newdimen\multicol@leftmargin % \end{macrocode} % \end{macro} % % % \begin{macro}{\@Mvi} % In versions prior to 1.8r the balancing at the end of the % environment was done by changing the output routine from % |\multi@column@out| to |\balance@column@out|. As it turned out % that this has a couple of issues when the last columns should not % be balanced after all (for example because they contained several % |\columnbreak| commands we now stay with one output routine for % the environment and only signal that we reached the end of the % environment by marking it with a special penalty that we can check % for later. % \changes{v1.8r}{2018/01/28}{Macro added} % \begin{macrocode} \mathchardef\@Mvi=10006 % 10005 is % \columnbreak % \end{macrocode} % \end{macro} % % % \begin{macro}{\endmulticols} % When the end of the \mc{} environment is sensed we have to % balance the gathered material. Depending on whether or not we are % inside a boxed multicol different things must happen. But first % we end the current paragraph with a |\par| command. % \begin{macrocode} \def\endmulticols{\par \if@boxedmulticols % \end{macrocode} % In boxed mode we have to close the box in which we have gathered % all material for the columns. But before we do this we need to % remove any space at the end of the box as we don't want to use % this in balancing. Because of the |\color@endgroup| this can't be % done later in |\balance@columns| as the color command will hide % it. % \changes{v1.8c}{2013/11/03}{Add \cs{color@endgroup} to prevent color leak} % \changes{v1.8f}{2014/06/19}{Discard spaces before adding \cs{color@endgroup}} % \begin{macrocode} \remove@discardable@items \color@endgroup\egroup % \end{macrocode} % Now we call |\balance@columns| the routine that balances material % stored in the box |\mult@box|. % \changes{v1.5?}{1994/?/?}{Splitting off zero box moved to % \cs{balance@columns}} % \begin{macrocode} \balance@columns % \end{macrocode} % After balancing the result has to be returned by the command % |\page@sofar|. % When the boxed multicol is returned to the page it can happen % that it doesn't fit onto it and \LaTeX{} therefore breaks % earlier. The problem in that case is that during the generation % \cs{hsize}, etc.\ got changed and this setting is still in effect % right now, and if this boxed multicol is within, say, % \texttt{multicols*} then its output routine gets very upset. We % therefore delay returning the result by saving it in box for now % until we have left the group below. % \changes{v1.9e}{2023/02/25}{Delay returning boxed multicols (gh/1002)} % \begin{macrocode} \global\setbox\mc@boxedresult\vbox{% % \end{macrocode} % We first update the mark structures and collect all marks that % need reinsertion once \mc{} has finished. Then we output the boxed % columns and finally we reinsert the marks. % \changes{v2.0a}{2024/11/10}{Use new mark mechanism} % \begin{macrocode} \mc@handle@marks@and@reinserts {in multicol (boxed mode)}% \page@sofar \mc@reinsert@marks }% % \end{macrocode} % This finishes the code for the ``boxed'' case. % \begin{macrocode} \else % \end{macrocode} % If there was a |\columnbreak| on the very last line all material % will have been moved to the |\colbreak@box|. Thus the galley % will be empty and no output routine gets called so that the text % is lost. To avoid this problem (though unlikely) we check if the % current galley is empty and the |\colbreak@box| contains text and % if so return that to the galley. If the galley is non-empty any % material in |\colbreak@box| is added in the output routine since % it needs to be put in front. % \changes{v1.6d}{2003/04/17}{Catch problem with \cs{columnbreak} in % last line} % \begin{macrocode} \ifdim\pagegoal=\maxdimen \ifvoid\colbreak@box\else \mult@info\@ne{Re-adding forced break(s) for splitting}% \unvbox\colbreak@box\fi \fi % \end{macrocode} % If we are in an unrestricted \mc{} environment we end the current % paragraph above with |\par| but this isn't sufficient since \TeX{}s % {\it page\_builder} will not totally empty the contribution % list.\footnote{This once caused a puzzling bug where some of the % material was balanced twice, resulting in some overprints. The % reason was the \cs{eject} which was placed at the end of % the contribution list. Then the {\it page\_builder} was called % (an explicit \cs{penalty} will empty the contribution % list), but the line with the \cs{eject} didn't fit onto % the current page. It was then reconsidered after the output % routine had ended, causing a second break after one line.} % Therefore we must also add an explicit |\penalty|. Now the % contribution list will be emptied and, if its material doesn't % all fit onto the current page then the output routine will be % called before we change it. % \changes{v1.3b}{1990/10/09}{Do \cs{penalty} with \cs{addpenalty}} % \changes{v1.4e}{1992/03/16}{But ignore \cs{@nobreak} in \cs{addpenalty}} % \changes{v1.5c}{1993/04/18}{Again use \cs{penalty}} % At this point we need to use |\penalty| not |\addpenalty| to % ensure that a) the recent contributions are emptied and b) that % the very last item on the main vertical list is a valid break % point so that \TeX{} breaks the page in case it is overfull. % \begin{macrocode} \penalty\z@ % \end{macrocode} % Now it's safe to call the output routine in order to balance % the columns. We do this by calling it with a special penalty. % \changes{v1.8r}{2018/01/28}{Use special penalty to signal end of environment} % \begin{macrocode} \penalty-\@Mvi % \end{macrocode} % If the \mc{} environment body was completely empty or if a % multi-page \mc{} just ends at a page boundary we have the unusual % case that the |\eject| will have no effect (since the main % vertical list is empty)---thus no output routine is called at % all. As a result the material preceding the \mc{} (stored in % |\partial@page| will get lost if we don't put this back by hand. % \changes{v1.4m}{1992/09/04}{Check \cs{partial@page} being emptied} % \begin{macrocode} \ifvbox\partial@page \unvbox\partial@page\fi \fi % \end{macrocode} % The output routine above will take care of the |\vsize| and % reinsert the balanced columns, etc. But it can't reinsert the % |\footnotes| because we first have to restore the % |\footins| parameter since we are returning to one column % mode. This will be done in the next line of code; we simply close % the group started in |\multicols|. % % To fix an obscure bug which is the result of the current % definition of the |\begin| \ldots\ |\end| macros, we check that % we are still (logically speaking) in the \mc{} environment. If, % for example, we forget to close some environment inside the % \mc{} environment, the following |\endgroup| would be % incorrectly considered to be the closing of this environment. % \changes{v1.3c}{1991/03/14}{Check closing env.} % \begin{macrocode} \@checkend{multicols}% \endgroup % \end{macrocode} % We also set the `\textsf{unbalance}' counter to its default. This is % done globally since \LaTeX{} counters are always changed this % way.\footnote{Actually, we are still in a group started by the % \cs{begin} macro, so \cs{global} must be used % anyway.} % \begin{macrocode} \global\c@unbalance\z@ % \end{macrocode} % Now it's time to return any footnotes if we are in unrestricted % mode. In boxed mode footnotes are kept inside, but in that case % we have to first return the saved box to the page and then write % another column status into the \texttt{.aux} % file to support \cs{docolaction} in case we have nested % environments. % \changes{v1.8s}{2018/04/20}{Support for \cs{docolaction} (issue/39)} % \changes{v1.9e}{2023/02/25}{Delay returning boxed multicols (gh/1002)} % \begin{macrocode} \if@boxedmulticols \unvbox\mc@boxedresult \mc@col@status@write \else \reinsert@footnotes % \end{macrocode} % We also take a look at the amount of free space on the current % page to see if it's time for a page break. The vertical space % added thereafter will vanish if |\enough@room| starts a new % page. % % But there is one catch. If the |\end{multicols}| is at the top of % which can happen if there is a break point just before it (such % as end ending environment) which was chosen. In that case we % would do the next page using the internal |\vsize| for multicol % collection which is a disaster. So we better catch this % case. Fortunately we can detect it by looking at |\pagegoal|. % \changes{v1.5x}{2000/05/05}{Detect and fix problem if a multicols % ends at the top of a page} % \begin{macrocode} \ifdim \pagegoal=\maxdimen \global\vsize\@colroom \else \enough@room\postmulticols \fi \fi \addvspace\multicolsep % \end{macrocode} % There is one more thing to do: the balanced result of the % environment is supposed to have a |\prevdepth| of zero as we % backed up by its real prevdepth within |\page@sofar|. However if % the balancing happened in the output routine then \TeX{} reverts % to the |\prevdepth| that was current before the OR once the OR has % finished. In short |\prevdepth| is something you can't set % globally it is always local to the current list being built. Thus % we need to set it back to zero here to avoid incorrect spacing. % \changes{v1.8h}{2014/09/12}{Set \cs{prevdepdth} for current vlist % when returning from multicols environment} % \begin{macrocode} \prevdepth\z@ % \end{macrocode} % If statistics are required we finally report that we have % finished everything. % \begin{macrocode} \mult@info\z@ {Ending environment \if@boxedmulticols \space(boxed mode)\fi }} % \end{macrocode} % \end{macro} % % % \begin{macro}{\c@unbalance} % \SpecialMainIndex{\c@collectmore} % \SpecialMainIndex{\col@number} % \SpecialMainIndex{\doublecol@number} % \SpecialMainIndex{\premulticols} % \SpecialMainIndex{\multicoltolerance} % \SpecialMainIndex{\multicolpretolerance} % \SpecialMainIndex{\page@free} % \SpecialMainIndex{\premulticols} % \SpecialMainIndex{\postmulticols} % \SpecialMainIndex{\multicolsep} % \SpecialMainIndex{\multicolbaselineskip} % \SpecialMainIndex{\partial@page} % \SpecialMainIndex{\mc@boxedresult} % Let us end this section by allocating all the registers used so % far. % \begin{macrocode} \newcount\c@unbalance \newcount\c@collectmore % \end{macrocode} % In the new \LaTeX{} release |\col@number| is already allocated by % the kernel, so we don't allocate it again. % \begin{macrocode} %\newcount\col@number \newcount\doublecol@number \newcount\multicoltolerance \newcount\multicolpretolerance \newdimen\full@width \newdimen\page@free \newdimen\premulticols \newdimen\postmulticols \newskip\multicolsep \newskip\multicolbaselineskip \newbox\partial@page \newbox\last@line \newbox\mc@boxedresult % \end{macrocode} % And here are their default values: % \begin{macrocode} \c@unbalance = 0 \c@collectmore = 0 % \end{macrocode} % To allow checking whether some macro is used within the \mc{} % environment the counter |\col@number| gets a default of |1| % outside the environment. % \changes{v1.3d}{1991/10/23}{\cs{col@number} set to one} % \changes{v1.8o}{2016/02/08}{\cs{col@number} already initialized in the % kernel, so not initializing it in the package % in case the document is in two-column (pr/4435)} % \begin{macrocode} %\col@number = 1 \multicoltolerance = 9999 \multicolpretolerance = -1 \premulticols = 50pt \postmulticols= 20pt \multicolsep = 12pt plus 4pt minus 3pt \multicolbaselineskip=0pt % \end{macrocode} % \end{macro} % % \end{multicols} % % \begin{multicols}{2}[\subsection{The output routines}] % % We first start with some simple macros. When typesetting the page we % save the columns either in the box registers 0, 2, 4,\ldots\ % (locally) or 1, 3, 5,\ldots\ (globally). This is \PlainTeX{} policy % to avoid an overflow of the save stack. % % \begin{macro}{\process@cols} % Therefore we define a |\process@cols| macro to help us in % using these registers in the output routines below. It has two % arguments: the first one is a number; the second one is the % processing information. It loops starting with |\count@=#1| % (|\count@| is a scratch register defined in \PlainTeX), % processes argument |#2|, adds two to |\count@|, % processes argument |#2| again, etc.\ until |\count@| is % higher than |\doublecol@number|. It might be easier to % understand it through an example, so we define it now and % explain its usage afterwards. % \begin{macrocode} \def\process@cols#1#2{\count@#1\relax \loop %<*debug> \typeout{Looking at box \the\count@} % #2% \advance\count@\tw@ \ifnum\count@<\doublecol@number \repeat} % \end{macrocode} % \end{macro} % % % \begin{macro}{\page@sofar} % We now define |\page@sofar| to give an example of the % |\process@cols| macro. |\page@sofar| should output everything % prepared by the balancing routine |\balance@columns|. % \begin{macrocode} \def\page@sofar{% % \end{macrocode} % |\balance@columns| prepares its output in the even numbered % scratch box registers. % Now we output the columns gathered assuming that they are saved % in the box registers 2 (left column), 4 (second column), \ldots\ % However, the last column (i.e.\ the right-most) should be saved in % box register 0.\footnote{You will see the reason for this numbering % when we look at the output routines % \cs{multi@column@out} and % \cs{balance@columns@out}.} % First we ensure that the columns have equal width. We use % |\process@cols| for this purpose, starting with % $|\count@|=|\mult@rightbox|$. Therefore |\count@| loops through % |\mult@rightbox|, $|\mult@rightbox| + 2$,\ldots % (to |\doublecol@number|). % \changes{v1.5a}{1992/11/04}{New box mechanism} % \begin{macrocode} \process@cols\mult@rightbox % \end{macrocode} % We have to check if the box in question is void, because the % operation |\wd|\meta{number} on a void box will \emph{not} change % its dimension (sigh). % \changes{v1.5h}{1994/08/26}{Check for void boxes} % \changes{v1.5i}{1994/10/02}{But don't remove original code.} % \begin{macrocode} {\ifvoid\count@ \setbox\count@\hbox to\hsize{}% \else \wd\count@\hsize \fi}% % \end{macrocode} % Now we give some tracing information. % \changes{v1.4l}{1992/08/17}{use \cs{multicol@leftmargin} instead of % \cs{@totalleftmargin}} % \changes{v1.6b}{2003/03/15}{Different info display} % \begin{macrocode} \count@\col@number \advance\count@\m@ne \mult@info\z@ {Column spec: \the\full@width\space = indent + columns + sep =\MessageBreak \the\multicol@leftmargin\space + \the\col@number\space x \the\hsize\space + \the\count@\space x \the\columnsep }% % \end{macrocode} % At this point we should always be in vertical mode. % \begin{macrocode} \ifvmode\else\errmessage{Multicol Error}\fi % \end{macrocode} % % % Now we put all columns together in an |\hbox| of width % |\full@width| (shifting it by |\multicol@leftmargin| to the right % so that it will be placed correctly if we are within a list % environment) % and separating the columns with a rule if desired. % \changes{v1.5a}{1992/11/04}{New box mechanism} % \changes{v1.5z}{2000/07/10}{Ensure that column rule has always % \cs{normalcolor}} % \changes{v1.6f}{2006/09/19}{Make the color of the rule a hook} % \changes{v1.4l}{1992/08/17}{use \cs{multicol@leftmargin} instead of % \cs{@totalleftmargin}} % % The box containing the columns has a large height and thus will % always result in using |\lineskip| if the normal |\baselineskip| % calculations are used. We therefore better cancel that process. % \changes{v1.5z1}{2003/02/17}{Suppress interline glue at this point} % \begin{macrocode} \nointerlineskip % \end{macrocode} % As mentioned earlier we want to have the reference point of the % box we put on the page being at the baseline of the last line of % the columns but we also want to ensure that the box has no depth % so that any following skip is automatically starting from that % baseline. % We achieve this by recording the depths of all columns and then % finally backing up by the maximum. (perhaps a simpler method % would be to assemble the box in a register and set the depth of % that box to zero (not checked). % % We need a global scratch register for this; using standard \TeX{} % conventions we choose |\dimen2| and initialize it with the depth % of the character ``p'' since that is one of the depths that % compete for the maximum. % \changes{v1.6a}{2003/03/15}{Preparing for adjusting \cs{prevdepth}} % \changes{v1.9f}{2023/03/30}{Make column min depth customizable (gh/698)} % \begin{macrocode} \setbox\z@\hbox{\multicolmindepthstring}\global\dimen\tw@\dp\z@ % \end{macrocode} % % \changes{v2.0a}{2024/11/12}{Addedd tagging socket} % \begin{macrocode} \UseTaggingSocket{page@sofar}% % \end{macrocode} % % \begin{macrocode} \moveright\multicol@leftmargin \hbox to\full@width{% % \end{macrocode} % If the document is written in a language that is typeset right-to-left % then, of course, the multicol columns should be also typeset % right-to-left. To support this we call |\mc@align@columns| which % with execute different code depending on the typesetting direction. % \changes{v1.7b}{2011/12/18}{RL language support fixed} % \begin{macrocode} \mc@align@columns % \end{macrocode} % The depths of the columns depend on their last lines. To ensure % that we will always get a similar look as far as the rules are % concerned we force the depth to be at least the depth of a % letter~`p' or more exactly \cs{multicolmindepthstring} (which is what % we set |\dimen2| to above). % \changes{v1.9f}{2023/03/30}{Make column min depth customizable (gh/698)} % \begin{macrocode} \rlap{\phantom \multicolmindepthstring}% }% % \end{macrocode} % The processed material might consist of a last line with a % descender in which case the |\prevdepth| will be % non-zero. However, this material is getting reformatted now so % that this value is likely to be wrong. We therefore normalize the % situation by pretending that the depth is zero. However, if |\page@sofar| % is being called inside the OR then setting |\prevdepth| here has % no long-lasting effect, we therefore have to repeat this once we % return to the main vertical list. Here we set it only for those % cases where the command is used within a list and then followed by % something else. % \changes{v1.8g}{2014/08/24}{Resetting \cs{prevdepth} in the right place} % \begin{macrocode} \prevdepth\z@ % \end{macrocode} % Now after typesetting the box we back up to its baseline by using % the value stored in |\dimen2| (which will hold the largest depth % found on any column). % \changes{v1.8g}{2003/03/15}{Now adjusting \cs{prevdepth}} % \begin{macrocode} \kern-\dimen\tw@ % \end{macrocode} % However, in case one of the columns was unusually deep \TeX{} may % have tried some corrective actions in which case backing up by % the saved value will not bring us back to the baseline. A good % indication for this is a depth of |\@maxdepth| though it is not an % absolute proof. If the option \texttt{grid} is used % |\mc@gridwarn| will expand to this, otherwise to |\maxdimen| in % which case this warning will not show up. % \changes{v1.8g}{2014/08/24}{Warn if value is exceeded not when equal} % \begin{macrocode} \ifdim\dimen\tw@ > \mc@gridwarn \PackageWarning{multicol}% {Very deep columns!\MessageBreak Grid alignment might be broken}% \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\multicolmindepthstring} % The default minimum depth of each column corresponds to the depth % of a `p' in the current font. This makes sense for Latin-based % languages and was hard-wired initially, but for Asian languages % it is better to use a zero depth (and alternatively one might % want to use the depth of a strut or a parentheses). So we now % offer a way to adjust this while maintaining backward % compatibility. Use \cs{renewcommand} to alter it. % \changes{v1.9f}{2023/03/30}{Make column min depth customizable (gh/698)} % \begin{macrocode} \def\multicolmindepthstring{p} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\columnseprulecolor} % \changes{v1.6f}{2006/09/19}{Make the color of the rule a hook} % By default the vertical rule between columns will be in |\normalcolor|. % \begin{macrocode} \def\columnseprulecolor{\normalcolor} % \end{macrocode} % \end{macro} % % \begin{macro}{\reinsert@footnotes} % Before we tackle the bigger output routines we define just one % more macro which will help us to find our way through the % mysteries later. |\reinsert@footnotes| will do what its name % indicates: it reinserts the footnotes present in % |\footinbox| so that they will be reprocessed by \TeX{}'s % {\it page\_builder}. % % Instead of actually reinserting the footnotes we insert an empty % footnote. This will trigger insertion mechanism as well and since % the old footnotes are still in their box and we are on a fresh page % |\skip| |footins| should be correctly taken into account. % \changes{v1.3c}{1990/03/03}{\cs{unbox}ing avoided.} % \begin{macrocode} \def\reinsert@footnotes{\ifvoid\footins\else \insert\footins{}\fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\vfilmaxdepth} % This curious definition is used as the space at the bottom of a % column if we implement |\raggedcolumns|. Normally one only appends % |\vfill| in that case but this is actually wrong for columns that % are more or less full: by adding a glue at the bottom such a % column doesn't have any depth any more but without it the material % would be allowed a depth of |\@maxdepth|. So we allow shrinking by % that amount. This only makes a difference if the box would % otherwise become overfull and shrinking never exceeds the % specified value, so we should be fine. % \changes{v1.8h}{2014/09/12}{Macro added (pr/4395)} % \changes{v1.8j}{2015/03/07}{Use only `0.0001fil' for stretching} % \changes{v1.8x}{2019/10/15}{Use \cs{@maxdepth} not \cs{maxdepth} (gh/190)} % \begin{macrocode} \def\vfilmaxdepth{\vskip \z@ \@plus .0001fil \@minus \@maxdepth} % \end{macrocode} % \end{macro} % % % \begin{macro}{\multi@column@out} % Now we can't postpone the difficulties any longer. The % |\multi@column@out| routine will be called in two situations. % Either the page is full (i.e., we have collected enough material % to generate all the required columns) or a float or marginpar or % a |\clearpage| is % sensed. In the latter case the |\outputpenalty| is less % than $-10000$, otherwise the penalty which triggered the output % routine is higher. Therefore it's easy to distinguish both % cases: we simply test this register. % \changes{v1.5c}{1993/04/18}{Support \cs{clearpage}} % \begin{macrocode} \def\multi@column@out{% \ifnum\outputpenalty <-\@M % \end{macrocode} % If this was a |\clearpage|, a float or a marginpar we call % |\speci@ls| % \begin{macrocode} \speci@ls \else % \end{macrocode} % otherwise we construct the final page. % \changes{v1.5u}{1999/05/25}{Support \cs{columnbreak}} % \changes{v1.5v}{1999/07/18}{Added debug statements for % column break support} % For the next block of code see comments in section~\ref{sec:colbreak}. % \begin{macrocode} \ifvoid\colbreak@box\else \mult@info\@ne{Re-adding forced break(s) for splitting}% \setbox\@cclv\vbox{% \unvbox\colbreak@box \penalty-\@Mv \unvbox\@cclv}% \fi % \end{macrocode} % Let us now consider the % normal case. We have to |\vsplit| the columns from the % accumulated material in box 255. Therefore we first assign % appropriate values to |\splittopskip| and |\splitmaxdepth|. % \begin{macrocode} \splittopskip\topskip \splitmaxdepth\@maxdepth % \end{macrocode} % We also need to restrict |\boxmaxdepth| so that re-boxing is not % generating boxes with arbitrary depth. % \changes{v1.8j}{2015/03/07}{Set \cs{boxmaxdepth}} % \begin{macrocode} \boxmaxdepth\@maxdepth % \end{macrocode} % Then we calculate the current column height (in |\dimen@|). % Note that the height of |\partial@page| is already % subtracted from |\@colroom| so we can use its value as a % starter. % \begin{macrocode} \dimen@\@colroom % \end{macrocode} % But we must also subtract the space occupied by footnotes on the % current page. Note that we first have to reset the skip register % to its normal value. % Again, the actual action is carried out in a utility macro, so that % other applications can modify it. % \changes{v1.5?}{1994/?/?}{Use \cs{leave@mult@footins}} % \begin{macrocode} \divide\skip\footins\col@number \ifvoid\footins \else \leave@mult@footins \fi % \end{macrocode} % And there is one more adjustment that we have to make: if the % user has issue a |\enlargethispage| command then the height the % |\@kludgeins| box will be the negation of the size by which the % page should be enlarged. If the star form of this command has % been used then we also need to shrink the resulting column. % % That local change will be reverted at the end of the output % routine So for the next page the original state will be % reestablished. However, in theory there is a possibility to sneak % in a whole multicols environment into the running header % definition. If that happens then it will also be affected by this % change---too bad I think. % \changes{v1.8a}{2011/12/20}{Support for \cs{enlargethispage}} % \changes{v1.8v}{2018/12/27}{Removed dead code, the case where this % can go wrong is too obscure to worry about it (gh/101)} % \begin{macrocode} \ifvbox \@kludgeins \advance \dimen@ -\ht\@kludgeins % \end{macrocode} % The star form of |\enlargethispage| makes the width of the box % greater than zero (sneaky isn't it?). % \begin{macrocode} \ifdim \wd\@kludgeins>\z@ \shr@nkingtrue \fi \fi % \end{macrocode} % Now we are able to |\vsplit| off all but the last column. % Recall that these columns should be saved in the box registers 2, % 4,\ldots\ (plus offset). % \changes{v1.5a}{1992/11/04}{New box mechanism} % \begin{macrocode} \process@cols\mult@firstbox{% \setbox\count@ \vsplit\@cclv to\dimen@ % \end{macrocode} % If |\raggedcolumns| is in force we add a |vfill| at the bottom by % unboxing the split box. % But we need to unbox anyway to ensure that at the end of the box % we do not have unwanted space. This can sneak in, in certain % situations, for example, if two lists follow each other and we % break between them. While such space is usually zero it still has % an effect because it hides depth of the last line in the column % and that will result in incorrect placement. % \changes{v1.3c}{1990/03/03}{\cs{unbox}ing avoided.} % \changes{v1.8b}{2013/08/28}{And 20odd years later conclude that % this was wrong and unboxing is always needed.} % \changes{v1.8b}{2013/08/28}{Remove discardable items at the % end of split boxes} % \changes{v1.8h}{2014/09/12}{Use \cs{vfilmaxdepth}} % \changes{v1.8k}{2015/03/22}{\cs{remove@discardable@items} removed} % \begin{macrocode} \setbox\count@ \vbox to\dimen@ {\unvbox\count@ \ifshr@nking \vfilmaxdepth\fi}% }% % \end{macrocode} % Then the last column follows. % \changes{v1.5a}{1992/11/04}{New box mechanism} % \changes{v1.8b}{2013/08/28}{Remove discardable items at the % end of split boxes} % \changes{v1.8h}{2014/09/12}{Use \cs{vfilmaxdepth}} % \changes{v1.8k}{2015/03/22}{\cs{remove@discardable@items} removed} % \begin{macrocode} \setbox\mult@rightbox \vsplit\@cclv to\dimen@ \setbox\mult@rightbox\vbox to\dimen@ {\unvbox\mult@rightbox \ifshr@nking\vfilmaxdepth\fi}% % \end{macrocode} % Having done this we hope that box 255 is emptied. If not, we % reinsert its contents. % \changes{v1.8a}{2011/12/20}{Only re-add output penalty if it was % explicitly set} % \begin{macrocode} \ifvoid\@cclv \else \unvbox\@cclv \ifnum\outputpenalty=\@M \else \penalty\outputpenalty \fi % \end{macrocode} % In this case a footnote that happens to fall into the leftover % bit will be typeset on the wrong page. Therefore we warn the user % if the current page contains footnotes. The older versions of % \mc{} produced this warning regardless of whether or not % footnotes were present, resulting in many unnecessary warnings. % \changes{v1.3c}{1991/02/17}{Check if footnotes are actually present % before issuing a warning.} % \begin{macrocode} \ifvoid\footins\else \PackageWarning{multicol}% {I moved some lines to the next page.\MessageBreak Footnotes on page \thepage\space might be wrong}% \fi % \end{macrocode} % % If the `\textsf{tracingmulticols}' counter is 4 or higher we also % add a rule. % \begin{macrocode} \ifnum \c@tracingmulticols>\thr@@ \hrule\allowbreak \fi \fi % \end{macrocode} % With a little more effort we could have done better. If we had, % for example, recorded the shrinkage of the material in % |\partial@page| it would be now possible to try higher % values for |\dimen@| (i.e.\ the column height) to overcome % the problem with the nonempty box 255. But this would make the % code even more complex so I skipped it in the current % implementation. % % Now we use \LaTeX{}'s standard output % mechanism.\footnote{This will produce a lot of overhead since both % output routines are held in memory. The correct % solution would be to redesign the whole output % routine used in \LaTeX.} % Admittedly this is a funny way to do it. % % Within the OR |\boxmaxdepth| needs to be unrestricted so we set it back % now as it was changed above. % \changes{v1.8p}{2016/04/07}{Reset \cs{boxmaxdepth}} % \begin{macrocode} \boxmaxdepth\maxdimen \setbox\@cclv\vbox {% % \end{macrocode} % If we make a page while still inside the \mc{} environment we % have to handle column and page mark structures. % \changes{v2.0a}{2024/11/10}{Use new mark mechanism} % \begin{macrocode} \mc@handle@col@andpage@marks {in multicol OR (full page)}% \unvbox\partial@page \page@sofar }% % \end{macrocode} % The macro |\@makecol| adds all floats assigned for the current % page to this page. |\@outputpage| ships out the resulting box. % Note that it is just possible that such floats are present even % if we do not allow any inside a \mc{} environment. % \begin{macrocode} \@makecol\@outputpage % \end{macrocode} % Now we reset |\@colroom| to |\@colht| which is \LaTeX's % saved value of |\textheight|. % We also have to reset the recorded position of the last % |\marginpar| as well as the recorded size of in-text floats % as we are now on a new page. % \changes{v1.8d}{2014/04/23}{Reset \cs{@mparbottom} after page finishes} % \changes{v1.8n}{2015/08/19}{Reset \cs{@textfloatsheight} after page finishes} % \begin{macrocode} \global\@colroom\@colht \global \@mparbottom \z@ \global \@textfloatsheight \z@ % \end{macrocode} % Then we process deferred floats waiting for their chance to be % placed on the next page. % \begin{macrocode} \process@deferreds \@whilesw\if@fcolmade\fi{\@outputpage \global\@colroom\@colht \process@deferreds}% % \end{macrocode} % If the user is interested in statistics we inform him about the % amount of space reserved for floats. % \begin{macrocode} \mult@info\@ne {Colroom:\MessageBreak \the\@colht\space after float space removed = \the\@colroom \@gobble}% % \end{macrocode} % Having done all this we must prepare to tackle the next page. % Therefore we assign a new value to |\vsize|. New, because % |\partial@page| is now empty and |\@colroom| might be % reduced by the space reserved for floats. % \changes{v1.4p}{1992/11/26}{Use different \cs{vsize} setting} % \begin{macrocode} \set@mult@vsize \global % \end{macrocode} % The |\footins| skip register will be adjusted when the output % group is closed. % \changes{v1.3c}{1991/03/03}{Unnecessary code removed} % \begin{macrocode} \fi} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\leave@mult@footins} % This macro is used to subtract the amount of space % occupied by footnotes for the current space from the % space available for the current column. The space current column % is stored in |\dimen@|. See above for the description of the default % action. % \changes{v1.5?}{1994/?/?}{Macro added} % \begin{macrocode} \def\leave@mult@footins{% \advance\dimen@-\skip\footins \advance\dimen@-\ht\footins } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\speci@ls} % We left out two macros: |\process@deferreds| and % |\speci@ls|. % \changes{v1.5c}{1993/04/18}{Support \cs{clearpage}} % \begin{macrocode} \def\speci@ls{% \ifnum\outputpenalty <-\@Mi % \end{macrocode} % If the document ends in the middle of a multicols environment, e.g., % if the user forgot the |\end{multicols}|, \TeX{} adds a very % negative penalty to the end of the galley which is intended to signal % the output routine that it is time to prepare for shipping out % everything remaining. Since inside multicols the output routine of % \LaTeX{} is disabled sometimes we better check for this case: if we % find a very negative penalty we produce an error message and run % the default output routine for this case. % \changes{v1.5s}{1998/09/10}{check for \cs{stop} penalty pr/2873} % \begin{macrocode} \ifnum \outputpenalty<-\@MM \PackageError{multicol}{Document end inside multicols environment}\@ehd \@specialoutput \else % \end{macrocode} % \changes{v1.5u}{1999/05/25}{Support \cs{columnbreak}} % \changes{v1.5v}{1999/07/18}{Added debug statements for % column break support} % For the next block of code see comments in section~\ref{sec:colbreak}. % \begin{macrocode} \ifnum\outputpenalty = -\@Mv \mult@info\@ne{Forced column break seen}% \global\advance\vsize-\pagetotal \global\setbox\colbreak@box \vbox{% \ifvoid\colbreak@box \else \unvbox\colbreak@box \penalty-\@Mv \fi % \end{macrocode} % As this is the place of a forced break we now remove vertical % white space just in front of it (or some of it at least) as it is % quite likely that the break is not exactly in the right place, % e.g., after a display environment (if LaTeX would break here by % its own it would break before the space following the display). % % Thus we rebox box 255 once (using |\@maxdepth| and calling % |\remove@discardable@items| inside). The depth of 255 will then % give us the depth the box would have had if it would have been a % natural break. We then unbox 255 to get it into the % |\colbreak@box| and then back up by this depth. This will position % the bottom of the box at its natural baseline which is useful for % balancing later on. % \changes{v1.8k}{2015/03/21}{Remove discardable items just before a % forced break} % \changes{v1.8x}{2019/10/15}{Use \cs{@maxdepth} not \cs{maxdepth} (gh/190)} % \begin{macrocode} \boxmaxdepth\@maxdepth \setbox\@cclv\vbox{% \unvbox\@cclv \remove@discardable@items}% \dimen@\dp\@cclv \unvbox\@cclv \kern-\dimen@ }% \reinsert@footnotes \else % \end{macrocode} % Another special case is reaching the end of the \mc{} % environment which is signaled by |-\@Mvi|. % \changes{v1.8r}{2018/01/28}{Handling end of env through special penalty} % \begin{macrocode} \ifnum\outputpenalty = -\@Mvi \mult@info\@ne{End penalty of multicols seen}% % \end{macrocode} % If we are at this point then we have to run the balancing code % (which was previously its own output routine). First we pretend % that we had a normal forced breakpoint and then call % |\balance@column@out|. The latter may be let to |\multi@column@out| % if we are inside \texttt{multicols*} in which case we would get a loop % if the |\outputpenalty| is not changed---this could be cleaned up % in a better way; basically it is like this, because of the older % code was using different ORs and I simply reused most of it. % \begin{macrocode} \outputpenalty\@M % pretend we had % a natural % forced break \balance@columns@out \else % \end{macrocode} % If we encounter a float or a marginpar in the current % implementation we simply warn the user that this is not allowed. % Then we reinsert the page and its footnotes. % \begin{macrocode} \PackageWarningNoLine{multicol}% {Floats and marginpars not allowed inside `multicols' environment!}% \unvbox\@cclv\reinsert@footnotes % \end{macrocode} % Additionally we empty the |\@currlist| to avoid later error % messages when the \LaTeX{} output routine is again in force. % But first we have to place the boxes back onto the % |\@freelist|. (|\@elt|s default is |\relax| so % this is possible with |\xdef|.) % \changes{v1.2a}{1990/02/05}{Float boxes freed.} % \begin{macrocode} \xdef\@freelist{\@freelist \@currlist}% \gdef\@currlist{}% \fi \fi \fi % \end{macrocode} % If the penalty is $-10001$ it will come from a |\clearpage| and % we will execute |\@doclearpage| to get rid of any deferred % floats. % \begin{macrocode} \else \@doclearpage \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\process@deferreds} % |\process@deferreds| is a simplified version of \LaTeX{}'s % |\@startpage|. We first call the macro % |\@floatplacement| to save the current user parameters in % internal registers. Then we start a new group and save the % |\@deferlist| temporarily in the macro |\@tempb|. % \begin{macrocode} \def\process@deferreds{% \@floatplacement \@tryfcolumn\@deferlist \if@fcolmade\else \begingroup \let\@tempb\@deferlist % \end{macrocode} % Our next action is to (globally) empty |\@deferlist| and % assign a new meaning to |\@elt|. Here |\@scolelt| is a % macro that looks at the boxes in a list to decide whether they % should be placed on the next page (i.e.\ on |\@toplist| or % |\@botlist|) or should wait for further processing. % \begin{macrocode} \gdef\@deferlist{}% \let\@elt\@scolelt % \end{macrocode} % Now we call |\@tempb| which has the form % \begin{center} % |\@elt|\meta{box register}|\@elt|^^A % \meta{box register}\ldots{} % \end{center} % So |\@elt| (i.e.\ |\@scolelt|) will distribute the % boxes to the three lists. % \begin{macrocode} \@tempb \endgroup \fi} % \end{macrocode} % \end{macro} % % % % \begin{macro}{ifshr@nking} % \begin{macro}{\raggedcolumns} % \begin{macro}{\flushcolumns} % \changes{v1.1a}{1989/09/20}{\cs{flushedcolumns} renamed to \cs{flushcolumns}.} % The |\raggedcolumns| and |\flushcolumns| % declarations are defined with the help of a new |\if...| % macro. % \begin{macrocode} \newif\ifshr@nking % \end{macrocode} % The actual definitions are simple: we just switch to \textsf{true} % or \textsf{false} depending on the desired action. To avoid extra % spaces in the output we enclose these changes in % |\@bsphack|\ldots{}\allowbreak|\@esphack|. % \begin{macrocode} \def\raggedcolumns{% \@bsphack\shr@nkingtrue\@esphack} \def\flushcolumns{% \@bsphack\shr@nkingfalse\@esphack} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\balance@columns@out} % Now for the last part of the show: the column balancing output % routine. Since this code is called with an explicit penalty % (|\eject|) there is no need to check for something special (eg % floats). We start by balancing the material gathered. % \begin{macrocode} \def\balance@columns@out{% % \end{macrocode} % For this we need to put the contents of box 255 into |\mult@box|. % \changes{v1.5u}{1999/05/25}{Support \cs{columnbreak}} % \changes{v1.5v}{1999/07/18}{Added debug statements for column break % support} For the next block of code see also comments in % section~\ref{sec:colbreak}. All forced breaks except the last are % inside |\colbreak@box| so all we have to do is to concatenate this % box with box |\@cclv| and put a penalty in between. Here we test if % |\colbreak@box| is void so that the message is only generated if % we really add forced breaks and the penalty. % \changes{v1.8k}{2015/03/21}{Use \cs{@Mv} and not \cs{break} in case % this forced break is not used on this page} % \begin{macrocode} \setbox\mult@box\vbox{% \ifvoid\colbreak@box\else \unvbox\colbreak@box \penalty-\@Mv \mult@info\@ne{Re-adding forced break(s) in balancing}% \fi \unvbox\@cclv % \end{macrocode} % The last column again is a forced break, so here we discard white % space as well as that is normally unwanted. % \changes{v1.8k}{2015/03/21}{Add \cs{remove@discardable@items} at the % end of the last column when balancing.} % \begin{macrocode} \remove@discardable@items }% \balance@columns % \end{macrocode} % If during balancing the columns got too long the flag % |\iftoo@bad| is set to true. % \changes{v1.8a}{2011/12/20}{Balancing concept improved} % \begin{macrocode} \iftoo@bad \mult@info\@ne {Balancing failed ... cut a normal page}% % \end{macrocode} % In that case we put the material back in box 255 so that we can % cut a normal page. The curious set of % |\vskip|s we add is necessary to cancel out the |\splittopskip| % that got added for balancing. % \begin{macrocode} \setbox\@cclv\vbox {\vskip\topskip \vskip-\splittopskip \unvbox\mult@box % \end{macrocode} % We also have to re-add the end of environment penalty since after % this page we may want balance the remaining material. % \changes{v1.8r}{2018/01/28}{Re-add the final penalty} % \begin{macrocode} \penalty-\@Mvi }% % \end{macrocode} % We then call the standard multicol output routine which will % produce a normal page for us (remember we are still within the % OR so some part of the code in |\multi@column@out| is actually not % doing anything---perhaps this should be cleaned up at some point). % This also means that if there was an |\enlargethispage| present % it will apply to this page as |\multi@column@out| will look at % the status of |\@kludgeins|. % \begin{macrocode} \multi@column@out % \end{macrocode} % Because balancing made the columns too long we are sure that there % will be some material remaining which was put back onto the main % vertical list by |\multi@column@out|. This will also put the % explicit |\eject| penalty back so the current % |\balance@columns@out| output routine will be called again (so we % better do not add another penalty or else the OR will be called % twice and we may get scrambled results). % \changes{v1.8k}{2015/03/21}{No additional penalty here} % \begin{macrocode} \else % \end{macrocode} % If the balancing went ok, we are in the position % to apply |\page@sofar|. But first we have to set |\vsize| to a % value suitable for one column output. % \begin{macrocode} \global\vsize\@colroom \global\advance\vsize\ht\partial@page % \end{macrocode} % We also have to look at |\@kludgeins| and generate a new % |\insert| in case there was one present due to an % |\enlargethispage| command. % \changes{v1.8a}{2011/12/20}{Support for \cs{enlargethispage}} % \begin{macrocode} \ifvbox\@kludgeins \insert\@kludgeins {\unvbox\@kludgeins}\fi % \end{macrocode} % Then we |\unvbox| the |\partial@page| (which may be void if we % are not processing the first page of this \mc{} environment. % \begin{macrocode} \unvbox\partial@page % \end{macrocode} % We then handle mark structures of the columns, return the gathered % material to the main vertical list and then also reinsert the % first and last marks that have been found in the columns. % \changes{v2.0a}{2024/11/10}{Use new mark mechanism} % \begin{macrocode} \mc@handle@marks@and@reinserts {in multicol OR (balancing)}% \page@sofar \mc@reinsert@marks % \end{macrocode} % % \begin{macrocode} % \end{macrocode} % We need to add a penalty at this point which allows to break at % this point since calling the output routine may have removed the % only permissible break point thereby ``glueing'' any following % skip to the balanced box. In case there are any weird settings % for |\multicolsep| etc. this could produce funny results. % \changes{v1.5c}{1993/04/18}{added penalty at output routine exit} % \begin{macrocode} \penalty\z@ \fi } % \end{macrocode} % As we already know, reinserting of footnotes will be done in the % macro |\endmulticols|. % \end{macro} % % % \begin{macro}{\balance@columns} % This macro now does the actual balancing. % \begin{macrocode} \def\balance@columns{% % \end{macrocode} % We start by adding a forced break point at the very beginning, so that we % can split the box to height zero later on, thereby adding a known % |\splittopskip| glue at the beginning. % \changes{v1.8k}{2015/03/21}{\cs{remove@discardable@items} removed} % \begin{macrocode} \setbox\mult@box\vbox{% \penalty-\@M \unvbox\mult@box }% % \end{macrocode} % Then follow values assignments to get the |\vsplit|ting right. % We use the natural part of |\topskip| as the natural part for % |\splittopskip| and allow for a bit of undershoot and overshoot % by adding some stretch and shrink. % \changes{v1.5?}{1994/?/?}{Allow columns to come out a bit long or short} % \changes{v1.8x}{2019/10/15}{Use \cs{@maxdepth} not \cs{maxdepth} (gh/190)} % \begin{macrocode} \@tempdima\topskip \splittopskip\@tempdima \@plus\multicolundershoot \@minus\multicolovershoot \splitmaxdepth\@maxdepth % \end{macrocode} % We also have to set |\boxmaxdepth| which normally allows to % build boxes with arbitrary depth, but as we are building text % columns we really want to restrict the depth. This is necessary as % we sometimes rebox the boxes generated by |\vsplit| and then the % restriction posed by |\splitmaxdepth| gets lost. % \changes{v1.8h}{2014/09/12}{All column boxes should obey % \cs{maxdepth} (pr/4395)} % \changes{v1.8x}{2019/10/15}{Use \cs{@maxdepth} not \cs{maxdepth} (gh/190)} % \begin{macrocode} \boxmaxdepth\@maxdepth % \end{macrocode} % The next step is a bit tricky: when \TeX{} assembles material in % a box, the first line isn't preceded by interline glue, i.e. % there is no parameter like |\boxtopskip| in \TeX{}. This means % that the baseline of the first line in our box is at some % unpredictable point depending on the height of the largest % character in this line. But of course we want all columns to % align properly at the baselines of their first lines. For this % reason we have opened |\mult@box| with a |\penalty| \textsf{-10000}. % This will now allow us to split off from |\mult@box| a tiny bit % (in fact nothing since the first possible break-point is the % first item in the box). The result is that |\splittopskip| is % inserted at the top of |\mult@box| which is exactly what we like % to achieve. % \changes{v1.5?}{1994/?/?}{Do splitting to zero here} % \begin{macrocode} \setbox\@tempboxa\vsplit\mult@box to\z@ % \end{macrocode} % Next we try to find a suitable starting point for the calculation % of the column height. It should be less than the height finally % chosen, but large enough to reach this final value in only a few % iterations. The formula which is now implemented will try to % start with the nearest value which is a multiple of % |\baselineskip|. The coding is slightly tricky in \TeX{} and % there are perhaps better ways \ldots % \changes{v1.4d}{1992/03/04}{New algorithm for start height} % \begin{macrocode} \@tempdima\ht\mult@box \advance\@tempdima\dp\mult@box \divide\@tempdima\col@number % \end{macrocode} % The code above sets |\@tempdima| to the length of a column if we % simply divide the whole box into equal pieces. To get to the next % lower multiple of |\baselineskip| we convert this dimen to a % number (the number of scaled points) then divide this by % |\baselineskip| (also in scaled points) and then multiply this % result with |\baselineskip| assigning the result to |\dimen@|. % This makes |\dimen@| $\leq$ to |\@tempdimena|. % \begin{macrocode} \count@\@tempdima \divide\count@\baselineskip \dimen@\count@\baselineskip % \end{macrocode} % Next step is to correct our result by taking into account the % difference between |\topskip| and |\baselineskip|. We start by % adding |\topskip|; if this makes the result too large then we % have to subtract one |\baselineskip|. % \begin{macrocode} \advance\dimen@\topskip \ifdim \dimen@ >\@tempdima \advance\dimen@-\baselineskip \fi % \end{macrocode} % As a further restriction we want to see a minimum number of % rows in the balanced result based on the setting of the counter % |minrows|. If the starting value is lower we adjust. % \changes{v1.8w}{2019/03/01}{Provide minrows counter for balancing} % \begin{macrocode} \@tempdima\dimexpr \topskip +\c@minrows\baselineskip -\baselineskip\relax \ifnum\dimen@<\@tempdima \mult@info\@ne {Start value \the\dimen@ \space -> \the\@tempdima \space (corrected for minrows)}% \dimen@\@tempdima \fi % \end{macrocode} % At the user's request we start with a higher value (or lower, but % this usually only increases the number of tries). % \begin{macrocode} \advance\dimen@\c@unbalance\baselineskip % \end{macrocode} % We type out statistics if we were asked to do so. % \changes{v1.4f}{1992/04/28}{\cs{on@line} added to tracing info} % \begin{macrocode} \mult@info\@ne {Balance columns\on@line: \ifnum\c@unbalance=\z@\else (off balance=\number\c@unbalance)\fi \@gobbletwo}% % \end{macrocode} % But we don't allow nonsense values for a start. % \begin{macrocode} \ifnum\dimen@<\topskip \mult@info\@ne {Start value \the\dimen@ \space -> \the\topskip \space (corrected)}% \dimen@\topskip \fi % \end{macrocode} % Now we try to find the final column height. We start by setting % |\vbadness| to infinity (i.e.\ $10000$) to suppress % underfull box reports while we are trying to find an acceptable % solution. We do not need to do it in a group since at the end of % the output routine everything will be restored. The setting of % the final columns will nearly always produce underfull boxes with % badness $10000$ so there is no point in warning the user about % it. % \changes{v1.2a}{1990/02/05}{Group around main loop removed.} % \begin{macrocode} \vbadness\@M % \end{macrocode} % We also allow for overfull boxes while we trying to split the % columns. They can easily happen if we have objects with unusual depth. % \changes{v1.8h}{2014/09/12}{Do not report overfull} % \begin{macrocode} \vfuzz \maxdimen % \end{macrocode} % The variable |\last@try| will hold the dimension used in the % previous trial splitting. We initialize it with a negative value. % \changes{v1.5?}{1994/?/?}{Initialize \cs{last@try}} % \begin{macrocode} \last@try-\p@ \loop % \end{macrocode} % In order not to clutter up \TeX{}'s valuable main memory with % things that are no longer needed, we empty all globally used box % registers. This is necessary if we return to this point after an % unsuccessful trial. We use |\process@cols| for this purpose, % starting with |\mult@grightbox|. Note the extra braces around % this macro call. They are needed since \PlainTeX{}'s % |\loop|\ldots{}\allowbreak|\repeat| mechanism cannot be nested on % the same level of grouping. % \changes{v1.5a}{1992/11/04}{New box mechanism} % \begin{macrocode} {\process@cols\mult@grightbox {\global\setbox\count@ \box\voidb@x}}% % \end{macrocode} % The contents of box |\mult@box| are now copied globally to % box~|\mult@grightbox|. (This will be the right-most column, as % we shall see later.) % \begin{macrocode} \global\setbox\mult@grightbox \copy\mult@box % \end{macrocode} % We start with the assumption that the trial will be successful. % If we end up with a solution that is too bad we set % |too@bad| to \texttt{true}. We also assume that all forced breaks % (if any) will be used during balancing. If this is not the case % we record this in |forcedbreak@leftover|. % \changes{v1.5b}{1992/11/05}{New badness mechanism} % \changes{v1.8k}{2015/03/21}{Init \cs{ifforcedbreak@leftover}} % \begin{macrocode} %<*badness> \too@badfalse \forcedbreak@leftoverfalse % % \end{macrocode} % Using |\vsplit| we extract the other columns from box register % |\mult@grightbox|. This leaves box register |\mult@box| % untouched so that we can start over again if this trial was % unsuccessful. % \begin{macrocode} {\process@cols\mult@gfirstbox{% \global\setbox\count@ \vsplit\mult@grightbox to\dimen@ % \end{macrocode} % After splitting we need to ensure that there isn't any space at % the bottom, so we rebox once more. % \changes{v1.8b}{2013/08/28}{Remove discardable items at the % end of split boxes} % \changes{v1.8k}{2015/03/21}{Do not use \cs{remove@discardable@items} % here} % \begin{macrocode} \global\setbox\count@ \vbox to\dimen@ {\unvbox\count@}% % \end{macrocode} % After every split we check the badness of the resulting column, % normally the amount of extra white in the column. % \begin{macrocode} %<*badness> \ifnum\c@tracingmulticols>\@ne \@tempcnta\count@ \advance\@tempcnta-\mult@grightbox \divide\@tempcnta \tw@ \message{^^JColumn \number\@tempcnta\space badness: \the\badness\space}% \fi % \end{macrocode} % If this badness is larger than the allowed column badness % we reject this solution by setting |too@bad| to \texttt{true}. % \begin{macrocode} \ifnum\badness>\c@columnbadness \ifnum\c@tracingmulticols>\@ne \message{too bad (>\the\c@columnbadness)}% \fi \too@badtrue \fi % }}% % \end{macrocode} % There is one subtle point here: while all other constructed boxes % have a depth that is determined by |\splitmaxdepth| and/or % |\boxmaxdepth| the last box % will get a natural depth disregarding the original setting and % the value of |\splitmaxdepth| or |\boxmaxdepth|. This means that % we may end up with a very large depth in box |\mult@grightbox| % which would % make the result of the testing incorrect. So we change the value % by unboxing the box into itself. % \begin{macrocode} \global\setbox\mult@grightbox \vbox{\unvbox\mult@grightbox}% % \end{macrocode} % We also save a copy |\mult@gfirstbox| at its ``natural'' size % for later use. % \begin{macrocode} \setbox\mult@nat@firstbox \vbox{\unvcopy\mult@gfirstbox}% % \end{macrocode} % After |\process@cols| has done its job we have the following % situation: % \begin{center} % \begin{tabular}{r@{$\:\:\longleftarrow\:\:$}l} % box |\mult@rightbox| & all material \\ % box |\mult@firstbox| & first column \\ % box |\mult@firstbox|${}+2$ & second column \\ % \multicolumn{1}{c}{$\vdots$} & % \multicolumn{1}{c}{$\vdots$} \\ % box |\mult@grightbox| & last column % \end{tabular} % \end{center} % We report the height of the first column, in brackets % the natural size is given. % \changes{v1.5?}{1994/?/?}{Show natural size} % \begin{macrocode} \ifnum\c@tracingmulticols>\@ne \message{^^JFirst column = \the\dimen@\space (\the\ht\mult@nat@firstbox)}\fi % \end{macrocode} % If |\raggedcolumns| is in force older releases of this file also % shrank the first column to its natural height at this point. % This was done so that the first column doesn't run short compared % to later columns but it is actually producing incorrect results % (overprinting of text) in boundary cases, so since version v1.5q % |\raggedcolumns| means allows for all columns to run slightly short. % \changes{v1.5q}{1998/01/19}{Do not reset \cs{mult@gfirstbox} (pr2739)} % \begin{macrocode} % \ifshr@nking % \global\setbox\mult@gfirstbox % \copy\mult@nat@firstbox % \fi % \end{macrocode} % Then we give information about the last column.\footnote{With % \TeX{} version 3.141 it is now possible to use \LaTeX's % \cs{newlinechar} in the \cs{message} command, but % people with older \TeX{} versions will now get % \texttt{\string^\string^J} instead of a new line on the screen.} % \changes{v1.4a}{1992/02/12}{Changed to proper \cs{endlinechar} in\cs{message}} % \begin{macrocode} \ifnum\c@tracingmulticols>\@ne \message{<> last column = \the\ht\mult@grightbox^^J}% % \end{macrocode} % Some tracing code that we don't compile into the production version % unless asked for. It will produce huge listings of the boxes % involved in balancing in the transcript file. % \changes{v1.6f}{2004/07/03}{need to use \cs{mult@grightbox} in the loop} % \begin{macrocode} %<*debug> \ifnum\c@tracingmulticols>4 {\showoutput \batchmode \process@cols\mult@grightbox {\showbox\count@}}% \errorstopmode \fi % \fi % \end{macrocode} % We check whether our trial was successful. The test used is very % simple: we merely compare the first and the last column. Thus % the intermediate columns may be longer than the first if % |\raggedcolumns| is used. If the right-most column is % longer than the first then we start over with a larger value for % |\dimen@|. % \changes{v1.3c}{1991/03/03}{\cs{global}\cs{advance} left over from older code} % \begin{macrocode} \ifdim\ht\mult@grightbox >\dimen@ % \end{macrocode} % If the height of the last box is too large we mark this trial as % unsuccessful. % \changes{v1.5v}{1999/07/18}{Added tracing statements for % trial unsuccessful} % \begin{macrocode} %<*badness> \too@badtrue \ifnum\c@tracingmulticols>\@ne \typeout{Rejected: last column too large!}% \fi \else % \end{macrocode} % \changes{v1.5v}{1999/07/18}{Check last column if it contains forced % break and reject trial if that is the case} % % To ensure that there isn't a forced break in the last column we % try to split off a box of size |\maxdimen| from |\mult@grightbox| % (or rather from a copy of it). This should result in a void box % after the split, unless there was a forced break somewhere within % the column in which case the material after the break would have % stayed in the box. % \begin{macrocode} \setbox\@tempboxa \copy\mult@grightbox \setbox\z@\vsplit\@tempboxa to\maxdimen \ifvoid\@tempboxa % \end{macrocode} % Thus if |\@tempboxa| is void we have a valid solution. % In this case we take a closer % look at the last column to decide if this column should be made % as long as all other columns or if it should be allowed to be % shorter. % For this we first have to rebox the column into a box of the % appropriate height. If tracing is enabled we then display the % badness for this box. % \begin{macrocode} \global\setbox\mult@grightbox \vbox to\dimen@ {\unvbox\mult@grightbox}% \ifnum\c@tracingmulticols>\@ne \message{Final badness: \the\badness}% \fi % \end{macrocode} % We then compare this badness with the allowed badness for the final % column. If it does not exceed this value we use the box, otherwise % we rebox it once more and add some glue at the bottom. % \changes{v1.8h}{2014/09/12}{Use \cs{vfilmaxdepth}} % \changes{v1.8j}{2015/03/07}{Use \cs{vfil} in this case} % \begin{macrocode} \ifnum\badness>\c@finalcolumnbadness \global\setbox\mult@grightbox \vbox to\dimen@ {\unvbox\mult@grightbox\vfil}% \ifnum\c@tracingmulticols>\@ne \message{ setting natural (> \the\c@finalcolumnbadness)}% \fi \fi % \end{macrocode} % If |\@tempboxa| above was not void our trial was unsuccessful and % we report this fact and try again. % \changes{v1.6f}{2004/07/03}{\texttt{/colbreak} guard in the wrong position} % \begin{macrocode} \else % \end{macrocode} % If we have unprocessed forced breaks we normally reiterate with a % larger column size to fit them in eventually. However, if there % are simply too many of them (e.g., 3 forced breaks but only 2 % columns to balance) then this will never succeed and we would % continue growing the columns until we hit the largest possible % column size. So in addition we check how big the column size is % compared to available room and if we exceed this by % |\maxbalancingoverflow| we give up and instead of balancing cut % another normal page. To be indicate this case we set % |forcedbreak@leftover| to true. % \changes{v1.8k}{2015/03/21}{Watch out for columns growing too far in % case of forced breaks} % \changes{v1.8l}{2015/03/25}{Added additional tracing if column overflows} % \begin{macrocode} \@tempdima\@colroom \advance\@tempdima \maxbalancingoverflow \ifdim \dimen@ < \@tempdima \too@badtrue \ifnum\c@tracingmulticols>\@ne \typeout{Rejected: unprocessed forced break(s) in last column!}% \fi \else \forcedbreak@leftovertrue \ifnum\c@tracingmulticols>\@ne \typeout{Failed: columns too large with unprocessed forced break(s)!}% \fi \fi \fi \fi % \end{macrocode} % If the natural height of the first box is smaller than the % current trial size but is larger than the previous trial size it % is likely that we have missed a potentially better % solution. (This could have happened if for some reason our first % trial size was too high.) In that case we dismiss this trial and % restart using the natural height for the next trial. % \begin{macrocode} \ifdim\ht\mult@nat@firstbox<\dimen@ \ifdim\ht\mult@nat@firstbox>\last@try \too@badtrue \ifnum\c@tracingmulticols>\@ne \typeout{Retry: using natural height of first column!}% \fi \dimen@\ht\mult@nat@firstbox \last@try\dimen@ \advance\dimen@-\p@ \fi \fi % \end{macrocode} % Finally the switch |too@bad| is tested. If it was made true % either earlier on or due to a rightmost column being too large % we try again with a slightly larger value for |\dimen@|. % \begin{macrocode} \iftoo@bad % \advance\dimen@\p@ \repeat % \end{macrocode} % If we come out of the loop with the switch |forcedbreak@leftover| % set to true then balancing has failed and we should cut a normal % page. We indicate this below with |\too@badtrue| when any of the % columns get too high, so we set this flag here too in order to % get the same processing logic.\footnote{Should get cleaned up as % we now have two different routes to reach this part of the % processing.} % \changes{v1.8k}{2015/03/21}{} % \begin{macrocode} \ifforcedbreak@leftover \too@badtrue \else % \end{macrocode} % At that point |\dimen@| holds the height that was determined by % the balancing loop. % If that height for the columns turns out to be larger % than the available space (which is |\@colroom|) we squeeze the % columns into the space assuming that they will have enough % shrinkability to allow this.\footnote{This might be wrong, since % the shrinkability that accounts for the amount of material might % be present only in some columns. But it is better to try then to % give up directly.} % However, this squeezing should only be done if we are balancing % columns on the main galley and \emph{not} if we are building a % boxed multicol (in the latter case the current |\@colroom| is % irrelevant since the produced box might be moved anywhere at a % later stage). % \changes{v1.3c}{1991/03/03}{Limit column height to \cs{@colroom}} % \changes{v1.5q}{1998/01/19}{Removed setting \cs{dimen@} (pr2739)} % \changes{v1.5y}{2000/06/10}{Limit column height only in unrestricted % mode (pr/3212)} % \begin{macrocode} \if@boxedmulticols\else \ifdim\dimen@>\@colroom \dimen@\@colroom \fi \fi % \end{macrocode} % Then we move the contents of the odd-numbered box registers to % the even-numbered ones, shrinking them if requested. % We have to use |\vbox| not |\vtop| (as it was done in % the first versions) since otherwise the resulting boxes will have % no height (\TB\/ page 81). This would mean that extra % |\topskip| is added when the boxes are returned to the % page-builder via |\page@sofar|. % \changes{v1.3a}{1990/05/20}{Changed \cs{vtop} to \cs{vbox}.} % \begin{macrocode} \process@cols\mult@rightbox {\@tempcnta\count@ \advance\@tempcnta\@ne % \end{macrocode} % when putting the final column together we want overfull % information: % \begin{macrocode} \vfuzz\z@ \setbox\count@\vbox to\dimen@ {% % \end{macrocode} % % \changes{v1.8h}{2014/09/12}{Use \cs{vfilmaxdepth}} % \begin{macrocode} \vskip \z@ \@plus-\multicolundershoot \@minus-\multicolovershoot \unvbox\@tempcnta \ifshr@nking\vfilmaxdepth\fi }% % \end{macrocode} % If the resulting box is overfull there was too much material to % fit into the available space. The question though is how much? If % it wasn't more than |\maxbalancingoverflow| we accept it still to % avoid getting very little material for the next page (which we % would then have difficulties to balance). % \changes{v1.8a}{2011/12/20}{Balancing concept improved} % \begin{macrocode} \ifnum\badness>\@M \vfuzz\maxdimen % no overfull warning \setbox\@tempboxa \vbox to\dimen@ {\vskip-\maxbalancingoverflow \unvcopy\count@}% \ifnum\badness>\@M \mult@info\@ne {Balanced column more than \the\maxbalancingoverflow\space too large}% % \end{macrocode} % Fail the balancing attempt: % \begin{macrocode} \too@badtrue \else % \end{macrocode} % Otherwise report that there is a problem but within the accepted % boundary. % \begin{macrocode} \mult@info\@ne {Balanced column too large, but less than \the\maxbalancingoverflow}% \fi \fi }% % \end{macrocode} % Finally end the |\ifforcedbreak@leftover| conditional. % \changes{v1.8k}{2015/03/21}{Finish the new conditional} % \begin{macrocode} \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\maxbalancingoverflow} % Amount that balancing is allowed to overflow the available column % space. We default to 12pt which means about one line in most % layouts. % \changes{v1.8a}{2011/12/20}{\cs{maxbalancingoverflow} parameter added} % \begin{macrocode} \newdimen\maxbalancingoverflow \maxbalancingoverflow=12pt % \end{macrocode} % \end{macro} % \end{multicols} % % \begin{multicols}{2}[\subsection{The box allocations}] % % \begin{macro}{\mult@rightbox} % \begin{macro}{\mult@grightbox} % \begin{macro}{\mult@firstbox} % \begin{macro}{\mult@gfirstbox} % Early releases of these macros used the first box registers % 0, 2, 4,\ldots\ for global boxes and 1, 3, 5,\ldots\ for the % corresponding local boxes. (You might still find some traces % of this setup in the documentation, sigh.) This produced a problem % at the moment we had more than 5 columns because then officially % allocated boxes were overwritten by the algorithm. % The new release now uses private box registers. % % There was in fact a bug in the new implementation because at one % point \LaTeX{} started to use the extended registers and so % jumped from below 255 to above omitting the boxes allocated for % inserts and the output page box. % % So nowadays we really have to check if we get the full sequence % of boxes allocated without holes (i.e., $2\times\textit{max % cols}+1$) and if not alter the allocation registers to start % allocating after 255. This is all done quite low-level by looking % directly at the values of the allocation counters. % \changes{v1.8y}{2019/12/09}{Allow for 20 columns (gh/237)} % \changes{v1.9b}{2021/10/22}{Drop one unnecessary box allocation (gh/701)} % \begin{macrocode} \ifnum\numexpr \count20-\count14-1<40 % this is = 2 * 20 \count14=\@cclv \fi % \end{macrocode} % % \begin{macrocode} \newbox\mult@rightbox \newbox\mult@grightbox \newbox\mult@firstbox \newbox\mult@gfirstbox \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \newbox\@tempa\newbox\@tempa \let\@tempa\relax % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \end{multicols} % % % \begin{multicols}{2}[\section{New macros and hacks for version 1.2}] % % \begin{macro}{\emergencystretch} % \begin{macro}{\setemergencystretch} % If we don't use \TeX{} 3.0 |\emergencystretch| is undefined % so in this case we simply add it as an unused \meta{dimen} % register. % \changes{v1.4j}{1992/06/25}{Setting of \cs{emergencystretch} on top % removed.} % \begin{macrocode} \@ifundefined{emergencystretch} {\newdimen\emergencystretch}{} % \end{macrocode} % \changes{v1.2a}{1990/02/05}{Macro added.} % My tests showed that the following formula worked pretty well. % Nevertheless the |\setemergencystretch| macro also gets % |\hsize| as second argument to enable the user to try % different formulae. % \begin{macrocode} \def\setemergencystretch#1#2{% \emergencystretch 4pt \multiply\emergencystretch#1} % \end{macrocode} % \end{macro} % \end{macro} % \begin{macro}{\set@floatcmds} % \changes{v1.2a}{1990/02/05}{Macro added.} % \changes{v1.5g}{1994/06/07}{Updated since floats have changed} % \changes{v1.5j}{1994/06/07}{Updated since floats have changed again} % \changes{v1.5l}{1995/10/19}{Added \cs{@largefloatcheck}} % \changes{v1.6g}{2006/02/23}{Added \cs{@minipagefalse}} % \changes{v1.6h}{2008/12/05}{Use \cs{@endfloatbox} to better support % the modifications done by the float package} % \changes{v1.9i}{2024/09/14}{Added tagging support} % Even if this should be used as a hook we use a |@| in the % name since it is more for experts. % For now we test if the socket is already defined % \begin{macrocode} \def\set@floatcmds{% \let\@dblfloat\@dbflt \def\end@dblfloat{\@endfloatbox \UseTaggingSocket{float/end}% \@largefloatcheck \outer@nobreak % \end{macrocode} % This is cheap (deferring the floats until after the current page) % but any other solution would go deep into \LaTeX's output % routine and I don't like to work on it until I know which parts % of the output routine have to be reimplemented anyway for % \LaTeX3. % \begin{macrocode} \ifnum\@floatpenalty<\z@ % \end{macrocode} % We have to add the float to the |\@deferlist| because we assume % that outside the \mc{} environment we are in one column mode. % This is not entirely correct, I already used the \mc{} % environment inside of \LaTeX{}s |\twocolumn| declaration but it % will do for most applications. % \begin{macrocode} \@cons\@deferlist\@currbox \fi \ifnum\@floatpenalty=-\@Mii \@Esphack \UseTaggingSocket{float/hmode/end}% \fi}} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\remove@discardable@items} % There are situations when we may have some space at the end of a % column and this macro here will attempt to get rid of it. The % typical \LaTeX{} sequence is a series of self-canceling glues so % if we remove them recursively we are usually fine. % % Special care is needed with handling |\vspace*| as that % corresponds to |\penalty10000|, |\vskip |, followed by % |\vskip 0pt|. If we see this sequence going backwards in the % vertical list we assume that this is a ``desired'' space. We % therefore stop the recursion and reinsert the spaces. % % As the multicol code sometimes add an explicit penalty at the end % of a column we first attempt to remove it in case it is there. % \changes{v1.8m}{2015/03/31}{Another rewrite of % \cs{remove@discardable@items} hopefully okay now} % \begin{macrocode} \skip0=0pt \edef\the@zero@skip{\the\skip0} \def\remove@discardable@items{% \unpenalty % \end{macrocode} % Save a previous skip (if there) and then remove it, we can't % really tell the difference between no skip an a skip of zero but % that's life. % \begin{macrocode} \edef\@tempa{\the\lastskip}% %\typeout{s1=\@tempa}% \unskip % \end{macrocode} % If it was a zero skip (or none) we save the next previous skip % (if any). % \begin{macrocode} \ifx\@tempa\the@zero@skip \edef\@tempb{\the\lastskip}% %\typeout{s2=\@tempb}% % \end{macrocode} % If this one again was zero (or more likely not there in the first % place) we stop. % \begin{macrocode} \ifx\@tempb\the@zero@skip \else % \end{macrocode} % Otherwise we remove this ``real'' skip. Then we look if it was % preceded by a penalty of 10000 (i.e., a |\nobreak|) % \begin{macrocode} \unskip %\typeout{p=\lastpenalty}% \ifnum \lastpenalty=\@M % \end{macrocode} % If so this was a |\vspace*| or something equivalent to % it. Therefore we reintroduce the skips and stop. Otherwise we % recurse. % \begin{macrocode} \vskip\@tempb\vskip\@tempa\relax \else \remove@discardable@items \fi \fi \else % \end{macrocode} % If the first skip was a non-zero skip we recurse as well. % \begin{macrocode} \remove@discardable@items \fi } % \end{macrocode} % \end{macro} % % \begin{macrocode} %<*badness> \newif\iftoo@bad \def\too@badtrue{\global\let\iftoo@bad\iftrue} \def\too@badfalse{\global\let\iftoo@bad\iffalse} % \end{macrocode} % % \changes{v1.8k}{2015/03/21}{The new switch} % \begin{macrocode} \newif\ifforcedbreak@leftover % \end{macrocode} % % \begin{macro}{\c@minrows} % \changes{v1.8w}{2019/03/01}{Provide minrows counter for balancing} % \begin{macrocode} \newcount\c@minrows \c@minrows=1 % \end{macrocode} % \end{macro} % % \begin{macro}{\c@columnbadness} % \begin{macro}{\c@finalcolumnbadness} % \begin{macrocode} \newcount\c@columnbadness \c@columnbadness=10000 \newcount\c@finalcolumnbadness \c@finalcolumnbadness=9999 \newdimen\last@try % \end{macrocode} % % \changes{v1.5z1}{2003/02/17}{Change wrong default for % \cs{multicolovershoot} to zero (pr/3465).} % \begin{macrocode} \newdimen\multicolovershoot \newdimen\multicolundershoot \multicolovershoot=0pt \multicolundershoot=2pt \newbox\mult@nat@firstbox % % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\mult@info} % A helper for producing info messages % \begin{macrocode} \def\mult@info#1#2{% \ifnum\c@tracingmulticols>#1% \GenericWarning {(multicol)\@spaces\@spaces}% {Package multicol: #2}% \fi } % \end{macrocode} % \end{macro} % % \end{multicols} % % % \begin{multicols}{2}[\section{Fixing the % \cs{columnwidth}}] % % \begin{macro}{\@footnotetext} % \changes{v1.5o}{1997/11/16}{Redefinition added pr/2664.} % \changes{v1.5r}{1998/08/17}{Use \cs{@footnotetext} but with % local change to \cs{columnwidth}.} % \begin{macro}{\mult@footnotetext} % \changes{v1.5r}{1998/08/17}{Macro removed again.} % If we store the current column width in |\columnwidth| we have % to redefine the internal |\@footnotetext| macro to use |\textwidth| % for the width of the footnotes rather than using the original % definition. % % Starting with version v1.5r this is now done in a way that the original % definition is still used, except that locally |\columnwidth| is set to % |\textwidth|. % % This solves two problems: first redefinitions of |\@footnotetext| % done by a class will correctly survive and second if multicols is % used inside a minipage environment the special definition of % |\@footnotetext| in that environment will be picked up and not the % one for the main galley (the latter would result in all footnotes % getting lost in that case). % % See the definition of the |\multicols| command further up for the exact % code. % \end{macro} % \end{macro} % \end{multicols} % % % \section{Further extensions} % % This section contains code for extensions added to this package % over time. Not all of them may be active, some might sit dormant and % wait for being activated in some later release. % % \subsection{Not balancing the columns} % % This is fairly trivial to implement. we just have to disable the % balancing output routine and replace it by the one that ships out % the other pages. % % \begin{macro}{\multicols*} % \changes{v1.5q}{1998/01/19}{Macro added} % The code for this environment was suggested by Matthias Clasen. % \begin{macrocode} %<*nobalance> \@namedef{multicols*}{% % \end{macrocode} % If we are not on the main galley, i.e., inside a box of some % sort, that approach will not work since we don't have a vertical % size for the box so we better warn that we balance anyway. % \begin{macrocode} \ifinner \PackageWarning{multicol}% {multicols* inside a box does not make sense.\MessageBreak Going to balance anyway}% \else % \end{macrocode} % If we aren't balancing we change the |\balance@columns@out| to % work like the normal output routine that cuts normal % pages. However, there is a catch: In case the last page we cut % (after seeing the end of the environment) is actually larger than % a page (for example, if it contains more |\columnbreak| commands % than columns) we end up with some leftover material that is % returned to the main galley, but now the environment end penalty % is missing. So we add another one here too. Of course that % shouldn't be done if there is really only a single final page, % but fortunately in that case we have just finished a page and any % penalty on the recent contributions will be discarded, thus the % extra one is harmless---puh. % \changes{v1.8t}{2018/06/26}{Re-add end penalty for % \texttt{multicols*} environment to guard against leftovers (git/53)} % \begin{macrocode} \def\balance@columns@out {\multi@column@out \penalty-\@Mvi }% \fi \begin{multicols} } % \end{macrocode} % \end{macro} % % \begin{macro}{\endmulticols*} % When ending the environment we simply end the inner % \texttt{multicols} environment, except that we better also stick % in some stretchable vertical glue so that the last column still % containing text is not vertically stretched out. % % We do this as follows: first we ensure that we are back in vertical mode % and then we cancel out |\lastskip| if it was % positive (in case of a negative glue we assume that it was % deliberate, for a deliberate positive glue one needs to use % |\vspace*|). We can't simply use |\remove@discardable@items| here % as this only works inside boxes but we are here on the main % vertical list. % % Then we back up by |\prevdepth| but not more than |\boxmaxdepth| % so that a baseline of the last box is now at the bottom. This way % the material will align properly in case something like |\vfill| % spreads it out after all. % Finally we append |\vfil| to put white space at the bottom of the % column, but we only do this if we aren't anyway doing |\raggedcolumns|. % \changes{v1.5q}{1998/01/19}{Macro added} % \changes{v1.8h}{2014/09/12}{Use \cs{vfilmaxdepth}} % \changes{v1.8i}{2014/10/28}{Add \cs{null} to hide the final fill and only add % vertical space if not doing \cs{raggedcolumns}} % \changes{v1.8j}{2015/03/07}{Redesign the whole approach.} % \changes{v1.8k}{2015/03/21}{And a bit more redesign because of the % change in \cs{remove@discardable@items}} % \changes{v1.8o}{2016/02/08}{Ensure we are back in vmode before using % \cs{prevdepth} (pr/4448)} % \begin{macrocode} \@namedef{endmulticols*}{% \par \ifdim\lastskip>\z@ \vskip-\lastskip \fi \ifdim \prevdepth>\z@ \vskip-\ifdim\prevdepth>\boxmaxdepth \boxmaxdepth \else \prevdepth \fi \fi \ifshr@nking\else \vfil \fi \end{multicols}} % % \end{macrocode} % \end{macro} % % % \subsection{Manual column breaking} \label{sec:colbreak} % % The problem with manual page breaks within \mc{} is the fact that % during collection of material for all columns a page-forcing penalty % (i.e. -10000 or higher) would stop the collecting pass which is not % quite what is desired. On the other hand, using a penalty like -9999 % would mean that there would be occasions where the |\vsplit|ing % operations within \mc{} would ignore that penalty and still choose a % different break point. % % For this reason the current implementation % uses a completely different approach. In a nutshell it extends the \LaTeX{} % output routine handling by introducing an additional penalty flag % (i.e., a penalty which is forcing but higher than -10000 so that the % output routine can look at this value and thus knows why it has been % called). % % Inside the output routine we test for this value and if it appears % we do two things: save the galley up to this point in a special box % for later use and reduce the |\vsize| by the height of the material % seen. This way the forcing penalty is now hidden in that box and we % can restart the collection process for the remaining % columns. (This is done in |\speci@ls| above.) % % In the output routines that do the |\vsplit|ting either for % balancing or for a full page we simply combine box~255 with the % saved box thus getting a single box for splitting which now % contains forcing breaks in the right positions. % % % \begin{macro}{\columnbreak} % \changes{v1.5u}{1999/05/25}{Macro added} % \changes{v1.9a}{2021/10/08}{Added optional argument for conditional break} % \changes{v1.9b}{2021/10/28}{Corrected error message text (gh/703)} % |\columnbreak| is modeled after |\pagebreak| except that we % generate a penalty -10005. % \begin{macrocode} \mathchardef\@Mv=10005 \newcommand\columnbreak[1][4]{% % \end{macrocode} % We have to ensure that it is only used within a \mc{} % environment since if that penalty would be seen by the unmodified % \LaTeX{} output routine strange things would happen. % \begin{macrocode} \ifnum\col@number<\tw@ \PackageError{multicol}% {\noexpand\columnbreak outside multicols}% {This command can only be used within a multicols or multicols* environment.}% \else % \end{macrocode} % Increasingly lower penalty based on argument value. This is like % \cs{pagebreak} but we use other penalty values as the \LaTeX{} % defaults are rather useless for pagination. % \begin{macrocode} \edef\mc@break@pen {-\ifcase#1\@m\or 3333\or 6666\or 9999\else\@Mv\fi\relax}% \ifvmode \penalty \mc@break@pen \else \@bsphack \vadjust{\penalty \mc@break@pen}% \@esphack \fi \fi} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\newcolumn} % \changes{v1.9a}{2021/10/08}{Macro added} % This is modeled after \cs{newpage} but for column breaks. % \begin{macrocode} \newcommand\newcolumn{% \ifnum\col@number<\tw@ \PackageError{multicol}% {\noexpand\newcolumn outside multicols}% {This command can only be used within a multicols or multicols* environment.}% \else \ifvmode % \end{macrocode} % We need to guard the \cs{vfill} from disappearing. % \changes{v1.9d}{2021/12/05}{Guard the \cs{vfill} (sx/624940)} % \begin{macrocode} \nobreak\vfill\kern\z@\penalty -\@Mv\relax \else \@bsphack \vadjust{\nobreak\vfill\kern\z@\penalty -\@Mv\relax}% \@esphack \fi \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\colbreak@box} % \changes{v1.5u}{1999/05/25}{Macro added} % Need a box to collect the galley up to the column break. % \begin{macrocode} \newbox\colbreak@box % % \end{macrocode} % \end{macro} % % % \subsection{Supporting right-to-left languages} \label{sec:RL} % % % \changes{v1.7a}{2010/10/24}{RL language support added} % \changes{v1.7b}{2011/12/18}{RL language support fixed} % % \begin{macro}{\LR@column@boxes} % |\LR@column@boxes| is called when we are assembling the columns for left % to right typesetting. When we start we are inside an |\hbox| of % full width. % Left to right typesetting is fairly easy, we basically output % each column box intermixed with vertical rules and proper % spacing. As this happens inside a box of a defined width the % rules and the columns automatically get into the right positions. % \begin{macrocode} \def\LR@column@boxes{% % \end{macrocode} % We loop through the columns with |\process@cols| % \begin{macrocode} \process@cols\mult@firstbox{% % \end{macrocode} % If the depth of the current box is larger than the maximum found % so far in |\dimen2| we update that register for later use. % \changes{v1.6a}{2003/03/15}{Preparing for adjusting \cs{prevdepth}} % \begin{macrocode} \ifdim\dp\count@>\dimen\tw@ \global\dimen\tw@\dp\count@ \fi % \end{macrocode} % If the \texttt{colaction} option is given we write out status % information about the current column, otherwise the next command % does nothing. % \changes{v1.8e}{2014/04/23}{Support \cs{docolaction}} % \begin{macrocode} \mc@col@status@write % \end{macrocode} % The typeset box followed by the column rule material % \begin{macrocode} \box\count@ \hss{\columnseprulecolor\vrule \@width\columnseprule}\hss}% % \end{macrocode} % As you will have noticed, we started with box register % |\mult@firstbox| (i.e.\ % the left column). So this time |\count@| looped through 2, % 4,\ldots\ (plus the appropriate offset). % Finally we add box |\mult@rightbox| and we are done. % \changes{v1.5a}{1992/11/04}{New box mechanism} % \changes{v1.6a}{2003/03/15}{Preparing for adjusting \cs{prevdepth}} % Again we may have to update |\dimen\tw@|. % \begin{macrocode} \ifdim\dp\mult@rightbox>\dimen\tw@ \global\dimen\tw@\dp\mult@rightbox \fi % \end{macrocode} % If the \texttt{colaction} option is given we write out status % information about the last column, otherwise the next command % does nothing. % \changes{v1.8e}{2014/04/23}{Support \cs{docolaction}} % \begin{macrocode} \mc@lastcol@status@write \box\mult@rightbox } % \end{macrocode} % \end{macro} % \begin{macro}{\RL@column@boxes} % Assembling the boxes for right to left typesetting is far more % complicated. When I first tried to build a solution for this my % thinking was that all that is necessary to do is to reverse the % order of the columns. But such an approach produces a subtle bug: % If we work this way then the first column put on the page will be % the last column of the text to read. and this means that the % order in which \TeX{} executes write statements or assembles mark % material will not happen in the order of the textual flow. So if, % for example each column contains a section command then these % sections will appear in reverse order in the table of content. % % For this reason some amount of gymnastics is needed to add the % columns in their natural flow. % \begin{macrocode} \def\RL@column@boxes{% % \end{macrocode} % First step is to put all rules in the right place (without adding % the comes which are instead represented by a space of |\hsize|. % \begin{macrocode} \process@cols\mult@firstbox{% \hskip\hsize \hss{\columnseprulecolor\vrule \@width\columnseprule}\hss }% \hskip\hsize % \end{macrocode} % At this point in the code our typesetting reference point is at % the right end of the rightmost column (or rather where that column % should appear). % % We are now typesetting all columns by first backing up by their % width (which is |\hsize|) then typesetting the box and then % backing up again, but this time further, i.e., also across the % column separation. That will then enable us to typeset the next % column using the same approach until we are done with all but the % final column. % \begin{macrocode} \process@cols\mult@firstbox{% \ifdim\dp\count@>\dimen\tw@ \global\dimen\tw@\dp\count@ \fi \hskip-\hsize % \end{macrocode} % % \changes{v1.8e}{2014/04/23}{Support \cs{docolaction}} % \begin{macrocode} \mc@col@status@write \box\count@ \hskip-\hsize \hskip-\columnsep }% % \end{macrocode} % The approach for the final column is similar only that we do not % have to back up over any column gap. % \begin{macrocode} \ifdim\dp\mult@rightbox>\dimen\tw@ \global\dimen\tw@\dp\mult@rightbox \fi \hskip-\hsize % \end{macrocode} % % \changes{v1.8e}{2014/04/23}{Support \cs{docolaction}} % \begin{macrocode} \mc@lastcol@status@write \box\mult@rightbox \hskip-\hsize % \end{macrocode} % However we do have to move the reference point to its right % place: to make the rules appear at the expected places, we should % get the typesetting position to the far right again. As we at the % moment at the far left we skip to the far right like this: % \begin{macrocode} \hskip\full@width } % \end{macrocode} % \end{macro} % % \begin{macro}{\RLmulticolcolumns} % \begin{macro}{\LRmulticolcolumns} % \begin{macro}{\mc@align@columns} % Macros to switch between left-right and right-left typesetting. In LR % typesetting the |\LR@column@boxes| is used to combine % the columns. When typesetting right to left the |\RL@column@boxes| % is used instead. % \begin{macrocode} \newcommand\RLmulticolcolumns {\let\mc@align@columns \RL@column@boxes} \newcommand\LRmulticolcolumns {\let\mc@align@columns \LR@column@boxes} % \end{macrocode} % The default is left-to-right: % \begin{macrocode} \LRmulticolcolumns % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \subsection{Supporting \texttt{\textbackslash docolaction}} % % \changes{v1.8e}{2014/04/23}{Support \cs{docolaction}} % % Whenever we want to do something that depends on the current % column we execute \verb=\docolaction=. This command takes one % optional and three mandatory arguments. The mandatory ones denote % what to do if this is a ``left'', ``middle'', or ``right'' column % and the optional one is simply there to say what to do if we don't % know (default is to use the ``left'' column action in that case). % % \begin{macro}{\mc@col@check@num} % We use one counter \verb=\mc@col@check@num= to generate us unique % label names. Each time we execute \verb=\docolaction= we increment % this counter to get a new name. % \begin{macrocode} \newcount\mc@col@check@num % \end{macrocode} % \end{macro} % % The generated ``labels'' are named %\begin{verbatim} %\mc@col-\the\mc@col@check@num %\end{verbatim} % and they hold as values the % numbers 1, 2, or 3 denoting the current column type. % \begin{macro}{\docolaction} % % The \verb=\docolaction= scans for a star and optional argument % and 3 mandatory ones, but we do this in chunks (not having xparse % available).\footnote{We can do better now, as % \cs{NewDocumentCommand} is part of the kernel. So this should be % cleaned up one day.} % % \changes{v1.8u}{2018/11/09}{Support star with \cs{docolaction}} % \begin{macrocode} \newcommand\docolaction{% % \end{macrocode} % First check is the support is enabled. % \begin{macrocode} \ifx\mc@col@status@write\relax \PackageError{multicol}% {Option 'colaction' not selected}% {\string\docolaction\space requires the use of the 'colaction' option on the package}% \fi % \end{macrocode} % Then prepare \verb=\mc@col@type=. % \begin{macrocode} \global\advance\mc@col@check@num\@ne \edef\mc@col@type{\expandafter\ifx \csname mc@col-\the\mc@col@check@num \endcsname\relax 0\else \csname mc@col-\the\mc@col@check@num \endcsname \fi}% % \end{macrocode} % Finally check for a star, record this information and then call % \verb=\@docolaction= to do the rest. % \begin{macrocode} \@ifstar {\@docolactionstartrue \@docolaction}% {\@docolactionstarfalse\@docolaction}% } % \end{macrocode} % % \begin{macrocode} \newcommand\@docolaction[4][1]{% % \end{macrocode} % % How does the column number get associated with our label? We % do this by writing another line into the aux file. Here are the % preparations. % \begin{macrocode} \edef\@docolactioncheck{\write\@auxout {\string\mc@set@col@status {mc@col-\the\mc@col@check@num}% {\mc@col@type}}}% % \end{macrocode} % Where we do the actual \verb=\write= depends on the whether or % not we gave seen a \texttt{*}. If yes, we do it first and then % execute the code argument, otherwise we execute that code first % and check at the point after that. % \begin{macrocode} \if@docolactionstar \@docolactioncheck \fi % \end{macrocode} % We prefix with 0 so that an unknown label (that returns % \verb=\relax=) will result in case 0 % \begin{macrocode} \ifcase \mc@col@type\relax % \end{macrocode} % If column is unknown we use the default action or the action % denoted by the optional argument (so that arg can take the value % 1, 2, 3). % \begin{macrocode} \ifcase #1\or #2\or#3\or#4\fi \or % \end{macrocode} % Otherwise we know (or think we know) that this is a first, middle, % or last column: % \begin{macrocode} #2% % 1 First col \or #3% % 2 any middle col \or #4% % 3 last col \else \ERRORwrongdefaultgiven \fi % \end{macrocode} % \begin{macrocode} \if@docolactionstar \else \@docolactioncheck \fi } % \end{macrocode} % \end{macro} % % Here is the if used above: % \begin{macrocode} \newif\if@docolactionstar % \end{macrocode} % % Because of extra data writing to the aux file the aux file will % now contain something like the following after the document is % processed the first time: %\begin{verbatim} %\relax %\mc@col@status{1} %\mc@set@col@status{lcol-1}{0} %\mc@col@status{2} %\mc@set@col@status{lcol-2}{0} %\mc@col@status{3} %\mc@set@col@status{lcol-3}{0} %\mc@col@status{1} %\mc@col@status{2} %\mc@col@status{3} %\mc@set@col@status{lcol-4}{0} %\end{verbatim} % The \verb=\mc@col@status= line denotes the column type and has been % written out just before corresponding the column box was placed % onto the page. % The\verb=\mc@set@col@status= lines have been written out as part % of shipping the column boxes out, e.g., % \verb=\mc@set@col@status{lcol-1}{0}= was therefore somewhere within % the first column as it appears between \verb=\mc@col@status{1}= % and \verb=\mc@col@status{2}= % The second argument in that line is the value used in the previous % run (or zero if there was no previous run. We can use this to % determine if a rerun is necessary. % % Thus with this knowledge we can set things up to get the labels % working. % % % \begin{macro}{\mc@col@status} % % When the aux file is read in \verb=\mc@col@status= is used to set % \verb=\mc@curr@col@status=: % \begin{macrocode} \def\mc@col@status#1{% \gdef\mc@curr@col@status{#1}} % \end{macrocode} % \end{macro} % % % % \begin{macro}{\mc@set@col@status} % % And when \verb=\mc@set@col@status= is executed we can simply set % up the label by associating it with the \verb=\mc@curr@col@status= % and ignore the second argument: % \begin{macrocode} \def\mc@set@col@status#1#2{% \global\expandafter\let\csname #1\endcsname \mc@curr@col@status} % \end{macrocode} % The above definition is being used when the \texttt{.aux} file is % read in at the beginning. At the end we need a different % definition to test if another typesetting run is needed. There we % compare the value used in the current run (stored in the second % argument) with the value used on the next run. If those two values % differ we set \verb=@tempswa= to false which will trigger the % ``Label(s) may have changed'' warning. % \begin{macrocode} \AtEndDocument{\def\mc@set@col@status#1#2{% \ifnum #2=\mc@curr@col@status\else \@tempswatrue \fi}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{mc@firstcol} % Finally, as part of determining in which column we are, we used a % switch inside |\mc@col@status@write| to determine if we are in the % first column or not. % \begin{macrocode} \newif\ifmc@firstcol \mc@firstcoltrue % \end{macrocode} % \end{macro} % % % % % \subsection{Using the new mark mechanism} % % \subsubsection{Helpers} % % \changes{v2.0a}{2024/11/10}{Using the new mark mechanism} % \begin{macrocode} \ExplSyntaxOn %<@@=mc> % \end{macrocode} % % % % \begin{macro}{\g_@@_curr_col_int} % Counter for tracking the current column number. At the start of a % \mc{} environment is holds the number of columns for % which there is currently \texttt{mcol-...} data (i.e., the number % of columns in the last \mc{} environment). % \begin{macrocode} \int_new:N \g_@@_curr_col_int % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@@_debug_marks:n} % For now we reuse the internal debugging interface of ltmarks, % this will probably change % \begin{macrocode} \cs_new:Npn \@@_debug_marks:n #1 { \__mark_debug:n {#1} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_update_mcol_structures:} % % Helper function to update the \texttt{mcol-...} regions when we % finish a page while within a \mc{} environment or when we finish % the \mc{} and return the balanced columns back to the galley. % % \begin{macrocode} \cs_new_protected:Npn \@@_update_mcol_structures: { \@@_debug_marks:n { \typeout{Marks:~ update~ mcol~ structures~ (multicol)} } % \end{macrocode} % It might be possible that there was a previous \mc{} (either % before the current one, or a boxed one inside) and that one might % have had more columns than the current one. If so, we should make these % column structures an error as they are no longer valid (or at % least empty them, not sure what is better). % \begin{macrocode} \int_step_inline:nnn {\col@number + 1} { \g_@@_curr_col_int } { \mark_set_structure_to_err:n { mcol - ##1 } } % \end{macrocode} % % There is no need to do anything to \texttt{mcol-1} up to % \texttt{mcol-\meta{\cs{col@number}}} because those regions get % new data in a second. % % Once we have done this we reset the column counter for further % processing. % \begin{macrocode} \int_gset:Nn \g_@@_curr_col_int {1} % \end{macrocode} % Now we loop through all the assembled column material, using the % \texttt{column} and \texttt{previous-column} regions as an % intermediate holding area. % \begin{macrocode} \process@cols\mult@firstbox { \mark_update_structure_from_material:nn %fmi {mcol} {column} {\unvcopy\count@} % \end{macrocode} % Once the \texttt{column} region got updated we copy it to % \texttt{mcol-\meta{\cs{\detokenize{g_@@_curr_col_int}}}} and then increment % the counter. % \begin{macrocode} \mark_copy_structure:nn {mcol - \int_use:N\g_@@_curr_col_int } %fmi {mcol} {column} \int_gincr:N \g_@@_curr_col_int } % \end{macrocode} % The above loop takes care of all columns, except for the last one % (which is stored in \cs{mult@rightbox}. So we have to do that separately. % \begin{macrocode} \mark_update_structure_from_material:nn %fmi {mcol} {column} {\unvcopy\mult@rightbox} \mark_copy_structure:nn { mcol - \int_use:N\g_@@_curr_col_int } %fmi {mcol} {column} % \end{macrocode} % Two more aliases to take care of: \texttt{first-column} and % \texttt{last-column} and we are done: % \begin{macrocode} \mark_copy_structure:nn{first-column}{mcol-1} %fmi \mark_copy_structure:nn{last-column} {mcol} \mark_copy_structure:nn{last-column} {column} } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_update_page_structures:} % If we are making a page while inside a \mc{} environment, we also % have to take care of the page region. % \begin{macrocode} \cs_new_protected:Npn \@@_update_page_structures: { \@@_debug_marks:n { \typeout{Marks:~ update~ page~ structure~ (multicol)} } % \end{macrocode} % Since for the \texttt{page} region we are only interested in the % top, first, and last marks on the whole page regardless in which % column they appear, we simply string together all columns in a big % box and update the structure from that. % \begin{macrocode} \mark_update_structure_from_material:nn {page} { % \end{macrocode} % And we better not forget the \cs{partial@page} in case this is % the first page of the \mc{} (on later pages this box will be void). % \begin{macrocode} \unvcopy\partial@page \process@cols \mult@firstbox { \unvcopy\count@ } \unvcopy\mult@rightbox } } % \end{macrocode} % \end{macro} % % \begin{macro}{\@@_prepare_mark_reinserts:} % % When finishing a \mc{} environment, we have to return marks (in % then boxed columns) to the current page so that they are % available when that page is produced. % This is what this helper does. % \begin{macrocode} \cs_new_protected:Npn \@@_prepare_mark_reinserts: { \@@_debug_marks:n { \typeout{Marks:~ prepare~ for~ reinserting~ marks~ (multicol)} } % \end{macrocode} % We are only interested in the top, first, and last marks of each % class regardless in which column they appeared, so we can copy % all column boxes together and process them in one go. The result % is returned in \cs{\detokenize{l_@@_first_marks_tl}} and % \cs{\detokenize{l_@@_last_marks_tl}} in form of \cs{\detokenize{mark_insert:nn}} statements % so we can later execute such token lists directly (and if there % were no marks they will be empty). % \begin{macrocode} \mark_get_marks_for_reinsertion:nNN { \process@cols \mult@firstbox { \unvcopy\count@ } \unvcopy\mult@rightbox } \l_@@_first_marks_tl \l_@@_last_marks_tl } % \end{macrocode} % And here are the token lists used above. % \begin{macrocode} \tl_new:N \l_@@_first_marks_tl \tl_new:N \l_@@_last_marks_tl % \end{macrocode} % \end{macro} % % % \begin{macro}{\mc@reinsert@marks} % So reinserting it just means executing the token lists (with some % surrounding debugging statements). % \begin{macrocode} \cs_new_protected:Npn \mc@reinsert@marks{ \@@_debug_marks:n { \typeout{Marks:~ --~ reinsert~ marks~ (multicol)} } \l_@@_first_marks_tl \l_@@_last_marks_tl \@@_debug_marks:n { \typeout{Marks:~ --~ finished~ reinserting~ marks~ (multicol)} } } % \end{macrocode} % \end{macro} % % % \subsubsection{Interfaces used in the \mc{} code and its output routines} % % % \begin{macro}{\mc@prepare@mark@regions} % When a \mc{} environment starts we need to clear the column % region as it it may contain quite old data. Otherwise, that data % would be used to generate the top marks and that would be % obviously wrong for the first column. % \begin{macrocode} \cs_new_protected:Npn \mc@prepare@mark@regions { % \end{macrocode} % However, before we do this we need to save away the current % column data in case this is a boxed multicol, because when that % finishes we need to restore the previous state --- this is not % necessary for a normal \mc{} environment, because there the % \texttt{column} region is overwritten in the standard output % routine by copying the \texttt{page} region. % \begin{macrocode} \legacy_if:nT { @boxedmulticols } { \mark_copy_structure:nn{saved-column}{column} } \@@_debug_marks:n { \typeout{Marks:~ empty~ mcol~ regions~ (multicol)} } \mark_clear_structure:n {column} } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\mc@handle@marks@and@reinserts} % % If a \mc{} ends the columns are balanced and then returned to the % galley. in that situation we do have to prepare the % \texttt{mcol-...} regions and also do this reinsertion. % \begin{macrocode} \cs_new_protected:Npn \mc@handle@marks@and@reinserts #1 { \@@_update_mcol_structures: % \end{macrocode} % Show the current region status when debugging: % \begin{macrocode} \@@_debug_marks:n { \__mark_status:nn {#1} {\the\col@number} } % \end{macrocode} % Then prepare for reinserting the marks: % \begin{macrocode} \@@_prepare_mark_reinserts: % \end{macrocode} % Finally, we restore the \texttt{column} region in case this was a % boxed \mc{} environment. % \begin{macrocode} \legacy_if:nT { @boxedmulticols } { \mark_copy_structure:nn {column}{saved-column} } } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\mc@handle@col@andpage@marks} % If a page is generated while we are processing a \mc{} then we % have to update the \texttt{mcol-...} regions but also the % \texttt{page} region. % \begin{macrocode} \cs_new_protected:Npn \mc@handle@col@andpage@marks #1 { \@@_update_mcol_structures: \@@_update_page_structures: % \end{macrocode} % Once done we display the current status of the marks. % \begin{macrocode} \@@_debug_marks:n { \__mark_status:nn {#1} {\the\col@number} } } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\leftmark,\rightmark} % We change the legacy \cs{leftmark} and \cs{rightmark} to use % the new mark mechanism. For now we do this only if pkg{multicol} % is loaded, but eventually this will move to the kernel which then % also simplifies the definitions for \cs{markboth} and friends. % % These commands should be expandable, so no protection. % \changes{v2.0a}{2024/11/10}{Use the new mark mechanism} % \begin{macrocode} \cs_set:Npn \leftmark {\mark_use_last:nn{page}{2e-left}} \cs_set:Npn \rightmark {\mark_use_first:nn{page}{2e-right}} % \end{macrocode} % \end{macro} % % \begin{macrocode} %<@@=> % \end{macrocode} % % % % % % % % \subsection{Tagging support} % % Here we collect adjustments necessary for tagging support, e.g., % before the 2024-11-01 release it was necessary to allocate two % float sockets. By now they are part of the kernel and their plugs % are currently defined by \pkg{tagpdf}. % \begin{macrocode} %\str_if_exist:cF { l__socket_tagsupport/float/end_plug_str } % { % \NewSocket{tagsupport/float/end}{0} % \NewSocket{tagsupport/float/hmode/end}{0} % } % \end{macrocode} % % This one is only relevant for \pkg{multicol} so declared here. % \begin{macrocode} \NewSocket{tagsupport/page@sofar}{0} % \end{macrocode} % % The plug definition for now just uses the definition from % \pkg{tagpdf}. There has to be a decision where such plugs should be % implemented: in the package (like now) then they functions used % from tagpdf should become public, in \pkg{tagpdf}, or in % \texttt{lttagging} in the kernel. % \changes{v2.0a}{2024/11/12}{Added tagging socket and use public tagpdf function} % \begin{macrocode} \NewSocketPlug {tagsupport/page@sofar}{default} { % \__tag_check_typeout_v:n {====>~In~\string\page@sofar} % some similar debug message if wanted. \process@cols\mult@firstbox { \tag_mc_add_missing_to_stream:Nn \count@ {multicol} } \tag_mc_add_missing_to_stream:Nn \mult@rightbox {multicol} } % \end{macrocode} % In the \LuaTeX{} engine there is no need to do anything special % in this socket. % \begin{macrocode} \sys_if_engine_luatex:TF { \AssignSocketPlug{tagsupport/page@sofar}{noop} } { \AssignSocketPlug{tagsupport/page@sofar}{default} } % \end{macrocode} % % % % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % % % \Finale % \endinput