% \iffalse meta-comment
%
% Copyright (C) 2014 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
%<*driver>
\ProvidesFile{flushend.dtx}
%</driver>
%<*package>
%% Copyright (C) 1997-2014 by Sigitas Tolu\v{s}is <sigitas@vtex.lt>
%% VTeX Ltd., Akademijos 4, 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>
    [2014/04/24 v2.2 Balancing columns in twocolumn mode]
%</package>
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{flushend}[2014/03/18]
\EnableCrossrefs
\CodelineIndex
%%\RecordChanges
\begin{document}
  \DocInput{flushend.dtx}
  %%\PrintChanges
  %%\PrintIndex
\end{document}
%</driver>
% \fi
%
% \CheckSum{1312}
%
% \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}
%
% \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{autobase}
%   It is used to guess |\baselineskip| value on original columns break.
% 
% \medskip
% \DescribeMacro{noauto}
%   It is used to switch off the previous option behaviour.
%
% \medskip
% \DescribeMacro{debug}
%   Adds rules to the bottom of columns (just for debugging) and leftcolumn break place.
%   Adds some additional log info.
%
% \StopEventually{}
% 
% \section{Implementation}
%
% \iffalse
%<*package>
% \fi
%
%
%    \begin{macrocode}
\newif\if@auto@baselineskip \@auto@baselineskiptrue
\newif\if@balance@debug \@balance@debugfalse
\DeclareOption{autobase}{\global\@auto@baselineskiptrue}
\DeclareOption{noauto}{\global\@auto@baselineskipfalse}
\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
\newdimen\flushend@@page@rule \flushend@@page@rule\z@
\def\showcolsendrule{\global\flushend@@page@rule=.4pt}
%    \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{4\topskip}
%    \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
  \bgroup
    \setbox\z@\lastbox
    \ifdim\wd\z@>\z@
      \box\z@
    \else
      \aftergroup\unskip@three@kern@penalty
    \fi
  \egroup
  }
%    \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}
%    \begin{macrocode}
\gdef\analyze@leftcolumn@box#1{%
  \splittopskip\z@ \vfuzz\maxdimen \vbadness\maxdimen
  \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
  \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
          \ifdim\ht\flushend@@varbox@a>.5\topskip
              \analyze@lastbox@box\flushend@@varbox@a
          \fi
          \setbox\flushend@@varbox@a\vbox{\unvbox\flushend@@tempbox@c}%
      \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
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\get@@footnoterule@@box}
%    \begin{macrocode}
\def\get@@footnoterule@@box{%
    \splittopskip\z@ \vfuzz\maxdimen \vbadness\maxdimen
    \setbox\flushend@@varbox@a\vbox{\strut
        \vskip\z@
        \footnoterule
        \unskip\unkern\unpenalty
        \unskip\unkern\unpenalty
        }%
    \setbox\flushend@@tempbox@c\vsplit\flushend@@varbox@a to\ht\strutbox
    \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}}%
    }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\check@@footnoterule@@box}\marg{box}\marg{skip}\marg{box}
%    \begin{macrocode}
\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
             \xdef\main@box@height{\the\ht#3}%
             \xdef\main@box@skip{\the#2}%
          \fi
        \fi
      \fi
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\check@@baselineskip@@skip}\marg{dimension}\marg{dimension}\marg{var}
%    \begin{macrocode}
\def\check@@baselineskip@@skip#1#2#3{%
    \ifdim#1>\z@
        \ifdim#2>\z@
            \global#3=\the#1%
            \gdef\check@@baselineskip@@skip##1##2##3{}%
        \fi
    \fi
  }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\analyze@rightcolumn@box}\marg{box}
