diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/sttools/flushend.dtx |
Initial commit
Diffstat (limited to 'macros/latex/contrib/sttools/flushend.dtx')
-rw-r--r-- | macros/latex/contrib/sttools/flushend.dtx | 1265 |
1 files changed, 1265 insertions, 0 deletions
diff --git a/macros/latex/contrib/sttools/flushend.dtx b/macros/latex/contrib/sttools/flushend.dtx new file mode 100644 index 0000000000..2634f02e80 --- /dev/null +++ b/macros/latex/contrib/sttools/flushend.dtx @@ -0,0 +1,1265 @@ +% \iffalse meta-comment/*% \end{macrocode}*/ +% +% Copyright (C) 2017 by Sigitas Tolu\v{s}is <sigitas@vtex.lt> +% --------------------------------------------------------------------------- +% 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 is in +% 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 Sigitas Tolu\v{s}is. +% +% This work consists of the files flushend.dtx and flushend.ins +% and the derived filebase flushend.sty. +% +% \fi +% +% \iffalse +%<*internal> +\begingroup +%</internal> +%<*batchfile> +\input docstrip.tex +\keepsilent\askforoverwritefalse +\nopreamble\nopostamble +\generate{\file{flushend.sty}{\from{flushend.dtx}{package}}} +%</batchfile> +%<batchfile>\endbatchfile +%<*internal> +\generate{\file{flushend.ins}{\from{flushend.dtx}{batchfile}}} +\endgroup +%</internal> +%<*driver> +\ProvidesFile{flushend.dtx} +%</driver> +%<*package> +%% Copyright (C) 1997-2017 by Sigitas Tolu\v{s}is <sigitas@vtex.lt> +%% VTeX Ltd., Mokslinink\k{u} 2a, Vilnius, Lithuania +%% http://www.vtex.lt/tex/download/macros/ +%% -------------------------------------------------------------------------- +%% 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 is in +%% 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. +%% +%% PURPOSE: Balanced columns on last page in twocolumn mode. +%% +%</package> +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{flushend} +%<*package> + [2017/03/27 v3.3 Balancing columns in twocolumn mode] +%</package> +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{flushend}[2016/06/21] +\EnableCrossrefs +\CodelineIndex +%%\RecordChanges +%\OnlyDescription +\begin{document} + \DocInput{flushend.dtx} + %%\PrintChanges + %%\PrintIndex +\end{document} +%</driver> +% \fi +% +% \CheckSum{1855} +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +% +% \changes{v0.1}{1997/05/16}{first version} +% \changes{v0.2}{1997/09/09}{support for compatibility with cuted.sty} +% \changes{v1.0}{1997/10/01}{\string\vipersep changed to \string\stripsep for compatibility with cuted.sty} +% \changes{v1.1}{2012/05/29}{Converted to DTX file} +% \changes{v2.0}{2014/03/03}{rewritten with new balance algorithm} +% \changes{v2.1}{2014/03/18}{Switched debug option off} +% \changes{v2.2}{2014/04/24}{bugfix version: removing empty box at the right column end} +% \changes{v3.0}{2015/04/08}{bugfix version and extra options: +% ancient/modern, +% spread/nospread, +% removelastbox/keeplastbox} +% \changes{v3.1}{2015/04/14}{set debug option off by default; keeplastbox modified;} +% \changes{v3.2}{2016/06/21}{bugfix compatibility with luatexja} +% \changes{v3.3}{2017/03/27}{bugfix for get@@footnoterule@@box; options for some checks on/off} +% +% \DoNotIndex{\newcommand,\newenvironment} +% +% \providecommand*{\url}{\texttt} +% \GetFileInfo{flushend.dtx} +% \title{The \textsf{flushend} package} +% \author{Sigitas Tolu\v{s}is \\ \url{sigitas@vtex.lt}} +% \date{\fileversion~from \filedate} +% +% \maketitle +% +% \section{Introduction} +% +% The package is used to balance columns on any page in twocolumn +% mode. By default it is switched on at the end of document. It is +% expected to work with footnotes, top floats and column break +% before one line section title. +% +% \section{Usage} +% +% Just load the package to balance the last page: that's all. +% To balance some page in middle of document use command +% \cs{flushcolsend} at that page. +% +% \medskip +% \DescribeMacro{\flushend} +% +% This macro switches on column balancing on the last page. It is used +% by default. +% +% \medskip +% \DescribeMacro{\raggedend} +% +% This macro switches off column balancing on the last page. +% +% \medskip +% \DescribeMacro{\flushcolsend} +% +% This macro switches on column balancing on the current page. +% +% \medskip +% \DescribeMacro{\raggedcolsend} +% +% This macro switches off column balancing on the current page. +% +% \medskip +% \DescribeMacro{\atColsBreak} +% \marg{tokens} +% +% Adds \meta{tokens} in place of the original column break (made without balancing). +% +% \medskip +% \textit{Example}: |\atColsBreak{\vskip-2pt}| +% +% \medskip +% \DescribeMacro{\atColsEnd} +% \marg{tokens} +% +% Adds \meta{tokens} at the end of right column. +% +% \medskip +% \textit{Example}: |\atColsEnd{\vfil}|. +% +% \medskip +% \DescribeMacro{\showcolsendrule} +% +% It can be used just for debugging: adds rule to the bottom of columns. +% +% \subsection{Package options} +% +% \medskip +% \DescribeMacro{ancient} +% It is used to switch on old version of balancing algorithm. +% This version is not so accurate or "clever" but quite safe. +% +% \medskip +% \DescribeMacro{modern} +% [default] It is used to switch on new version of balancing algorithm. +% This version has some heuristic guesses for footnotes, floats +% and section like head skip. So it is more dangerous in the case +% for text misplace or disappear. +% +% \medskip +% \DescribeMacro{autobase} +% [default] It is used to guess |\baselineskip| value on original columns +% break. On failure just use |\atColsBreak{...}|. +% +% \medskip +% \DescribeMacro{noautobase} +% It is used to switch off the previous option behaviour. +% +% \medskip +% \DescribeMacro{spread} +% [default] It adds extra glue to the rightcolumn trying to balance. +% +% \medskip +% \DescribeMacro{nospread} +% It skips adding extra glue to the last column. +% +% \medskip +% \DescribeMacro{removelastbox} +% [default] It tries to remove an empty box (some more material) from the last column bottom. +% +% \medskip +% \DescribeMacro{keeplastbox} +% It skips removing anything from the last column. As example it is usefull and can be used +% then document ends by reference item and last line of text should be with indend. +% +% \medskip +% \DescribeMacro{checkfootnote} +% [default] Adds guess for footnote on left column then modern balancing algorithm is in use. +% +% \medskip +% \DescribeMacro{nocheckfootnote} +% Skips guess for footnote then modern balansing algorithm is in use. +% +% \medskip +% \DescribeMacro{checkfloat} +% [default] Adds guess for top float on right column then modern balancing algorithm is in use. +% +% \medskip +% \DescribeMacro{nocheckfloat} +% Skips guess for top float on right column then modern balancing algorithm is in use. +% +% \medskip +% \DescribeMacro{debug} +% Adds rules to the bottom of columns (just for debugging) and leftcolumn break place. +% Adds some additional log info. +% +% \medskip +% \DescribeMacro{nodebug} +% [default] Skips putting debuging lines. +% +% \StopEventually{} +% +% \section{Implementation} +% +% \iffalse +%<*package> +% \fi +% +%/*% \begin{macrocode}*/ +% \begin{macrocode} +\newif\if@auto@baselineskip \@auto@baselineskiptrue +\newif\if@ancient@balance@version \@ancient@balance@versionfalse +\newif\if@right@column@spread \@right@column@spreadtrue +\newif\if@remove@lastbox@at@balancing \@remove@lastbox@at@balancingtrue +\newif\if@balance@debug \@balance@debugfalse +\DeclareOption{autobase}{\global\@auto@baselineskiptrue} +\DeclareOption{noautobase}{\global\@auto@baselineskipfalse} +\DeclareOption{ancient}{\global\@ancient@balance@versiontrue} +\DeclareOption{modern}{\global\@ancient@balance@versionfalse} +\DeclareOption{spread}{\global\@right@column@spreadtrue} +\DeclareOption{nospread}{\global\@right@column@spreadfalse} +\DeclareOption{removelastbox}{\global\@remove@lastbox@at@balancingtrue} +\DeclareOption{keeplastbox}{\global\@remove@lastbox@at@balancingfalse} +\DeclareOption{checkfootnote}{% + \AtEndOfPackage{% + \let\check@@footnoterule@@box\initial@check@@footnoterule@@box + }% + } +\DeclareOption{nocheckfootnote}{% + \AtEndOfPackage{% + \let\check@@footnoterule@@box\@gobblethree + }% + } +\DeclareOption{checkfloat}{% + \AtEndOfPackage{% + \let\top@@floatbox@min\top@@floatbox@min@default + }% + } +\DeclareOption{nocheckfloat}{% + \AtEndOfPackage{% + \let\top@@floatbox@min\maxdimen + }% + } +\DeclareOption{debug}{\global\@balance@debugtrue} +\DeclareOption{nodebug}{\global\@balance@debugfalse} +\ProcessOptions +% \end{macrocode} +% +% \begin{macrocode} +\newskip\flushend@@lastskip@a +\newskip\flushend@@lastskip@b +\newskip\flushend@@lastskip@c +\newcount\flushend@@penalty@a +\newdimen\flushend@@lastkern@a +\newdimen\var@@temp@spread +\newdimen\var@@temp@a +\def\top@@skip@@limit{.7\topskip} +\newdimen\flushend@@page@rule \flushend@@page@rule\z@ +\def\showcolsendrule{\global\flushend@@page@rule=.4\p@} +% \end{macrocode} +% +% \begin{macro}{\top@@floatbox@min}\marg{float size} +% This value is used to catch possible float on right column top. +% \begin{macrocode} +\gdef\top@@floatbox@min@default{4\topskip} +\let\top@@floatbox@min\top@@floatbox@min@default +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +\newbox\flushend@@varbox@a +\newbox\flushend@@varbox@c +\newbox\flushend@@tempbox@a +\newbox\flushend@@tempbox@c +\@ifundefined{@viper}{\newbox\@viper}{} +\@ifundefined{hold@viper}{\newbox\hold@viper}{} +% \end{macrocode} +% +% \begin{macrocode} +\newtoks\atColsBreak \atColsBreak={} +\newtoks\atColsEnd \atColsEnd={} +% \end{macrocode} +% +% \begin{macrocode} +\@ifundefined{fmt@box@adds}{\def\fmt@box@adds#1{#1}}{} +\@ifundefined{fmt@vbox@adds}{\def\fmt@vbox@adds[#1]#2{#2}}{} +% \end{macrocode} +% +% \begin{macro}{\remove@lastbox@at@balancing} +% It is used to remove empty box at the right column end. +% \begin{macrocode} +\def\unskip@three@kern@penalty{% + \unskip\unkern\unpenalty + \unskip\unkern\unpenalty + \unskip\unkern\unpenalty + } +\gdef\remove@lastbox@at@balancing{% + \unskip@three@kern@penalty + \if@remove@lastbox@at@balancing + \else + \expandafter\null + \fi + \bgroup + \setbox\z@\lastbox + \ifdim\wd\z@>\z@ + \box\z@ + \else + \aftergroup\unskip@three@kern@penalty + \fi + \egroup + } +\def\set@split@topskip@to#1{% + \splittopskip#1\relax \vfuzz\maxdimen \vbadness\maxdimen + } +% \end{macrocode} +% \end{macro} +% +% Macros used in debug mode. +% +% \begin{macrocode} +\def\show@@box#1{% + \bgroup + \showboxbreadth=20000\showboxdepth=20000% + \showbox#1\relax + \egroup + } +\def\wlog@balance@debug#1{\if@balance@debug \wlog{#1}\fi} +\def\log@box@info#1{<box\the#1>(\the\ht#1+\the\dp#1)x\the\wd#1} +\let\show@@box@next\@gobble +% \end{macrocode} +% +% To get more or less proper result we need to know about footnotes at +% the left column end, top floats at the right column top, skips and +% so on. This part of the package is responsible for such analysis. +% +% \begin{macrocode} +\gdef\analyze@lastbox@box#1{% + \setbox\flushend@@varbox@a\vbox{% + \unvbox#1% + \global\flushend@@lastskip@a\lastskip + \unskip + \global\var@@temp@a\lastkern + \unkern + \global\flushend@@penalty@a\lastpenalty + \unpenalty + \ifdim\lastskip>\z@ + \global\flushend@@lastskip@a\lastskip + \fi + \unskip + \ifdim\lastkern>\z@ + \global\var@@temp@a\lastkern + \fi + \unkern + \ifnum\lastpenalty>\z@ + \global\flushend@@penalty@a\lastpenalty + \fi + \unpenalty + \global\setbox\flushend@@tempbox@a\lastbox + }% + \wlog@balance@debug{^^J::analyze@lastbox@box::\log@box@info{#1}% + ^^J ::unvbox: \log@box@info{\flushend@@varbox@a}% + ^^J::lastbox: \log@box@info{\flushend@@tempbox@a}% + ^^J::lastskip: \the\flushend@@lastskip@a; + lastkern: \the\var@@temp@a; + lastpenalty: \the\flushend@@penalty@a + }% + } +% \end{macrocode} +% +% \begin{macro}{\analyze@leftcolumn@box}\marg{box} +% +% Fills: +% \begin{itemize} +% \item baselineskip skip from the last boxes to |\flushend@@lastskip@c| +% \item leftcolumn height without the footnote to |\main@box@height| +% \item footnote skip to |\main@box@skip| +% \end{itemize} +% +% \begin{macrocode} +\gdef\analyze@leftcolumn@box#1{% + \set@split@topskip@to\z@ + \flushend@@lastskip@b\ht#1% + \wlog@balance@debug{^^Jmainbox: \log@box@info{#1}}% + \setbox\flushend@@varbox@a\vbox{% + \unvbox#1% + \global\flushend@@lastskip@a\lastskip + \unskip + \global\flushend@@lastkern@a\lastkern + \unkern + \global\flushend@@penalty@a\lastpenalty + \unpenalty + \global\setbox\flushend@@tempbox@a\lastbox + }% + \advance\flushend@@lastskip@b -\ht\flushend@@varbox@a + \advance\flushend@@lastskip@b -\ht\flushend@@tempbox@a + \wlog@balance@debug{.-box: \log@box@info{\flushend@@varbox@a}% + ^^J.-lastbox: \log@box@info{\flushend@@tempbox@a}% + ^^J.-lastskip: \the\flushend@@lastskip@a; + lastkern: \the\flushend@@lastkern@a; + lastpenalty: \the\flushend@@penalty@a + ^^J.-diff: \the\flushend@@lastskip@b + }% + \check@@footnoterule@@box\flushend@@tempbox@a\flushend@@lastskip@b\flushend@@varbox@a + \check@@baselineskip@@skip + \flushend@@lastskip@a + \flushend@@lastskip@b + \flushend@@lastskip@c + \ifx\check@@footnoterule@@box\check@@baselineskip@@skip + \else + \ifvoid\flushend@@tempbox@a + \ifdim\ht\flushend@@varbox@a>\topskip + \flushend@@lastskip@b\ht\flushend@@varbox@a + \var@@temp@a\ht\flushend@@varbox@a + \loop + \setbox\flushend@@tempbox@c\vsplit\flushend@@varbox@a to\var@@temp@a + \ifvoid\flushend@@varbox@a + \setbox\flushend@@varbox@a\vbox{\unvbox\flushend@@tempbox@c}% + \advance \var@@temp@a -3\p@ + \else + \var@@temp@a=-1\p@ + \fi + \ifdim \var@@temp@a>\z@ + \repeat + \setbox\flushend@@varbox@a\vbox{\unvbox\flushend@@varbox@a}% + \setbox\flushend@@tempbox@c\vbox{\unvbox\flushend@@tempbox@c}% + \advance\flushend@@lastskip@b -\ht\flushend@@varbox@a + \advance\flushend@@lastskip@b -\ht\flushend@@tempbox@c + \wlog@balance@debug{..--box: \log@box@info{\flushend@@tempbox@c}% + ^^J..--lastbox: \log@box@info{\flushend@@varbox@a}% + ^^J..--diff: \the\flushend@@lastskip@b + }% + \check@@footnoterule@@box\flushend@@varbox@a\flushend@@lastskip@b + \flushend@@tempbox@c + \check@@baselineskip@@skip\flushend@@lastskip@a\flushend@@lastskip@b + \flushend@@lastskip@c + \ifx\check@@footnoterule@@box\check@@baselineskip@@skip + \else + \ifdim\ht\flushend@@varbox@a>.5\topskip + \analyze@lastbox@box\flushend@@varbox@a + \fi + \setbox\flushend@@varbox@a\vbox{\unvbox\flushend@@tempbox@c}% + \fi + \else + \wlog@balance@debug{lastbox: \log@box@info{\flushend@@varbox@a}}% + \fi + \fi + \ifdim\ht\flushend@@varbox@a>\topskip + \expandafter\analyze@leftcolumn@box\expandafter\flushend@@varbox@a + \fi + \fi + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\get@@footnoterule@@box} +% +% Gets dimensions of the box made by |footnoterule| and writes to: +% |\footnoterule@@box@@ht|, |\footnoterule@@box@@dp|, |\footnoterule@@box@@wd|. +% +% \begin{macrocode} +\def\get@@footnoterule@@box{% + \set@split@topskip@to\z@ + \setbox\flushend@@varbox@a\vbox{\strut + \vskip\z@ + \footnoterule + \unskip\unkern\unpenalty + \unskip\unkern\unpenalty + }% + \setbox\flushend@@tempbox@c\vsplit\flushend@@varbox@a to\p@ + \xdef\footnoterule@@box@@ht{\the\ht\flushend@@varbox@a}% + \xdef\footnoterule@@box@@dp{\the\dp\flushend@@varbox@a}% + \xdef\footnoterule@@box@@wd{\the\wd\flushend@@varbox@a}% + \wlog@balance@debug{:footnoterule: \log@box@info{\flushend@@varbox@a}}% + \setbox\flushend@@tempbox@c\vbox{\unvbox\flushend@@varbox@a}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\check@@footnoterule@@box}\marg{box1}\marg{skip}\marg{box2} +% +% Checks if \marg{box1} dimensions equals to |footnoterule| box dimensions. +% If so and if \marg{skip} is not |\topskip| we guess it is footnote. +% In that case we define |leftcolumn| height without |footnote| as +% \marg{box2} height and save it as |\main@box@height|. Skip from text to +% footnote define as |\main@box@skip|. +% +% \begin{macrocode} +\long\def\@gobblethree#1#2#3{} +\def\check@@footnoterule@@box#1#2#3{% + \ifdim\ht#1=\footnoterule@@box@@ht + \ifdim\dp#1=\footnoterule@@box@@dp + \ifdim\wd#1=\footnoterule@@box@@wd + \ifdim#2=\topskip + \else + \xdef\main@box@height{\the\ht#3}% + \xdef\main@box@skip{\the#2}% + \wlog@balance@debug{^^J:footnoterule found: + main@box <ht=\main@box@height, + skip=\main@box@skip> + }% + \global\let\check@@footnoterule@@box\@gobblethree + \global\let\check@@baselineskip@@skip\reset@check@@baselineskip@@skip + \fi + \fi + \fi + \fi + } +\let\initial@check@@footnoterule@@box\check@@footnoterule@@box +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\check@@baselineskip@@skip}\marg{dimension1}\marg{dimension2}\marg{var} +% +% If both dimensions: \marg{dimension1} and \marg{dimension2} are positive we +% define by \marg{var} value of \marg{dimension1} as last skip between text lines +% and deactivate |\check@@baselineskip@@skip| itself. +% +% \begin{macrocode} +\def\check@@baselineskip@@skip#1#2#3{% + \ifdim#1>\z@ + \ifdim#2>\z@ + \global#3=\the#1% + \global\let\check@@baselineskip@@skip\@gobblethree + \fi + \fi + } +\let\initial@check@@baselineskip@@skip\check@@baselineskip@@skip +% \end{macrocode} +% +% In the case we found footnote it is necessary to look for the last skip +% between text lines again. For that we use +% |\reset@check@@baselineskip@@skip|. It activates |\check@@baselineskip@@skip|. +% +% \begin{macrocode} +\def\reset@check@@baselineskip@@skip#1#2#3{% + \global#3=\z@ + \global\let\check@@baselineskip@@skip\initial@check@@baselineskip@@skip + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\analyze@rightcolumn@box}\marg{box} +% +% Some guess of possible float or section title at the top of right column.\break +% Fills: +% \begin{itemize} +% \item float height to |\top@@floatbox@ht| +% \item float skip to |\top@@floatbox@skip| +% \item head skip to |\top@@section@skip| +% \end{itemize} +% +% \begin{macrocode} +\def\analyze@rightcolumn@box#1{% + \bgroup + \xdef\top@@floatbox@ht{\z@}% + \xdef\top@@floatbox@skip{\z@}% + \xdef\top@@section@skip{\z@}% + \set@split@topskip@to\z@ + \setbox\flushend@@varbox@a\vbox{\strut + \vskip\z@ + \unvcopy#1% + }% + \setbox\flushend@@tempbox@c\vsplit\flushend@@varbox@a to\p@ + \wlog@balance@debug{^^J(R)mainbox: \log@box@info{#1}}% + \flushend@@lastskip@a\ht\flushend@@varbox@a + \advance\flushend@@lastskip@a\dp\flushend@@varbox@a + \ifdim\flushend@@lastskip@a>\z@ + \analyze@nonempty@rightcolumn@box + \fi + \egroup + } +\def\analyze@nonempty@rightcolumn@box{% + \bgroup + \var@@temp@a3\p@ + \loop + \flushend@@lastskip@b\ht\flushend@@varbox@a + \advance\flushend@@lastskip@b\dp\flushend@@varbox@a + \setbox\flushend@@tempbox@c\vsplit\flushend@@varbox@a to\var@@temp@a + \ifvoid\flushend@@tempbox@c + \advance \var@@temp@a 3\p@ + \ifdim\var@@temp@a>\flushend@@lastskip@b + \var@@temp@a=-1\p@ + \fi + \else + \setbox\flushend@@tempbox@c\vbox{\unvbox\flushend@@tempbox@c}% + \ifdim\ht\flushend@@tempbox@c>\top@@floatbox@min + \advance\flushend@@lastskip@b -\ht\flushend@@tempbox@c + \advance\flushend@@lastskip@b -\dp\flushend@@tempbox@c + \advance\flushend@@lastskip@b -\ht\flushend@@varbox@a + \advance\flushend@@lastskip@b -\dp\flushend@@varbox@a + \xdef\top@@floatbox@skip{\the\flushend@@lastskip@b}% + \flushend@@lastskip@b\flushend@@lastskip@a + \advance\flushend@@lastskip@b -\ht\flushend@@varbox@a + \advance\flushend@@lastskip@b -\top@@floatbox@skip + \xdef\top@@floatbox@ht{\the\flushend@@lastskip@b}% + \var@@temp@a=3\p@ + \else + \advance\flushend@@lastskip@b -\ht\flushend@@tempbox@c + \advance\flushend@@lastskip@b -\dp\flushend@@tempbox@c + \advance\flushend@@lastskip@b -\ht\flushend@@varbox@a + \advance\flushend@@lastskip@b -\dp\flushend@@varbox@a + \ifdim\ht\flushend@@tempbox@c>\topskip + \else + \xdef\top@@section@skip{\the\flushend@@lastskip@b}% + \fi + \var@@temp@a=-1\p@ + \fi + \fi + \ifdim \var@@temp@a>\z@ + \repeat + \ifvoid\flushend@@tempbox@c + \else + \ifdim\top@@section@skip>\z@ + \else + \ifdim\ht\flushend@@tempbox@c>\z@ + \setbox\flushend@@varbox@a\vbox{\unvbox\flushend@@tempbox@c}% + \fi + \flushend@@lastskip@b\ht\flushend@@varbox@a + \var@@temp@a=3\p@ + \loop + \setbox\flushend@@tempbox@c\vsplit\flushend@@varbox@a to\var@@temp@a + \ifvoid\flushend@@tempbox@c + \advance \var@@temp@a 3\p@ + \ifdim\var@@temp@a>\flushend@@lastskip@b + \var@@temp@a=-1\p@ + \fi + \else + \ifdim\ht\flushend@@tempbox@c<\z@ + \else + \var@@temp@a=-1\p@ + \fi + \fi + \ifdim \var@@temp@a>\z@ + \repeat + \loop + \setbox\flushend@@varbox@a\vbox{% + \unvbox\flushend@@tempbox@c + \unskip\unkern\unpenalty + \unskip\unkern\unpenalty + \unskip\unkern\unpenalty + \setbox\flushend@@tempbox@c\lastbox + }% + \flushend@@lastskip@b\ht\flushend@@varbox@a + \setbox\flushend@@varbox@a\vbox{% + \unvbox\flushend@@varbox@a + \unskip\unkern\unpenalty + \unskip\unkern\unpenalty + \unskip\unkern\unpenalty + }% + \advance\flushend@@lastskip@b -\ht\flushend@@varbox@a + \ifdim\flushend@@lastskip@b>\topskip + \xdef\top@@section@skip{\the\flushend@@lastskip@b}% + \fi + \ifdim\ht\flushend@@varbox@a>2\topskip + \setbox\flushend@@tempbox@c\vbox{\unvbox\flushend@@varbox@a}% + \repeat + \fi + \fi + \egroup + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\combine@columns@for@balance} +% +% Collects both columns to one box removing left column footnotes +% and right column top float and adding right skip in between them. +% +% \begin{macrocode} +\def\combine@columns@for@balance{% + \setbox\@outputbox\vbox{\strut + \vskip\z@ + \unvbox\@outputbox + }% + \set@split@topskip@to\z@ + \setbox\flushend@@tempbox@c\vsplit\@outputbox to\p@ + \if@auto@baselineskip + %% Trying guess baselineskip value on column break + \ifdim\top@@floatbox@skip>\z@ + \setbox\flushend@@tempbox@c\vsplit\@outputbox to\top@@floatbox@ht + \setbox\flushend@@tempbox@c\vbox{\unvbox\flushend@@tempbox@c}% + \fi + \setbox\@tempboxa\vbox{% + \unvbox\flushend@@varbox@a + \unskip\unkern\unpenalty + \vskip\flushend@@lastskip@c + \the\atColsBreak + \hrule\@height\flushend@@page@rule width\columnwidth + \ifdim\top@@section@skip>\top@@skip@@limit + \vskip\top@@section@skip + \fi + \unvbox\@outputbox + \remove@lastbox@at@balancing + \the\atColsEnd + }% + \ifdim\top@@floatbox@skip>\z@ + \setbox\@outputbox\vbox{\unvbox\flushend@@tempbox@c}% + \fi + \else + %% Ignore baselineskip value on column break + \setbox\@tempboxa\vbox{% + \unvbox\@leftcolumn + \setbox\z@\lastbox + \unskip\unkern\unpenalty + \the\atColsBreak + \hrule\@height\flushend@@page@rule width\columnwidth + \unvbox\@outputbox + \remove@lastbox@at@balancing + \the\atColsEnd + }% + \fi + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\set@outputbox@with@footnote} +% +% Calculates break position and formats balanced columns in the |\@outputbox| +% with footnotes. +% +% \begin{macrocode} +\def\set@outputbox@with@footnote{% + %% footnote in left column + \@tempdimb\ht\@tempboxa + \ifdim\top@@floatbox@skip>\z@ + \advance\@tempdimb \top@@floatbox@skip + \advance\@tempdimb \top@@floatbox@ht + \fi + \advance\@tempdimb \main@box@skip + \advance\@tempdimb \ht\@leftcolumn + \@tempdimb .5\@tempdimb + \advance\@tempdimb -\main@box@skip + \advance\@tempdimb -\ht\@leftcolumn + \set@split@topskip@to\topskip + \loop + \setbox\flushend@@varbox@a\copy\@tempboxa + \setbox\flushend@@tempbox@a\vsplit\flushend@@varbox@a to\@tempdimb + \setbox\flushend@@tempbox@c\vbox{\unvcopy\flushend@@tempbox@a}% + \ifdim\top@@floatbox@skip>\z@ + \setbox\flushend@@varbox@c\vbox{% + \unvcopy\@outputbox + \vskip\top@@floatbox@skip + \unvbox\flushend@@varbox@a + }% + \else + \setbox\flushend@@varbox@c\vbox{\unvbox\flushend@@varbox@a}% + \fi + \var@@temp@spread=\ht\flushend@@tempbox@c + \advance\var@@temp@spread by\dp\flushend@@tempbox@c + \advance\var@@temp@spread \main@box@skip + \advance\var@@temp@spread \ht\@leftcolumn + \advance\var@@temp@spread by-\ht\flushend@@varbox@c + \advance\var@@temp@spread by-\dp\flushend@@varbox@c + \wlog@balance@debug{Left x: \the\ht\flushend@@tempbox@a + +\the\dp\flushend@@tempbox@a=\the\ht\flushend@@varbox@a + +\the\dp\flushend@@varbox@a::\the\@tempdimb + ^^JLeft 0: \the\ht\flushend@@tempbox@c + +\the\dp\flushend@@tempbox@c::\the\@tempdimb + ^^JRight x: \the\ht\flushend@@varbox@c + +\the\dp\flushend@@varbox@c=\the\ht\flushend@@varbox@a + +\the\dp\flushend@@varbox@a::\the\@tempdimb + ^^JExtra height:\the\var@@temp@spread\space when \the\@tempdimb + }% + \ifdim\var@@temp@spread<\z@ + \advance\@tempdimb 1\p@ + \repeat + \flushend@@lastskip@a\the\ht\flushend@@tempbox@c + \advance\flushend@@lastskip@a \main@box@skip + \advance\flushend@@lastskip@a \ht\@leftcolumn + \flushend@@lastskip@b\the\@tempdimb + \setbox\flushend@@tempbox@a\vsplit\@tempboxa to\@tempdimb + \setbox\@leftcolumn\vbox to\@tempdima{% + \vbox to \flushend@@lastskip@a{% + \unvbox\flushend@@tempbox@a + \vskip\main@box@skip + \unvbox\@leftcolumn + \vss + }% + \hrule\@height\flushend@@page@rule width\textwidth + \vss + }% + \global\ht\@leftcolumn=\the\@tempdima + \wlog{- LAST -% + ^^JExtra skip:\the\var@@temp@spread + ^^JLeft:\the\ht\@leftcolumn/\the\dp\@leftcolumn + ^^JRight:\the\ht\@tempboxa/\the\dp\@tempboxa + ^^JOutput:\the\@tempdimb + }% + \ifdim\top@@floatbox@skip>\z@ + \setbox\@outputbox\vbox to\@tempdima{% + \if@right@column@spread + \vbox spread\var@@temp@spread{% + \unvbox\@outputbox + \vskip\top@@floatbox@skip + \unvbox\@tempboxa + }% + \else + \vbox spread\var@@temp@spread{% + \unvbox\@outputbox + \vskip\top@@floatbox@skip + \unvbox\@tempboxa + \vss + }% + \fi + \vss + }% + \else + \setbox\@outputbox\vbox to\@tempdima{% + \if@right@column@spread + \vbox spread\var@@temp@spread{% + \unvbox\@tempboxa + }% + \else + \vbox spread\var@@temp@spread{% + \unvbox\@tempboxa + \vss + }% + \fi + \vss + }% + \fi + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\set@outputbox@without@footnote} +% +% Calculates break position and formats balanced columns in the |\@outputbox| +% without footnotes. +% +% \begin{macrocode} +\def\set@outputbox@without@footnote{% + %% no footnote in left column + \@tempdimb \ht\@tempboxa + \ifdim\top@@floatbox@skip>\z@ + \advance\@tempdimb \top@@floatbox@skip + \advance\@tempdimb \top@@floatbox@ht + \fi + \@tempdimb .5\@tempdimb + \set@split@topskip@to\topskip + \loop + \setbox\flushend@@varbox@a\copy\@tempboxa + \setbox\flushend@@tempbox@a\vsplit\flushend@@varbox@a to\@tempdimb + \setbox\flushend@@tempbox@c\vbox{\unvcopy\flushend@@tempbox@a}% + \ifdim\top@@floatbox@skip>\z@ + \setbox\flushend@@varbox@c\vbox{% + \unvcopy\@outputbox + \vskip\top@@floatbox@skip + \unvbox\flushend@@varbox@a + }% + \else + \setbox\flushend@@varbox@c\vbox{\unvbox\flushend@@varbox@a}% + \fi + \var@@temp@spread=\ht\flushend@@tempbox@c + \advance\var@@temp@spread by\dp\flushend@@tempbox@c + \advance\var@@temp@spread by-\ht\flushend@@varbox@c + \advance\var@@temp@spread by-\dp\flushend@@varbox@c + \wlog@balance@debug{Left x: \the\ht\flushend@@tempbox@a + +\the\dp\flushend@@tempbox@a=\the\ht\flushend@@varbox@a + +\the\dp\flushend@@varbox@a::\the\@tempdimb + ^^JLeft 0: \the\ht\flushend@@tempbox@c + +\the\dp\flushend@@tempbox@c::\the\@tempdimb + ^^JRight x: \the\ht\flushend@@varbox@c + +\the\dp\flushend@@varbox@c=\the\ht\flushend@@varbox@a + +\the\dp\flushend@@varbox@a::\the\@tempdimb + ^^JExtra height:\the\var@@temp@spread\space when \the\@tempdimb + }% + \ifdim\var@@temp@spread<\z@ \advance\@tempdimb 1\p@ \repeat + \wlog{- LAST -% + ^^JExtra skip:\the\var@@temp@spread + ^^JLeft:\the\ht\flushend@@tempbox@c/\the\dp\flushend@@tempbox@c + ^^JRight:\the\ht\flushend@@varbox@c/\the\dp\flushend@@varbox@c + ^^JOutput:\the\@tempdimb + }% + \setbox\flushend@@tempbox@c\vsplit\@tempboxa to\@tempdimb + \setbox\flushend@@varbox@c\vbox{\unvbox\flushend@@tempbox@c}% + \setbox\@leftcolumn\vbox to\@tempdima{% + \vbox to\@tempdimb{\unvbox\flushend@@varbox@c\vss}% + \hrule\@height\flushend@@page@rule width\textwidth + \vss + }% + \global\ht\@leftcolumn=\the\@tempdima + \ifdim\top@@floatbox@skip>\z@ + \setbox\@outputbox\vbox to\@tempdima{% + \if@right@column@spread + \vbox spread\var@@temp@spread{% + \unvbox\@outputbox + \vskip\top@@floatbox@skip + \unvbox\@tempboxa + }% + \else + \vbox spread\var@@temp@spread{% + \unvbox\@outputbox + \vskip\top@@floatbox@skip + \unvbox\@tempboxa + \vss + }% + \fi + \vss + }% + \else + \setbox\@outputbox\vbox to\@tempdima{% + \if@right@column@spread + \vbox spread\var@@temp@spread{% + \unvbox\@tempboxa + }% + \else + \vbox spread\var@@temp@spread{% + \unvbox\@tempboxa + \vss + }% + \fi + \vss + }% + \fi + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\last@outputdblcol@modern} +% +% Columns balancing of the twocolumn mode page (modern algorithm). +% It is maybe not so safe for text moving or missing at all +% as it uses some heuristic technique to find footnotes, last skip between lines +% at left column and floats or section like heads at right column top +% for replacing them (except heads of course) to other places in text. +% +% \begin{macrocode} +\def\last@outputdblcol@modern{% + \if@firstcolumn + \global \@firstcolumnfalse + \global \setbox\@leftcolumn \box\@outputbox + \else + \global \@firstcolumntrue + \@tempdima\ht\@leftcolumn + \set@split@topskip@to\topskip + \var@@temp@spread=\wd\@outputbox + \get@@footnoterule@@box + \xdef\main@box@height{\the\ht\@leftcolumn}% + \xdef\main@box@skip{\z@}% + \global\flushend@@lastskip@c\z@ + \setbox\flushend@@varbox@a\vbox{\unvcopy\@leftcolumn}% + \analyze@leftcolumn@box\flushend@@varbox@a + \setbox\flushend@@varbox@a\vbox{\unvcopy\@outputbox}% + \analyze@rightcolumn@box\flushend@@varbox@a + \ifdim\main@box@skip>\z@ + %% footnote in left column + \set@split@topskip@to\z@ + \setbox\flushend@@varbox@a\vsplit\@leftcolumn to\main@box@height + \else + %% no footnote in left column + \setbox\flushend@@varbox@a\box\@leftcolumn + \fi + \ifdim\var@@temp@spread>\z@ + %% rightcolumn non empty + \combine@columns@for@balance + \else + %% rightcolumn empty + \setbox\@tempboxa\vbox{% + \unvbox\flushend@@varbox@a + \remove@lastbox@at@balancing + \the\atColsEnd + }% + \fi + \ifdim\main@box@skip>\z@ + %% footnote in left column + \set@outputbox@with@footnote + \else + %% no footnote in left column + \set@outputbox@without@footnote + \fi + \setbox\@outputbox \vbox {% + \hb@xt@\textwidth {% + \hb@xt@\columnwidth {% + \fmt@box@adds{\box\@leftcolumn}\hss}% + \hfil + \vrule \@width\columnseprule + \hfil + \hb@xt@\columnwidth {% + \fmt@box@adds{\box\@outputbox}\hss}% + }% + }% + \global\let\@outputdblcol\saved@orig@@outputdblcol + \global\atColsEnd{}% + \ifvoid\hold@viper + \else + \setbox\@outputbox\vbox{\box\hold@viper\box\@outputbox}% + \fi + \@combinedblfloats + \@outputpage + \begingroup + \@dblfloatplacement + \@startdblcolumn + \@whilesw\if@fcolmade\fi + {\@outputpage\@startdblcolumn}% + \ifvoid\@viper + \else + \global\setbox\@viper\vbox{% + \vskip-\stripsep + \unvbox\@viper + }% + \csname @viperoutput\endcsname + \fi + \endgroup + \fi + } +% \end{macrocode} +% \end{macro} +% \begin{macro}{\last@outputdblcol@old} +% +% Columns balancing of the twocolumn mode page (ancient algorithm). +% It is maybe not so good in some cases but maybe more safe for text +% moving or missing at all. +% +% \begin{macrocode} +\def\last@outputdblcol@ancient{% + \if@firstcolumn + \global\@firstcolumnfalse + \global\setbox\@leftcolumn\box\@outputbox + \else + \global\@firstcolumntrue + \@tempdima\ht\@leftcolumn + \set@split@topskip@to\topskip + \if@auto@baselineskip + \setbox\@tempboxa\vbox{% + \unvcopy\@leftcolumn + \global\flushend@@lastskip@c\lastskip + \global\flushend@@lastskip@b\lastskip + \loop + \global\flushend@@lastskip@a\flushend@@lastskip@b + \unskip\unpenalty + \global\flushend@@lastskip@b\lastskip + \global\advance\flushend@@lastskip@c by\lastskip + \ifdim\flushend@@lastskip@b=-\flushend@@lastskip@a + \global\advance\flushend@@lastskip@c by-\lastskip + \else + \repeat + \ifdim\flushend@@lastskip@b=-\flushend@@lastskip@a + \ifdim\flushend@@lastskip@b=\z@ + \setbox\flushend@@varbox@a\lastbox + \global\advance\flushend@@lastskip@c by\ht\flushend@@varbox@a + \global\advance\flushend@@lastskip@c by\lastskip + \unskip\unpenalty + \setbox\flushend@@varbox@a\lastbox + \global\advance\flushend@@lastskip@c by\dp\flushend@@varbox@a + \else + \global\flushend@@lastskip@c\lastskip + \global\advance\flushend@@lastskip@c by\topskip + \fi + \fi + \global\advance\flushend@@lastskip@c by-\topskip + }% + \setbox\@tempboxa\vbox{% + \unvbox\@leftcolumn + \unskip\unpenalty + \vskip\flushend@@lastskip@c + \hrule\@height\flushend@@page@rule width\columnwidth + \the\atColsBreak + \unvbox\@outputbox + \remove@lastbox@at@balancing + \the\atColsEnd + }% + \else + \setbox\@tempboxa\vbox{% + \unvbox\@leftcolumn + \setbox\z@\lastbox + \unskip + \hrule\@height\flushend@@page@rule width\columnwidth + \the\atColsBreak + \unvbox\@outputbox + \remove@lastbox@at@balancing + \the\atColsEnd + }% + \fi + \@tempdimb .5\ht\@tempboxa + \loop + \setbox\flushend@@tempbox@a\copy\@tempboxa + \setbox\flushend@@tempbox@c\vbox to\@tempdimb{% + \vsplit\flushend@@tempbox@a to\@tempdimb + \vss + \vsplit\flushend@@tempbox@a to\@tempdimb + }% + \wlog{Extra height:\the\ht\flushend@@tempbox@a\space when \the\@tempdimb}% + \ifvoid\flushend@@tempbox@a + \else + \advance\@tempdimb 1\p@ + \repeat + \loop + \setbox\flushend@@tempbox@a\copy\@tempboxa + \setbox\flushend@@tempbox@c\vbox to\@tempdimb{% + \vsplit\flushend@@tempbox@a to\@tempdimb + \vss + }% + \wlog{(2)Left:\the\ht\flushend@@tempbox@c\space + Right:\the\ht\flushend@@tempbox@a\space + Output:\the\@tempdimb + }% + \ifdim\ht\flushend@@tempbox@c<\ht\flushend@@tempbox@a + \@tempdimb=\the\ht\flushend@@tempbox@a + \repeat + \wlog{- LAST -^^JExtra skip: \the\z@ + ^^JLeft:\the\ht\flushend@@tempbox@c + ^^JRight:\the\ht\flushend@@tempbox@a + ^^JOutput:\the\@tempdimb + }% + \setbox\flushend@@tempbox@c\vbox to\@tempdimb{% + \vsplit\@tempboxa to\@tempdimb + \vss + }% + \setbox\@leftcolumn\vbox to\@tempdima{% + \fmt@vbox@adds[\columnwidth]{% + \vbox to\@tempdimb{% + \unvbox + \flushend@@tempbox@c + }% + }% + \hrule\@height\flushend@@page@rule + \vss + }% + \setbox\@outputbox\vbox to\@tempdima{% + \fmt@vbox@adds[\columnwidth]{% + \vbox to\@tempdimb{% + \unvbox\@tempboxa + \vskip\z@ + }% + }% + \hrule\@height\flushend@@page@rule + \vss + }% + \setbox\@outputbox\vbox{% + \hb@xt@\textwidth{% + \hb@xt@\columnwidth{\box\@leftcolumn\hss}% + \hfil + \vrule \@width\columnseprule + \hfil + \hb@xt@\columnwidth{\box\@outputbox\hss}% + }% + }% + \global\let\@outputdblcol\saved@orig@@outputdblcol + \global\atColsEnd{}% + \ifvoid\hold@viper + \else + \setbox\@outputbox\vbox{\box\hold@viper\box\@outputbox}% + \fi + \@combinedblfloats + \@outputpage + \begingroup + \@dblfloatplacement + \@startdblcolumn + \@whilesw\if@fcolmade\fi + {\@outputpage\@startdblcolumn}% + \ifvoid\@viper + \else + \global\setbox\@viper\vbox{% + \vskip-\stripsep + \unvbox\@viper + }% + \csname @viperoutput\endcsname + \fi + \endgroup + \fi + } +% \end{macrocode} +% \end{macro} +% +% Adds default balancing of the last page at the end of document. +% +% \begin{macrocode} +\usepackage{etoolbox} +\AtBeginDocument{% + \global\let\saved@orig@@outputdblcol\@outputdblcol + \if@ancient@balance@version + \global\let\last@outputdblcol\last@outputdblcol@ancient + \else + \global\let\last@outputdblcol\last@outputdblcol@modern + \fi + \global\let\balanced@@outputdblcol\last@outputdblcol + \preto\enddocument{\let\@outputdblcol\balanced@@outputdblcol}% + \appto\footnoterule{\vskip\z@}% + } +% \end{macrocode} +% +% User interface commands for the balancing pages. +% +% \cs{flushcolsend} is used to switch on column balancing on the current page. +% +% \begin{macrocode} +\def\flushcolsend{\global\let\@outputdblcol\last@outputdblcol} +% \end{macrocode} +% +% \cs{raggedcolsend} is used to switch off column balancing on the current page. +% +% \begin{macrocode} +\def\raggedcolsend{\global\let\@outputdblcol\saved@orig@@outputdblcol} +% \end{macrocode} +% +% \cs{flushend} is used to switch on column balancing on the last page. +% It is used by default. +% +% \begin{macrocode} +\def\flushend{\global\let\balanced@@outputdblcol\last@outputdblcol} +% \end{macrocode} +% +% \cs{raggedend} is used to switch off column balancing on the last page. +% +% \begin{macrocode} +\def\raggedend{\global\let\balanced@@outputdblcol\saved@orig@@outputdblcol} +% \end{macrocode} +% +% In the case to see some debug information |debug| option is used and it is +% possible to see how package calculates dimensions of balanced columns by +% additional rules on balanced page and some log records in log file. +% +% \begin{macrocode} +\if@balance@debug + \showcolsendrule +\fi +% \end{macrocode} +% +% \iffalse +%</package> +% \fi +% +% \Finale |