summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pbalance/pbalance.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2022-06-23 03:00:50 +0000
committerNorbert Preining <norbert@preining.info>2022-06-23 03:00:50 +0000
commit00e67dfd87c53faeafcf0c9e66c8c2c7a410fcb8 (patch)
treeef301069afe23459e4f42b83386787a5aca10e5f /macros/latex/contrib/pbalance/pbalance.dtx
parentd6888fdb49e3ac954c2d436951f364d3a4a4b17d (diff)
CTAN sync 202206230300
Diffstat (limited to 'macros/latex/contrib/pbalance/pbalance.dtx')
-rw-r--r--macros/latex/contrib/pbalance/pbalance.dtx322
1 files changed, 269 insertions, 53 deletions
diff --git a/macros/latex/contrib/pbalance/pbalance.dtx b/macros/latex/contrib/pbalance/pbalance.dtx
index 9f984e0e11..b5712f00c6 100644
--- a/macros/latex/contrib/pbalance/pbalance.dtx
+++ b/macros/latex/contrib/pbalance/pbalance.dtx
@@ -1,5 +1,5 @@
% \iffalse meta-comment
-% Copyright 2020-2021 Nelson Lago <lago@ime.usp.br>
+% Copyright 2020-2022 Nelson Lago <lago@ime.usp.br>
%
% This work may be distributed and/or modified under the conditions of the
% LaTeX Project Public License, either version 1.3c of this license or (at
@@ -15,7 +15,7 @@
% \iffalse
%
%<package>\NeedsTeXFormat{LaTeX2e}[2015/01/01]
-%<package>\ProvidesPackage{pbalance}[2021/05/24 v1.1.1 Poor man's balance]
+%<package>\ProvidesPackage{pbalance}[2022/06/22 v1.3.0 Poor man's balance]
%
%<*driver>
@@ -34,6 +34,8 @@
anchorcolor=black,
}
+\usepackage{microtype}
+
\usepackage[draft]{pbalance}
\usepackage{libertinus}
@@ -60,6 +62,14 @@
% \changes{v1.1.0}{2021/04/26}{Do not crash in one-column mode}
% \changes{v1.1.1}{2021/05/24}{Do not use balance package if
% there are dbltop floats}
+% \changes{v1.2.0}{2022/06/20}{Improvements to latexmk file}
+% \changes{v1.2.0}{2022/06/20}{More logging and sanity checks}
+% \changes{v1.2.0}{2022/06/20}{Add ``safe'' option}
+% \changes{v1.2.0}{2022/06/20}{Do not use \texttt{balance} pkg
+% with \texttt{lineno}}
+% \changes{v1.2.0}{2022/06/20}{Compatibility with \texttt{lineno} pkg}
+% \changes{v1.2.1}{2022/06/21}{Better error handling}
+% \changes{v1.3.0}{2022/06/22}{Compatibility with \texttt{stfloats} pkg}
%
% \GetFileInfo{pbalance.sty}
%
@@ -126,11 +136,14 @@
%
% If the last page does not have floats, footnotes, or marginpars, the
% package simply uses \verb|\balance|, from the \texttt{balance} package,
-% otherwise it uses its own algorithm. You may instead use
+% otherwise it uses its own algorithm. If that fails for some reason, you
+% may add the \verb|safe| option to the package, which makes the code
+% never use (or even load) the \texttt{balance} package. You may also use
% \verb|\shrinkLastPage{some-measurement}| to manually define how much
-% shorter the first column of the last page should be. This, however, will
-% not eliminate the need for extra passes (the package needs to find out
-% which page is the last).
+% shorter the first column of the last page should be instead of letting
+% the package determine the amount. This, however, will not eliminate the
+% need for extra passes (the package needs to find out which \mbox{page is
+% the last).}\looseness=1
%
% The package actually balances the last \emph{text} page; if the last
% page is a float page, it is ignored. It also \emph{should} work if you
@@ -157,7 +170,7 @@
% to give up on balancing (the document is still generated correctly
% in this case). To minimize the chances of this outcome, it is
% probably a good idea to make the parameters a little more liberal
-% than the default, for example:
+% than the default, for example:\looseness=-1
%
% \begin{verbatim}
%\setcounter{totalnumber}{5} % default 3
@@ -215,9 +228,6 @@
%
% \begin{itemize}
%
-% \item add options to (1) allow using the balance package on pages with
-% floats and (2) completely disable the balance package;
-%
% \item make the mechanism able to work with any page, not just the last,
% and with more than one page at once. This is useful for the last
% page of each chapter of a two-column book, for example;
@@ -256,9 +266,9 @@
% \subsection{Initialization, required packages etc.}
%
% Besides some other required packages, here we load the \texttt{balance}
-% package; if there are no floats or footnotes involved, we will simply use
-% it. We need to load it after we modify \verb|\@outputdblcol|, so we use
-% \verb|\AtEndOfPackage|.
+% package; if there are no floats or footnotes involved and if the document
+% does not load \texttt{lineno.sty}, we will simply use it. We need to load
+% it after we modify \verb|\@outputdblcol|, so we use \verb|\AtEndOfPackage|.
%
% We also define the \texttt{draft} option, which disables processing.
%
@@ -269,23 +279,43 @@
\RequirePackage{atbegshi} % Manipulate the page output routine
\RequirePackage{atveryend} % Write to the aux file after processing ends
\RequirePackage{zref-abspage} % Figure out the current page
+\RequirePackage{filehook} % Patch other packages that modify the output routine
-\AtEndOfPackage{\RequirePackage{balance}}
-
-% See https://github.com/latex3/latex2e/issues/399#issuecomment-703081793
-\gdef \@reinserts{%
- \ifvbox\@kludgeins\insert\@kludgeins
- {\unvbox\@kludgeins}\fi
- \ifvoid\footins\else\insert\footins{\unvbox\footins}\fi
-}
+\newtoggle{@PBpatchFailed}
+% These may be already defined in the .aux file from a previous run
\providetoggle{@PBstabilized}
\providetoggle{@PBimpossible}
+\newtoggle{@PBnoBalancePackage}
+\DeclareOption{safe}{\toggletrue{@PBnoBalancePackage}}
+
\newtoggle{@PBdraft}
\DeclareOption{draft}{\toggletrue{@PBdraft}}
+
\ProcessOptions\relax
+% lineno may be loaded after us, so we need to check for it later...
+\AtEndPreamble{\@ifpackageloaded{lineno}{\toggletrue{@PBnoBalancePackage}}{}}
+
+% ... But it does not harm to check here too, which may save us
+% the trouble of needlessly loading the balance package only to
+% never use it later on. If we get it wrong, that's ok.
+\@ifpackageloaded{lineno}{\toggletrue{@PBnoBalancePackage}}{}
+
+\AtEndOfPackage{
+ \ifboolexpr{togl {@PBdraft} or togl {@PBnoBalancePackage}}
+ {}
+ {\RequirePackage{balance}}
+}
+
+% See https://github.com/latex3/latex2e/issues/399#issuecomment-703081793
+\gdef \@reinserts{%
+ \ifvbox\@kludgeins\insert\@kludgeins
+ {\unvbox\@kludgeins}\fi
+ \ifvoid\footins\else\insert\footins{\unvbox\footins}\fi
+}
+
% \end{macrocode}
% \subsection{The balancing front}
@@ -333,7 +363,10 @@
\newcommand\@PBStartBalancing{
\ifdefvoid{\@PBslack}
{\@PBautomaticBalance}
- {\@PBshrinkPage}
+ {
+ \PackageInfo{pbalance}{Automatic mode disabled, doing manual adjustment}
+ \@PBshrinkPage
+ }
}
\newcommand\@PBautomaticBalance{
@@ -348,10 +381,10 @@
\@PBcalculateShrinkage
\@PBshrinkPage
}
- {}
+ {\PackageInfo{pbalance}{Page "naturally" balanced, doing nothing}}
}
}
- {}
+ {\PackageInfo{pbalance}{Float-only column at last page, doing nothing}}
}
% Calculate how much we should shrink the left column of the last
@@ -370,8 +403,8 @@
% Figure out the amount of unused space on the last page (both
% cols); we will reduce the first column height by half that amount
- \dimgdef\@PBslack{2\dimexpr\@PBtmpH\relax - \@PBtmpUL - \@PBtmpUR}
- \dimgdef\@PBslack{.5\dimexpr\@PBslack\relax}
+ \dimgdef\@PBslack{\@PBtmpH *2 - \@PBtmpUL - \@PBtmpUR}
+ \dimgdef\@PBslack{\@PBslack /2}
% Actually, I lied. While half, as said above, sometimes yields
% perfectly balanced columns, that is often not the case (the page
@@ -408,7 +441,12 @@
% ``push'' them up to be aligned with the end of the left column,
% especially if there are footnotes on the left column too. We
% do this by manipulating \@textbottom in \@outputdblcol.
-\pretocmd{\@outputdblcol}{\@PBbalanceSecondColumn}{}{}
+\pretocmd{\@outputdblcol}{\@PBbalanceSecondColumn}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
\let\@PBbalanceSecondColumn\relax
@@ -466,7 +504,6 @@
\newtoggle{@PBtmpHasMarginpars}
\def\@PBcollectPageInfo{
-
\ifboolexpr
{
test {\@PBifmidfloat} or test {\@PBiftopfloat} or
@@ -481,10 +518,20 @@
{}
}
-\pretocmd{\@makecol}{\@PBcollectPageInfo}{}{}
+\pretocmd{\@makecol}{\@PBcollectPageInfo}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
% This only gets called if there is a marginpar, so that's easy
-\pretocmd{\@addmarginpar}{\global\toggletrue{@PBtmpHasMarginpars}}{}{}
+\pretocmd{\@addmarginpar}{\global\toggletrue{@PBtmpHasMarginpars}}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
% \end{macrocode}
%
@@ -524,8 +571,19 @@
}
\ExplSyntaxOff
-\pretocmd{\@addtocurcol}{\dimgdef{\@PBtmpHeightBefore}{\@textfloatsheight}}{}{}
-\apptocmd{\@addtocurcol}{\@PBcollectFloatHeights}{}{}
+\pretocmd{\@addtocurcol}{\dimgdef{\@PBtmpHeightBefore}{\@textfloatsheight}}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+
+\apptocmd{\@addtocurcol}{\@PBcollectFloatHeights}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
% \end{macrocode}
%
@@ -539,8 +597,58 @@
\newtoggle{@PBtmpHasFloatcol}
\newtoggle{@PBtmpIsFloatPage}
+% It would be nice to modify @makecol to do something like
+%
+% if@firstcolumn
+% @PBtmpUsedLeft = currentColumnHeight
+% else
+% @PBtmpUsedRight = currentColumnHeight
+%
+% Unfortunately, as stated in texdoc source2e on the section about the
+% output routine (ltoutput.dtx) around source line 273, "any conditional
+% code for the two-column case within output may not get executed with
+% the correct value of if@firstcolumn."
+%
+% Another approach, then, would be to defer the measurement of the
+% columns to @outputdblcol, where there are @leftcolumn and @outputbox.
+% This works, unless the package lineno was loaded: this package modifies
+% @makecol, preventing us from obtaining the correct height for the
+% output boxes.
+%
+% What we do, then, is (1) collect the column height in @makecol and
+% (2) decide whether the collected height corresponds to the left or
+% right column in @outputdblcol.
+\newcommand\@PBcollectColumnUsedHeight{
+ \setbox\@tempboxa=\vbox{\unvcopy\@outputbox\unskip\unskip}
+ \dimgdef\@PBtmpColumnUsedHeight{\ht\@tempboxa\relax}
+}
+
+\apptocmd{\@makecol}{\@PBcollectColumnUsedHeight}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+
+\newtoggle{@PBpatchStillActive} % Let's make sure our patched code actually runs
+
\newcommand\@PBcollectColumnInfo{
+ \global\toggletrue{@PBpatchStillActive}
+
+ \iftoggle{@PBpatchFailed}
+ {}
+ {
+ \ifdefvoid{\@PBtmpColumnUsedHeight}
+ {
+ \global\toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch disabled by another
+ package, won't balance}
+ }
+ {\@PBreallyCollectColumnInfo}
+ }
+}
+\newcommand\@PBreallyCollectColumnInfo{
\if@firstcolumn
\@PBiffloatcol
@@ -556,6 +664,7 @@
% Space used by \texttt{here} floats
\dimgdef\@PBtmpLeftFloatsHeight{\@textfloatsheight}
+ \dimgdef\@PBtmpUsedLeft{\@PBtmpColumnUsedHeight}
\else
@@ -569,26 +678,106 @@
\dimgdef\@PBtmpRightHeight{\@colroom}
\dimgdef\@PBtmpRightFloatsHeight{\@textfloatsheight}
-
- \setbox\@tempboxa=\copy\@leftcolumn
- \setbox\@tempboxa=\vbox{\unvbox\@tempboxa\unskip\unskip}
- \dimgdef\@PBtmpUsedLeft{\ht\@tempboxa\relax}
-
- \setbox\@tempboxa=\copy\@outputbox
- \setbox\@tempboxa=\vbox{\unvbox\@tempboxa\unskip\unskip}
- \dimgdef\@PBtmpUsedRight{\ht\@tempboxa\relax}
+ \dimgdef\@PBtmpUsedRight{\@PBtmpColumnUsedHeight}
\fi
}
-% The default LaTeX macro
-\pretocmd{\@outputdblcol}{\@PBcollectColumnInfo}{}{}
+% Now we patch the default @outputdblcol LaTeX macro...
+\pretocmd{\@outputdblcol}{\@PBcollectColumnInfo}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+
+% ... And the balance package version, but only if we actually loaded it
+\ifboolexpr{togl {@PBdraft} or togl {@PBnoBalancePackage}}
+ {}
+ {
+ \AtEndOfPackage{
+ \pretocmd{\@BAdblcol}{\@PBcollectColumnInfo}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+ % Revert \balance before next page if it exists (it might be a float page)
+ \patchcmd{\@BAdblcol}{\endgroup}{\endgroup\nobalance}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+ }
+ }
-% The version from the balance package
-\AtEndOfPackage{
- \pretocmd{\@BAdblcol}{\@PBcollectColumnInfo}{}{}
- % Revert \balance before next page if it exists (it might be a float page)
- \patchcmd{\@BAdblcol}{\endgroup}{\endgroup\nobalance}{}{}
-}
+% \end{macrocode}
+%
+% \subsection{Compatibility with other packages}
+%
+% We mostly modify stuff from the output routine to collect data, not to
+% change what is typeset (the only exception is @textbottom, which we
+% manipulate to align footnotes). This means that, if some other package
+% modifies the output routine as well, we will not break anything, which
+% is why this package is mostly safe to use. Unfortunately, such other
+% packages may prevent us from balancing. Here we try to play nice with
+% some of them.
+%
+% \subsubsection{stfloats}
+%
+% \begin{macrocode}
+
+% stfloats overwrites @addtocurcol; if it is already loaded, we already
+% patched the modified version, so we only need to run this if the package
+% is loaded later on. Therefore, we use AtEndOfPackageFile without *.
+\AtEndOfPackageFile{stfloats}
+ {
+
+ \pretocmd{\@addtocurcol}{\dimgdef{\@PBtmpHeightBefore}{\@textfloatsheight}}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+
+ \apptocmd{\@addtocurcol}{\@PBcollectFloatHeights}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+ }
+
+% We always need to patch these, so this code should run whether the
+% package is already loaded or gets loaded later on. Therefore, we
+% use AtEndOfPackageFile with *.
+\AtEndOfPackageFile*{stfloats}
+ {
+ \pretocmd{\fn@makecol}{\@PBcollectPageInfo}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+ \pretocmd{\org@makecol}{\@PBcollectPageInfo}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+ \apptocmd{\fn@makecol}{\@PBcollectColumnUsedHeight}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+ \apptocmd{\org@makecol}{\@PBcollectColumnUsedHeight}
+ {}
+ {
+ \toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch failed, won't balance}
+ }
+ }
% \end{macrocode}
%
@@ -600,8 +789,22 @@
%
% \begin{macrocode}
-\ExplSyntaxOn
\AtBeginShipout{
+ \iftoggle{@PBpatchFailed}
+ {}
+ {
+ \iftoggle{@PBpatchStillActive}
+ {\@PBfinalizePageData}
+ {
+ \global\toggletrue{@PBpatchFailed}
+ \PackageWarningNoLine{pbalance}{Patch disabled by another
+ package, won't balance}
+ }
+ }
+}
+
+\ExplSyntaxOn
+\newcommand\@PBfinalizePageData{
% It only makes sense to consider pages that actually have two
% columns. LaTeX3 does not do short-circuit evaluation, so we
% cannot add this test to the ifboolexpr below.
@@ -656,7 +859,7 @@
% document, there is no candidate page.
\ifcsdef{@PBlastPage}
{\@PBcopyPageData{candidate}{pg\@Roman{\@PBlastPage}}}
- {}
+ {\PackageInfo{pbalance}{No two-column pages, doing nothing}}
}
% \end{macrocode}
@@ -696,8 +899,16 @@
% so the user can start over if they want to.
\iftoggle{@PBdraft}{\togglefalse{@PBimpossible}}{}
- \ifboolexpr{togl {@PBdraft} or togl {@PBimpossible}}
- {}
+ \ifboolexpr{togl {@PBdraft} or togl {@PBimpossible} or togl {@PBpatchFailed}}
+ {
+ \iftoggle{@PBimpossible}
+ {\PackageWarningNoLine{pbalance}{Could not balance, doing nothing}}
+ {
+ \iftoggle{@PBpatchFailed}
+ {\PackageWarningNoLine{pbalance}{Patching failed, doing nothing}}
+ {\PackageInfo{pbalance}{Draft mode, doing nothing}}
+ }
+ }
{
\ifdefvoid{\@PBprevLastPage}
{\@PBsaveUnbalancedInfo\@PBnotifyRerun} % First pass
@@ -783,6 +994,8 @@
togl {@PBunbalpg\@Roman{\@PBprevLastPage}HasFootnotes}
or
togl {@PBunbalpg\@Roman{\@PBprevLastPage}HasMarginpars}
+ or
+ togl {@PBnoBalancePackage}
}
{#2}
{#1}
@@ -1027,7 +1240,10 @@
\PackageWarningNoLine{pbalance}
{Last two-column page cols not balanced. Rerun LaTeX}
}
- {}
+ {
+ \PackageWarningNoLine{pbalance}
+ {No two-column pages, doing nothing}
+ }
}
}