%    \begin{macrocode}
\def\analyze@rightcolumn@box#1{%
  \bgroup
      \xdef\top@@floatbox@ht{\z@}%
      \xdef\top@@floatbox@skip{\z@}%
      \xdef\top@@section@skip{\z@}%
      \splittopskip\z@ \vfuzz\maxdimen \vbadness\maxdimen
      \wlog@balance@debug{^^J(R)mainbox: \log@box@info{#1}}%
      \var@@temp@a3\p@
      \setbox\flushend@@varbox@a\vbox{\strut
                 \vskip\z@
                 \unvcopy#1%
                }%
      \splittopskip\z@ 
      \setbox\flushend@@tempbox@c\vsplit\flushend@@varbox@a to\ht\strutbox
      \flushend@@lastskip@a\ht\flushend@@varbox@a
      \loop
          \flushend@@lastskip@b\ht\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 -\ht\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 -\ht\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@
                          \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}{\last@outputdblcol}
%
% Columns balancing of the twocolumn mode page.
%
%    \begin{macrocode}
\def\last@outputdblcol{%
  \if@firstcolumn
      \global \@firstcolumnfalse
      \global \setbox\@leftcolumn \box\@outputbox
  \else
      \global \@firstcolumntrue
      \@tempdima\ht\@leftcolumn
      \splittopskip\topskip \splitmaxdepth\maxdepth
      \var@@temp@spread=\wd\@outputbox
      \if@auto@baselineskip
          %% Trying guess baselineskip value on column break
          \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@
            \splittopskip\z@
            \setbox\flushend@@varbox@a\vsplit\@leftcolumn to\main@box@height
          \else
            \setbox\flushend@@varbox@a\box\@leftcolumn
          \fi
          \ifdim\var@@temp@spread>\z@
              \setbox\@outputbox\vbox{\strut
                 \vskip\z@
                 \unvbox\@outputbox
                }%
              \splittopskip\z@ 
              \setbox\flushend@@tempbox@c\vsplit\@outputbox to\ht\strutbox
              \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>\topskip
                    \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 %% rightcolumn empty
              \setbox\@tempboxa\vbox{%
                  \unvbox\flushend@@varbox@a
                  \remove@lastbox@at@balancing
                  \the\atColsEnd
                  }%
          \fi
      \else
          %% Ignore baselineskip value on column break
          \ifdim\var@@temp@spread>\z@
              \setbox\@outputbox\vbox{\strut
                  \vskip\z@
                  \unvbox\@outputbox
                }%
              \splittopskip\z@ 
              \setbox\flushend@@tempbox@c\vsplit\@outputbox to\ht\strutbox
              \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
                  }%
          \else
              \setbox\@tempboxa\vbox{%
                  \unvbox\@leftcolumn
                  \remove@lastbox@at@balancing
                  \the\atColsEnd
                  }%
          \fi
      \fi
      \ifdim\main@box@skip>\z@
          \@tempdimb\ht\@tempboxa
          \advance\@tempdimb -\main@box@skip
          \advance\@tempdimb -\ht\@leftcolumn
          \@tempdimb .5\@tempdimb
          \splittopskip\topskip \splitmaxdepth\maxdepth
          \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
                  \vskip\main@box@skip
                  \unvcopy\@leftcolumn
                  }%
              \setbox\flushend@@varbox@c\vbox{\unvbox\flushend@@varbox@a}%
              \var@@temp@spread=\ht\flushend@@tempbox@c
              \advance\var@@temp@spread by-\ht\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
          \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
               }%
          \setbox\@outputbox\vbox to\@tempdima{%
               \vbox spread\var@@temp@spread{\unvbox\@tempboxa}%
              \vss
              }%
      \else
          \@tempdimb \ht\@tempboxa
          \ifdim\top@@floatbox@skip>\z@
              \advance\@tempdimb \top@@floatbox@skip
              \advance\@tempdimb \top@@floatbox@ht
          \fi
          \@tempdimb .5\@tempdimb
          \splittopskip\topskip \splitmaxdepth\maxdepth
          \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-\ht\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
          \@tempdimb\ht\flushend@@tempbox@c
          \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@a}%
          \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{%
                  \vbox spread\var@@temp@spread{%
                      \unvbox\@outputbox
                      \vskip\top@@floatbox@skip
                      \unvbox\@tempboxa
                      }%
                  \vss
                  }%
          \else
              \setbox\@outputbox\vbox to\@tempdima{%
                  \vbox spread\var@@temp@spread{\unvbox\@tempboxa}%
                  \vss
                  }%
          \fi
      \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}
%
% Adds default balancing of the last page at the end of document.
%
%    \begin{macrocode}
\usepackage{etoolbox}
\AtBeginDocument{%
    \global\let\saved@orig@@outputdblcol\@outputdblcol
    \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.
%
%    \begin{macrocode}
\def\flushcolsend{\global\let\@outputdblcol\last@outputdblcol}
\def\raggedcolsend{\global\let\@outputdblcol\saved@orig@@outputdblcol}
\def\flushend{\global\let\balanced@@outputdblcol\last@outputdblcol}
\def\raggedend{\global\let\balanced@@outputdblcol\saved@orig@@outputdblcol}
%    \end{macrocode}
%
%    \begin{macrocode}
\if@balance@debug
    \showcolsendrule
\fi
%    \end{macrocode}
%
% \iffalse
%</package>
% \fi
%
% \Finale
