summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/pbalance
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2020-12-04 22:24:00 +0000
committerKarl Berry <karl@freefriends.org>2020-12-04 22:24:00 +0000
commit510e24ff93e1d12670e0eadcf5b46aa257c7d507 (patch)
tree71a319532ebd8222d745ce4ad287bebe98bb628b /Master/texmf-dist/tex/latex/pbalance
parent308fffa9446e3b5d28b6e48b89be81575b565c70 (diff)
pbalance (4dec20)
git-svn-id: svn://tug.org/texlive/trunk@57067 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/pbalance')
-rw-r--r--Master/texmf-dist/tex/latex/pbalance/pbalance.sty672
1 files changed, 672 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/pbalance/pbalance.sty b/Master/texmf-dist/tex/latex/pbalance/pbalance.sty
new file mode 100644
index 00000000000..e7d9dde4c9d
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/pbalance/pbalance.sty
@@ -0,0 +1,672 @@
+%%
+%% This is file `pbalance.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% pbalance.dtx (with options: `package')
+%% Copyright 2020 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.3 of this license or (at
+%% your option) any later version. The latest version of this license can be
+%% found at http://www.latex-project.org/lppl.txt and version 1.3 or later
+%% is part of all distributions of LaTeX version 2005/12/01 or later.
+%%
+%% This work has the LPPL maintenance status `maintained'.
+%%
+%% The Current Maintainer of this work is Nelson Lago <lago@ime.usp.br>.
+%%
+\NeedsTeXFormat{LaTeX2e}[2015/01/01]
+\ProvidesPackage{pbalance}[2020/12/03 v1.0 Poor man's balance]
+
+\RequirePackage{etoolbox}
+\RequirePackage{expl3}
+\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
+
+\AtEndOfPackage{\RequirePackage{balance}}
+
+\gdef \@reinserts{%
+ \ifvbox\@kludgeins\insert\@kludgeins
+ {\unvbox\@kludgeins}\fi
+ \ifvoid\footins\else\insert\footins{\unvbox\footins}\fi
+}
+
+\providetoggle{@PBstabilized}
+\providetoggle{@PBimpossible}
+
+\newtoggle{@PBdraft}
+\DeclareOption{draft}{\toggletrue{@PBdraft}}
+\ProcessOptions\relax
+
+
+
+\AtBeginDocument{
+ \@PBifShouldBalanceNascentPage
+ {\@PBStartBalancing}
+ {}
+}
+
+\AtBeginShipout{
+ \@PBifShouldBalanceNascentPage
+ {\@PBStartBalancing}
+ {}
+}
+
+\newcommand\@PBifShouldBalanceNascentPage[2]{
+ \ifboolexpr
+ {
+ togl {@PBdraft}
+ or not togl {@PBstabilized}
+ or test {\ifdefvoid{\@PBprevLastPage}}
+ }
+ {#2}
+ {
+ % abspage refers to the finished page, not the nascent page
+ \ifnumcomp{\@PBprevLastPage - 1}{=}{\value{abspage}}
+ {#1}
+ {#2}
+ }
+}
+
+\newcommand\shrinkLastPage[1]{\dimgdef\@PBslack{#1}}
+
+\newcommand\@PBStartBalancing{
+ \ifdefvoid{\@PBslack}
+ {\@PBautomaticBalance}
+ {\@PBshrinkPage}
+}
+
+\newcommand\@PBautomaticBalance{
+ \@PBifBalancePossible
+ {
+ \@PBifBalancePkgPossible
+ {\balance} % easy peasy, use the balance package
+ {
+ \@PBifPoorBalancePossible
+ {
+ % use the poor man's balance algorithm
+ \@PBcalculateShrinkage
+ \@PBshrinkPage
+ }
+ {}
+ }
+ }
+ {}
+}
+
+\newcommand\@PBcalculateShrinkage{
+
+ % Let's use some shorter names, please
+ \dimdef\@PBtmpH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}Height}}
+ \dimdef\@PBtmpUL{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}UsedLeft}}
+ \dimdef\@PBtmpUR{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}UsedRight}}
+
+ \dimdef\@PBtmpLH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}LeftHeight}}
+ \dimdef\@PBtmpLFH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}LeftFloatsHeight}}
+ \dimdef\@PBtmpRH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}RightHeight}}
+ \dimdef\@PBtmpRFH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}RightFloatsHeight}}
+
+ % 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}
+
+ % Actually, I lied. While half, as said above, sometimes yields
+ % perfectly balanced columns, that is often not the case (the page
+ % may have an odd number of lines, or textheight may not be a
+ % multiple of baselineskip, or there may be glues etc.). Sometimes
+ % the difference is very small, less than a line, which does not
+ % look good at all, and sometimes the right column is slightly
+ % higher than the left, which is also not ideal. Here, we force
+ % the left column to always be somewhat taller than the left; the
+ % result is often ``better''.
+ \dimgdef\@PBslack{\@PBslack - 1.5\baselineskip}
+
+ % If necessary, reduce @PBslack to prevent LaTeX from adding a page
+ \@PBsafetyCheck
+}
+
+\def\@PBshrinkPage{
+ % Zero obviously means ``do nothing''. We could
+ % ``enlarge'' by 0, but IDK, maybe that would
+ % trigger another LaTeX pass or something.
+ \ifdimcomp{\@PBslack}{=}{0pt}
+ {}
+ {
+ % Shrink the first column
+ \enlargethispage{-\@PBslack}
+
+ % Modify the behavior of \@outputdblcol
+ % to raise footnotes in the second column.
+ \global\let\@PBbalanceSecondColumn\@PBrealBalanceSecondColumn
+ }
+}
+
+\pretocmd{\@outputdblcol}{\@PBbalanceSecondColumn}{}{}
+
+\let\@PBbalanceSecondColumn\relax
+
+\def\@PBrealBalanceSecondColumn{
+ \if@firstcolumn
+ % Affects the next column
+ \global\let\@PBorigtextbottom\@textbottom
+ \gdef\@textbottom{\vskip \@PBslack plus .0001fil minus 10000fill\relax \@PBorigtextbottom}
+ \else
+ % Back to normal before starting the next page
+ \global\let\@textbottom\@PBorigtextbottom
+ \global\let\@PBbalanceSecondColumn\relax
+ \fi
+}
+
+
+
+\newcommand\@PBifmidfloat[2]{\ifx\@midlist\empty #2\else #1\fi}
+\newcommand\@PBiftopfloat[2]{\ifx\@toplist\empty #2\else #1\fi}
+\newcommand\@PBifbotfloat[2]{\ifx\@botlist\empty #2\else #1\fi}
+\newcommand\@PBiffootnote[2]{\ifvoid\footins #2\else #1\fi}
+\newcommand\@PBiffloatcol[2]{\if@fcolmade #1\else #2\fi}
+%%%\newcommand\@PBifdbltopfloat[2]{\ifx\@dbltoplist\empty #2\else #1\fi}
+\newcommand\@PBifdblbotfloat[2]{%
+ \ifdefvoid{\@dblbotlist}
+ {#2}
+ {\ifx\@dblbotlist\empty #2\else #1\fi}%
+}
+
+\newtoggle{@PBtmpHasFootnotes}
+\newtoggle{@PBtmpHasFloats}
+\newtoggle{@PBtmpHasMarginpars}
+
+\def\@PBcollectPageInfo{
+
+ \ifboolexpr
+ {
+ test {\@PBifmidfloat} or test {\@PBiftopfloat} or
+ test {\@PBifbotfloat} or test {\@PBifdblbotfloat}
+ }
+ {\global\toggletrue{@PBtmpHasFloats}}
+ {}
+
+ \@PBiffootnote
+ {\global\toggletrue{@PBtmpHasFootnotes}}
+ {}
+}
+
+\pretocmd{\@makecol}{\@PBcollectPageInfo}{}{}
+
+\pretocmd{\@addmarginpar}{\global\toggletrue{@PBtmpHasMarginpars}}{}{}
+
+
+\ExplSyntaxOn
+\seq_gclear_new:N \@PBtmpLeftFloatHeights
+\seq_gclear_new:N \@PBtmpLeftFloatSpacesBelow
+\def\@PBcollectFloatHeights{
+ \if@firstcolumn
+ \dimdef\@PBfloatHeight{\@textfloatsheight - \@PBtmpHeightBefore}
+ \ifdimcomp{\@PBfloatHeight}{>}{0pt}
+ {
+ \global\seq_put_right:NV \@PBtmpLeftFloatHeights \@PBfloatHeight
+
+ \dimdef\@PBspaceBelow{\@colroom - \@pageht - \@PBfloatHeight}
+ % within \@addtocurcol, \@pageht corresponds to all
+ % currently used space in the column, including footnotes
+ % (check \@specialoutput in the LaTeX kernel). Let's
+ % exclude the footnotes, we only want the space below
+ % the float.
+ \ifvoid\footins\else
+ \dimdef\@PBspaceBelow{\@PBspaceBelow + \ht\footins + \skip\footins + \dp\footins}
+ \fi
+
+ % No idea why, but this can happen; maybe because of the page depth?
+ \ifdimcomp{\@PBspaceBelow}{<}{0pt}
+ {\dimdef\@PBspaceBelow{0pt}}
+ {}
+
+ \global\seq_put_right:NV \@PBtmpLeftFloatSpacesBelow \@PBspaceBelow
+ }
+ {}
+ \fi
+}
+\ExplSyntaxOff
+
+\pretocmd{\@addtocurcol}{\dimgdef{\@PBtmpHeightBefore}{\@textfloatsheight}}{}{}
+\apptocmd{\@addtocurcol}{\@PBcollectFloatHeights}{}{}
+
+
+\newtoggle{@PBtmpHasFloatcol}
+\newtoggle{@PBtmpIsFloatPage}
+
+\newcommand\@PBcollectColumnInfo{
+
+ \if@firstcolumn
+
+ \@PBiffloatcol
+ {\global\toggletrue{@PBtmpHasFloatcol}}
+ {}
+
+ % Available vertical space excluding
+ % dblfloats; the same for both columns
+ \dimgdef\@PBtmpHeight{\@colht}
+
+ % Available vertical space excluding top/bottom floats
+ \dimgdef\@PBtmpLeftHeight{\@colroom}
+
+ % Space used by \texttt{here} floats
+ \dimgdef\@PBtmpLeftFloatsHeight{\@textfloatsheight}
+
+ \else
+
+ \@PBiffloatcol
+ {
+ \iftoggle{@PBtmpHasFloatcol}
+ {\global\toggletrue{@PBtmpIsFloatPage}}
+ {\global\toggletrue{@PBtmpHasFloatcol}}
+ }
+ {}
+
+ \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}
+ \fi
+}
+
+\pretocmd{\@outputdblcol}{\@PBcollectColumnInfo}{}{}
+
+\AtEndOfPackage{
+ \pretocmd{\@BAdblcol}{\@PBcollectColumnInfo}{}{}
+ % Revert \balance before next page if it exists (it might be a float page)
+ \patchcmd{\@BAdblcol}{\endgroup}{\endgroup\nobalance}{}{}
+}
+
+
+\ExplSyntaxOn
+\AtBeginShipout{
+ \ifboolexpr
+ {
+ % A float page is not the last text page, ignore
+ togl {@PBtmpIsFloatPage}
+ or
+ % A page with a float column on the left and an empty
+ % column on the right is not the last text page, ignore
+ (
+ togl {@PBtmpHasFloatcol}
+ and
+ test {\ifdimcomp{\@PBtmpUsedRight}{=}{\topskip}}
+ )
+ }
+ {}
+ {
+ % This page is a candidate to be the last page
+ \xdef\@PBlastPage{\the\value{abspage}}
+ \@PBcopyPageData{tmp}{candidate}
+ }
+
+ % Reset before processing next page
+ \global\togglefalse{@PBtmpHasFloats}
+ \global\togglefalse{@PBtmpHasFloatcol}
+ \global\togglefalse{@PBtmpHasFootnotes}
+ \global\togglefalse{@PBtmpHasMarginpars}
+ \global\togglefalse{@PBtmpIsFloatPage}
+
+ \seq_gclear_new:N \@PBtmpLeftFloatHeights
+ \seq_gclear_new:N \@PBtmpLeftFloatSpacesBelow
+}
+\ExplSyntaxOff
+
+
+\AfterLastShipout{\@PBcopyPageData{candidate}{pg\@Roman{\@PBlastPage}}}
+
+
+\AfterLastShipout{
+ % Reset \@PBimpossible if we are in draft mode,
+ % so the user can start over if they want to.
+ \iftoggle{@PBdraft}{\togglefalse{@PBimpossible}}{}
+
+ \ifboolexpr{togl {@PBdraft} or togl {@PBimpossible}}
+ {}
+ {
+ \ifdefvoid{\@PBprevLastPage}
+ {\@PBsaveUnbalancedInfo\@PBnotifyRerun} % First pass
+ {
+ \iftoggle{@PBstabilized}
+ {\@PBmanageBalancingPasses}
+ {
+ \@PBifSomethingChanged[unbal]
+ % Document still changing; discard data from previous pass
+ {\@PBsaveUnbalancedInfo[update]\@PBnotifyRerun}
+ % No changes, so let's balance from now on (once @PBstabilized
+ % becomes true, it never reverts back to false, unless the aux
+ % file is deleted).
+ {\toggletrue{@PBstabilized}\@PBsaveUnbalancedInfo\@PBnotifyRerun}
+ }
+ }
+ \@PBsaveToggle{@PBstabilized}
+ }
+
+ \@PBsaveToggle{@PBimpossible}
+ \immediate\write\@mainaux{\gdef\string\@PBprevLastPhysPage{\the\value{abspage}}}
+}
+
+\newcommand\@PBmanageBalancingPasses{
+ % This is the second pass or later after we started balancing
+
+ \providetoggle{@PBpg\@Roman{\@PBlastPage}alreadyBalanced}
+
+ \iftoggle{@PBpg\@Roman{\@PBlastPage}alreadyBalanced}
+ {
+ % Third pass or later; document was already
+ % balanced, so there should be no more changes
+ \@PBifSomethingChanged
+ % The document has changed, so we need to measure
+ % stuff again; clear aux file and start over.
+ {\@PBnotifyRerun}
+ % Nothing changed, just write the same info down
+ {\@PBsaveUnbalancedInfo\@PBsaveBalancedInfo}
+ }
+ % Second pass, which means something did change: we have just
+ % balanced the columns for the first time.
+ {
+ \xdef\@tempa{\the\value{abspage}}
+ \ifboolexpr
+ {
+ test {\ifdefstrequal{\@PBprevLastPage}{\@PBlastPage}}
+ and
+ test {\ifdefstrequal{\@PBprevLastPhysPage}{\@tempa}}
+ }
+ % All is well; save the new info
+ {\@PBsaveUnbalancedInfo\@PBsaveBalancedInfo}
+ % Oh, no! As we attempted to balance, we actually changed
+ % the number of pages (maybe we added a float page, maybe
+ % we turned the last float page into a text page etc.). If
+ % we continue, the document might never converge (endless
+ % ``please rerun LaTeX'' messages). Let's give up balancing.
+ {\toggletrue{@PBimpossible}}
+ }
+}
+
+
+\newcommand\@PBifBalancePossible[2]{
+ \iftoggle{@PBunbalpg\@Roman{\@PBprevLastPage}HasFloatcol}
+ {#2}
+ {#1}
+}
+
+\newcommand\@PBifBalancePkgPossible[2]{
+ \ifboolexpr
+ {
+ togl {@PBunbalpg\@Roman{\@PBprevLastPage}HasFloats}
+ or
+ togl {@PBunbalpg\@Roman{\@PBprevLastPage}HasFootnotes}
+ or
+ togl {@PBunbalpg\@Roman{\@PBprevLastPage}HasMarginpars}
+ }
+ {#2}
+ {#1}
+}
+
+
+\newcommand\@PBifPoorBalancePossible[2]{
+
+ % Let's use some shorter names, please
+ \dimdef\@PBtmpH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}Height}}
+ \dimdef\@PBtmpUL{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}UsedLeft}}
+ \dimdef\@PBtmpUR{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}UsedRight}}
+
+ \dimdef\@PBtmpLH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}LeftHeight}}
+ \dimdef\@PBtmpLFH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}LeftFloatsHeight}}
+ \dimdef\@PBtmpRH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}RightHeight}}
+ \dimdef\@PBtmpRFH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}RightFloatsHeight}}
+
+ \ifboolexpr{
+ % Plenty of space on right column, difference is worth it
+ test {\ifdimcomp{\@PBtmpUL}{>}{\@PBtmpUR + 6\baselineskip}}
+ or
+ (
+ test {\ifdimcomp{\@PBtmpUL}{>}{4\baselineskip}}
+ and
+ test {\ifdimcomp{\@PBtmpUR}{=}{\topskip}} % column is empty
+ )
+ }{#1}{#2}
+}
+
+
+
+\ExplSyntaxOn
+\def\@PBsafetyCheck{
+
+ % Let's use some shorter names, please
+ \dimdef\@PBtmpH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}Height}}
+ \dimdef\@PBtmpUL{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}UsedLeft}}
+ \dimdef\@PBtmpUR{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}UsedRight}}
+
+ \dimdef\@PBtmpLH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}LeftHeight}}
+ \dimdef\@PBtmpLFH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}LeftFloatsHeight}}
+ \dimdef\@PBtmpRH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}RightHeight}}
+ \dimdef\@PBtmpRFH{\csuse{@PBunbalpg\@Roman{\@PBprevLastPage}RightFloatsHeight}}
+
+ % Make sure we do not push top/bottom floats out of the left col
+ \dimdef\@PBmaxSlack{\@PBtmpLH}
+
+ \dimdef\@PBtmpdim{0pt}
+
+ % Start from the bottom
+ \numdef{\@PBtmpcnt}{\seq_count:c {@PBunbalpg\@Roman{\@PBprevLastPage}LeftFloatHeights}}
+ \int_while_do:nNnn {\@PBtmpcnt} > {0}
+ {
+
+ \dimdef\@PBcurrentFloatHeight
+ {\seq_item:cn {@PBunbalpg\@Roman{\@PBprevLastPage}LeftFloatHeights} {\@PBtmpcnt}}
+
+ \dimdef\@PBcurrentFloatSpaceBelow
+ {\seq_item:cn {@PBunbalpg\@Roman{\@PBprevLastPage}LeftFloatSpacesBelow} {\@PBtmpcnt}}
+
+ \dimdef{\@PBtmpdim}{\@PBtmpdim + \@PBcurrentFloatHeight}
+
+ \ifboolexpr
+ {
+ % Does the float fit in the second column?
+ test {\ifdimcomp{\@PBtmpdim}{<}{\@PBtmpRH - \@PBtmpRFH}}
+ and
+ % Is there something above this float, i.e., if we move
+ % this float to the next column, will anything remain?
+ test
+ {
+ \ifdimcomp
+ {\@PBcurrentFloatSpaceBelow + \@PBcurrentFloatHeight}
+ {<}
+ {\@PBtmpLH - 6\baselineskip}
+ }
+ }
+ {\numdef{\@PBtmpcnt}{\@PBtmpcnt - 1}} % this one is ok; check next
+ {
+ % this one should not be moved, we found the limit
+ \ifdimcomp{\@PBmaxSlack}{>}{\@PBcurrentFloatSpaceBelow}
+ {\dimdef{\@PBmaxSlack}{\@PBcurrentFloatSpaceBelow}}
+ {}
+ \numdef{\@PBtmpcnt}{0} % exit the loop
+ }
+ }
+
+ \ifdimcomp{\@PBmaxSlack}{<}{\@PBslack}
+ {\dimgdef{\@PBslack}{\@PBmaxSlack}}
+ {}
+}
+\ExplSyntaxOff
+
+\newcommand\@PBifSomethingChanged[3][bal]{
+ \ifdefstrequal{\@PBprevLastPage}{\@PBlastPage}
+ {
+ \@PBifPageDataMatches
+ {pg\@Roman{\@PBlastPage}}
+ {#1pg\@Roman{\@PBlastPage}}
+ {#3}
+ {#2}
+ }
+ {#2}
+}
+
+\newcommand\@PBifPageDataMatches[4]{
+ \ifboolexpr{
+ test {\@PBifTogglesMatch{@PB#1HasFloats}{@PB#2HasFloats}}
+ and test {\@PBifTogglesMatch{@PB#1HasFloatcol}{@PB#2HasFloatcol}}
+ and test {\@PBifTogglesMatch{@PB#1HasFootnotes}{@PB#2HasFootnotes}}
+ and test {\@PBifTogglesMatch{@PB#1HasMarginpars}{@PB#2HasMarginpars}}
+ and test {\@PBifDimensionsMatch{@PB#1Height}{@PB#2Height}}
+ and test {\@PBifDimensionsMatch{@PB#1LeftHeight}{@PB#2LeftHeight}}
+ and test {\@PBifDimensionsMatch{@PB#1RightHeight}{@PB#2RightHeight}}
+ and test {\@PBifDimensionsMatch{@PB#1UsedLeft}{@PB#2UsedLeft}}
+ and test {\@PBifDimensionsMatch{@PB#1UsedRight}{@PB#2UsedRight}}
+ }
+ {#3}
+ {#4}
+}
+
+\newcommand\@PBifTogglesMatch[4]{
+ \ifboolexpr{(togl{#1} or not togl{#2}) and (togl{#2} or not togl{#1})}
+ {#3}
+ {#4}
+}
+
+\newcommand\@PBifDimensionsMatch[4]{
+ \ifdimcomp{\csuse{#1}}{=}{\csuse{#2}}
+ {#3}
+ {#4}
+}
+
+\newcommand\@PBsaveUnbalancedInfo[1][]{
+
+ \immediate\write\@mainaux{\gdef\string\@PBprevLastPage{\@PBlastPage}}
+
+ \ifboolexpr{test {\ifdefvoid{\@PBprevLastPage}} or test {\ifstrequal{#1}{update}}}
+ % Columns are currently unbalanced, either because this is
+ % the first pass (we do not have any previous information)
+ % or because the document has not stabilized yet, so any
+ % previous information is unreliable. Save the information
+ % we just collected as ``unbalanced''.
+ {\@PBsavePageDataAs{pg\@Roman{\@PBlastPage}}{unbalpg\@Roman{\@PBlastPage}}}
+ % Not the first pass, so columns are possibly balanced;
+ % to save the unbalanced information, repeat what was
+ % gathered during the first pass.
+ {\@PBsavePageData{unbalpg\@Roman{\@PBprevLastPage}}}
+}
+
+\def\@PBsaveBalancedInfo{
+ \global\toggletrue{@PBpg\@Roman{\@PBlastPage}alreadyBalanced}
+ \@PBsaveToggle{@PBpg\@Roman{\@PBlastPage}alreadyBalanced}
+
+ \@PBsavePageDataAs{pg\@Roman{\@PBlastPage}}{balpg\@Roman{\@PBlastPage}}
+}
+
+\def\@PBnotifyRerun{
+ \AtVeryEndDocument{
+ \PackageWarningNoLine{pbalance}
+ {Last page columns not balanced. Rerun LaTeX}
+ }
+}
+
+\ExplSyntaxOn
+\newcommand\@PBcopyPageData[2]{
+
+ \global\providetoggle{@PB#2HasFloats}
+ \global\providetoggle{@PB#2HasFloatcol}
+ \global\providetoggle{@PB#2HasFootnotes}
+ \global\providetoggle{@PB#2HasMarginpars}
+
+ \iftoggle{@PB#1HasFloats}
+ {\global\toggletrue{@PB#2HasFloats}}
+ {\global\togglefalse{@PB#2HasFloats}}
+
+ \iftoggle{@PB#1HasFloatcol}
+ {\global\toggletrue{@PB#2HasFloatcol}}
+ {\global\togglefalse{@PB#2HasFloatcol}}
+
+ \iftoggle{@PB#1HasFootnotes}
+ {\global\toggletrue{@PB#2HasFootnotes}}
+ {\global\togglefalse{@PB#2HasFootnotes}}
+
+ \iftoggle{@PB#1HasMarginpars}
+ {\global\toggletrue{@PB#2HasMarginpars}}
+ {\global\togglefalse{@PB#2HasMarginpars}}
+
+ \csdimgdef{@PB#2Height}{\csuse{@PB#1Height}}
+ \csdimgdef{@PB#2LeftHeight}{\csuse{@PB#1LeftHeight}}
+ \csdimgdef{@PB#2LeftFloatsHeight}{\csuse{@PB#1LeftFloatsHeight}}
+ \csdimgdef{@PB#2RightHeight}{\csuse{@PB#1RightHeight}}
+ \csdimgdef{@PB#2RightFloatsHeight}{\csuse{@PB#1RightFloatsHeight}}
+ \csdimgdef{@PB#2UsedLeft}{\csuse{@PB#1UsedLeft}}
+ \csdimgdef{@PB#2UsedRight}{\csuse{@PB#1UsedRight}}
+
+ \seq_gclear_new:c {@PB#2LeftFloatHeights}
+ \seq_gclear_new:c {@PB#2LeftFloatSpacesBelow}
+ \seq_gset_eq:cc {@PB#2LeftFloatHeights} {@PB#1LeftFloatHeights}
+ \seq_gset_eq:cc {@PB#2LeftFloatSpacesBelow} {@PB#1LeftFloatSpacesBelow}
+}
+\ExplSyntaxOff
+
+\newcommand\@PBsavePageDataAs[2]{
+ \@PBsaveDimAs{@PB#1Height}{@PB#2Height}
+ \@PBsaveDimAs{@PB#1LeftHeight}{@PB#2LeftHeight}
+ \@PBsaveDimAs{@PB#1LeftFloatsHeight}{@PB#2LeftFloatsHeight}
+ \@PBsaveDimAs{@PB#1RightHeight}{@PB#2RightHeight}
+ \@PBsaveDimAs{@PB#1RightFloatsHeight}{@PB#2RightFloatsHeight}
+ \@PBsaveDimAs{@PB#1UsedLeft}{@PB#2UsedLeft}
+ \@PBsaveDimAs{@PB#1UsedRight}{@PB#2UsedRight}
+
+ \@PBsaveToggleAs{@PB#1HasFloats}{@PB#2HasFloats}
+ \@PBsaveToggleAs{@PB#1HasFloatcol}{@PB#2HasFloatcol}
+ \@PBsaveToggleAs{@PB#1HasFootnotes}{@PB#2HasFootnotes}
+ \@PBsaveToggleAs{@PB#1HasMarginpars}{@PB#2HasMarginpars}
+
+ \@PBsaveSeqAs{@PB#1LeftFloatHeights}{@PB#2LeftFloatHeights}
+ \@PBsaveSeqAs{@PB#1LeftFloatSpacesBelow}{@PB#2LeftFloatSpacesBelow}
+}
+
+\newcommand\@PBsavePageData[1]{
+ \@PBsavePageDataAs{#1}{#1}
+}
+
+\newcommand\@PBsaveToggleAs[2]{
+ \immediate\write\@mainaux{\providetoggle{#2}}
+ \iftoggle{#1}
+ {\immediate\write\@mainaux{\global\toggletrue{#2}}}
+ {\immediate\write\@mainaux{\global\togglefalse{#2}}}
+}
+
+\newcommand\@PBsaveToggle[1]{
+ \@PBsaveToggleAs{#1}{#1}
+}
+
+\newcommand\@PBsaveDimAs[2]{
+ \immediate\write\@mainaux{\csdimgdef{#2}{\csuse{#1}}}
+}
+
+\newcommand\@PBsaveDim[1]{
+ \@PBsaveDimAs{#1}{#1}
+}
+
+\ExplSyntaxOn
+\newcommand\@PBsaveSeqAs[2]{
+ \immediate\write\@mainaux{\string\ExplSyntaxOn}
+ \immediate\write\@mainaux{\string\seq_gclear_new:c {#2}}
+ \seq_map_inline:cn {#1}
+ {\immediate\write\@mainaux{\string\global\string\seq_put_right:cn {#2}{##1}}}
+ \immediate\write\@mainaux{\string\ExplSyntaxOff}
+}
+\ExplSyntaxOff
+
+\newcommand\@PBsaveSeq[1]{
+ \@PBsaveSeqAs{#1}{#1}
+}
+
+\endinput
+%%
+%% End of file `pbalance.sty'.