% \iffalse meta-comment/*%    \end{macrocode}*/
%
% Copyright (C) 2020 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
\preamble
%%
%% This is file `flushend.sty',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% flushend.dtx  (with options: `package')
%% 
\endpreamble
\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-2020 by Sigitas Tolu\v{s}is <sigitas@vtex.lt>
%% VTeX Ltd., Mokslinink\k{u} 2a, Vilnius, Lithuania
%% --------------------------------------------------------------------------
%% 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>
    [2020/10/16 v3.5 Balancing columns in twocolumn mode]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{flushend}[2020/10/16]
\EnableCrossrefs
\CodelineIndex
%%\RecordChanges
%\OnlyDescription
\begin{document}
  \DocInput{flushend.dtx}
  %%\PrintChanges
  %%\PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{2020}
%
% \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}
% \changes{v3.4}{2020/10/14}{bugfix development and test}
% \changes{v3.5}{2020/10/16}{bugfix version: modern with noautobase}
%
% \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
\newcount\var@@loop@iter
\newdimen\flushend@@lastkern@a
\newdimen\var@@temp@spread
\newdimen\var@@temp@a
\newdimen\var@@temp@loop
\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\var@@temp@loop=\ht\flushend@@varbox@a\relax
           \global\advance\var@@loop@iter\@ne
        \fi
        \var@@temp@loop=\ht\flushend@@varbox@a\relax
        \ifnum\var@@loop@iter<3\relax
            \wlog@balance@debug{analyze left col: iteration \number\var@@loop@iter; ht \the\var@@temp@loop}%
        \else
            \wlog@balance@debug{analyze left col loop limit!}%
            \ht\flushend@@varbox@a\z@
        \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\var@@temp@loop=\ht\flushend@@varbox@a\relax
                        \advance\var@@loop@iter\@ne
                    \fi
                    \var@@temp@loop=\ht\flushend@@varbox@a\relax
                    \ifnum\var@@loop@iter<3\relax
                        \wlog@balance@debug{analyze right col: iteration \number\var@@loop@iter; ht \the\var@@temp@loop}%
                    \else
                        \wlog@balance@debug{analyze right col loop limit!}%
                        \ht\flushend@@varbox@a=\z@
                    \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
            \hrule\@height\flushend@@page@rule width\columnwidth
            \vskip-\flushend@@page@rule
            \hrule\@height\z@ width\columnwidth
            \vskip\flushend@@lastskip@c
            \the\atColsBreak
            \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\flushend@@varbox@a
            \unskip\unkern\unpenalty
            \hrule\@height\flushend@@page@rule width\columnwidth
            \vskip-\flushend@@page@rule
            \hrule\@height\z@ width\columnwidth
            \the\atColsBreak
            \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
        \vskip-\flushend@@page@rule
        \hrule\@height\z@ width\columnwidth
        \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
        \vskip-\flushend@@page@rule
        \hrule\@height\z@ 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\copy\@outputbox
        \splitmaxdepth\maxdimen
        \vbadness\maxdimen
        \setbox\@outputbox\vbox{\unvbox\@outputbox\unskip}%
        \setbox\@outputbox\vsplit\@outputbox to\maxdimen
        \toks@\expandafter{\topmark}%
        \xdef\@firstcoltopmark{\the\toks@}%
        \toks@\expandafter{\splitfirstmark}%
        \xdef\@firstcolfirstmark{\the\toks@}%
        \ifx\@firstcolfirstmark\@empty
            \global\let\@setmarks\relax
        \else
            \gdef\@setmarks{%
                \let\firstmark\@firstcolfirstmark
                \let\topmark\@firstcoltopmark
                }%
        \fi
    \else
        \global \@firstcolumntrue
        \@tempdima\ht\@leftcolumn
        \advance\@tempdima by\dp\@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@}%
        \reset@check@@baselineskip@@skip\relax\relax\flushend@@lastskip@c
        \setbox\flushend@@varbox@a\vbox{\unvcopy\@leftcolumn}%
        \var@@loop@iter\z@ \var@@temp@loop\z@
        \analyze@leftcolumn@box\flushend@@varbox@a
        \setbox\flushend@@varbox@a\vbox{\unvcopy\@outputbox}%
        \var@@loop@iter\z@ \var@@temp@loop\z@
        \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
        \csname @setmarks\endcsname
        \@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
                \vskip-\flushend@@page@rule
                \hrule\@height\z@ width\textwidth
                \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
                \vskip-\flushend@@page@rule
                \hrule\@height\z@ width\textwidth
                \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
            \vskip-\flushend@@page@rule
            \hrule\@height\z@ width\textwidth
            \vss
            }%
        \setbox\@outputbox\vbox to\@tempdima{%
            \fmt@vbox@adds[\columnwidth]{%
                \vbox to\@tempdimb{%
                    \unvbox\@tempboxa
                    \vskip\z@
                    }%
                }%
            \hrule\@height\flushend@@page@rule
            \vskip-\flushend@@page@rule
            \hrule\@height\z@ width\textwidth
            \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
