% This is an experiment in balancing columns at the end of a
% \textsf{twocolumn} mode piece of document.
%
% Syntax is \cs{BalanceColumns}\oarg{epsilon}
%
% Balances what's left as contributions to the final page, subject to
% fudge-factor \emph{epsilon} in the final balancing: the default
% factor is \texttt{1.0}, and it's multiplied by \cs{baselineskip} and
% then added to the `target' height of the left column which is passed
% to the \cs{vsplit} primitive
%
% A spare temporary box, needed for \cs{FinalBalance}~\dots\ or could
% we use \cs{@holdpg}?
%    \begin{macrocode}
\newbox\@tempboxb
%    \end{macrocode}
%
%    \begin{macrocode}
\newcommand\BalanceColumns[1][0.5]{%
%    \end{macrocode}
%
% ensure we're in vertical mode
%    \begin{macrocode}
  \par
%    \end{macrocode}
%
% insert a zero penalty to ensure that the penultimate page is output
% properly
%    \begin{macrocode}
  \penalty\z@
%    \end{macrocode}
%
% define a dummy output routine for gathering up what's left at the
% end of the last page:
%    \begin{macrocode}
  \def\@dummy@balance@output{%
    \if@firstcolumn
      \ifx\@toplist\@empty
        \global\setbox\@tempboxa \vbox{\unvbox\@cclv}%
      \else
        % 1. (?) get rid of \topskip glue at the top of \@cclv
        % 2. insert the top float(s) and the appropriate separations
        % 3. adjust \@colroom and so on
        \global\setbox\@tempboxa \vbox{%
          \@tempswatrue
          \NRC@return@floats\@toplist\@toproom\@topnum\@empty
          \vspace\textfloatsep
          \unvbox\@cclv
        }%
        % 4. (?) warn about potential problems?
        % ... or ...
        % moan about the thing being there in the first place?
      \fi
    \else
%    \end{macrocode}
%
% we were in the right-hand column, so box 255 has (at this stage) got
% a \cs{topskip} glue in it (which we definitely don't want), so we
% stick in a penalty and \cs{vsplit} if off again, which loses the
% glue for us\dots
%    \begin{macrocode}
      \setbox\@cclv \vbox{%
        \penalty-\@M
        \unvbox\@cclv}%
%\showboxdepth2
%\showboxbreadth15
      \splittopskip\topskip
      \splitmaxdepth\maxdepth
      \setbox\@tempboxa \vsplit\@cclv to\z@
%\showbox\@tempboxa
%\showbox\@cclv
%    \end{macrocode}
%
% now reassemble the two columns into one, in \cs{@tempboxa}
%    \begin{macrocode}
      \ifx\@toplist\@empty
      % insert top floats in the right column here?
      % ... or ...
      \else
      % moan at their very existence?
        \NRC@warning{%
          Top float(s) (2nd column) lost in balancing}%
        \@tempswafalse
        \NRC@return@floats\@toplist\@toproom\@topnum\@empty
      \fi
      \global\setbox\@tempboxa \vbox{%
        \unvbox\@leftcolumn
        \unvbox\@cclv}%
    \fi
  }%
%    \end{macrocode}
%
% now check if there are outstanding floats, and moan if so (I'm not
% in the slightest particular sure whether the presence of floats can
% be dealt with at all without major restructuring, so we complain
% instead\dots).
%
% Note, we \emph{don't}, now, complain about deferred floats (they're
% the user's problem), but bottom floats have me stumped.  (In-text
% floats have already been committed by the time we get to this stage,
% and it's acceptable simply to return them:
%    \begin{macrocode}
  \ifx\@botlist\@empty\else
    \NRC@warning{%
      Bottom floats outstanding when balancing may be lost\MessageBreak
      What's more, balancing may be invalid}%
  \fi
  \xdef\@freelist{\@freelist\@midlist}
%    \end{macrocode}
%
% Acquire the output contributions so far, by exercising our little
% dummy output routine
%    \begin{macrocode}
  {%
%   \vfill
    \output{\@dummy@balance@output}%
    \eject
  }%
%    \end{macrocode}
%
% Establish the total height of the boxes we've thereby acquired
%    \begin{macrocode}
  {%
    \@tempdima .5\ht\@tempboxa
    \advance\@tempdima .5\dp\@tempboxa
    \splittopskip\topskip
    \splitmaxdepth\maxdepth
    \ClassInfo\NRC@clsname{%
      \string\FinalBalance: total height of page is
      \the\@tempdima\space--\MessageBreak
      \string\vsplit\space to half of that
      (plus #1\string\baselineskip)}%
    \advance\@tempdima #1\baselineskip
    \vbadness\@M
    \setbox\@tempboxb \vsplit\@tempboxa to\@tempdima
%    \end{macrocode}
%
% Log what we've done\dots
%    \begin{macrocode}
    \ClassInfo\NRC@clsname{%
      Column balance: left column height
                      \the\ht\@tempboxb+\the\dp\@tempboxb
      \MessageBreak
      right column height \the\ht\@tempboxa+\the\dp\@tempboxa}%
%\showboxdepth2
%\showboxbreadth15
%\showbox\@tempboxb
%\showbox\@tempboxa
%    \end{macrocode}
%
% Reassemble the two columns we now have into the `top of the page'
%    \begin{macrocode}
    \@tempdima \ht\@tempboxa
    \advance\@tempdima \dp\@tempboxa
    \dimen@    \ht\@tempboxb
    \advance\dimen@    \dp\@tempboxb
    \ifdim \dimen@ < \@tempdima
      \dimen@ \@tempdima
    \fi
    \global\setbox\@tempboxa \vbox {%
      \ifx\@dbltoplist\@empty
      \else
        \NRC@return@floats\@dbltoplist\@dbltoproom\@dbltopnum{dbl}%
        \vspace\dbltextfloatsep
      \fi
      \hb@xt@\textwidth {%
        \hb@xt@\columnwidth {%
          \vbox to\dimen@{%
            \unvbox\@tempboxb
            \vfill
          }%
          \hss
        }%
        \hfill
        \vrule \@width\columnseprule
        \hfill
        \hb@xt@\columnwidth {%
          \vbox to\dimen@{%
            \unvbox\@tempboxa
            \vfill
          }%
          \hss
        }%
      }%
    }%
%\showboxdepth5
%\showbox\@tempboxa
%\showthe\ht\@tempboxa
%\showthe\@colroom
%\showthe\@colht
%    \end{macrocode}
%
% Preserve the value of the \cs{columnwidth} for use in the
% \cs{*ColumnBar} commands
%    \begin{macrocode}
    \xdef\NRC@narrow@width{\the\columnwidth}
%    \end{macrocode}
%
% We now have the two columns, nestling happily together, in (global)
% \cs{@tempboxa}, so we simulate a \cs{onecolumn} command, so that we
% can proceed as if we've now given up on this two column game\dots
%    \begin{macrocode}
    \global\columnwidth\textwidth
    \global\hsize\columnwidth
    \global\linewidth\columnwidth
    \global\@twocolumnfalse
    \col@number \@ne
%    \end{macrocode}
%
% Finally, dump the contents of the \@tempboxa we prepared earlier
% into this new one-columned environment
%    \begin{macrocode}
    \unvbox\@tempboxa
  }%
}
%    \end{macrocode}
%
% \begin{macro}{\NRC@return@floats}
% Syntax: \cs{NRC@return@floats}\marg{float list}\marg{float room}^^A
%                               \marg{float count}\marg{double ind}
%
% `Return' a list of floats that existed for the present page, and
% recover the space they would have occupied in the present column;
% note that since this operation redefines the float list \cs{@elt}
% macro, it operates inside a group, and all its external actions need
% to be done \cs{global}.  \cs{if@tempswa}, the body(ies) of the
% float(s) is(are) inserted; otherwise they're simply lost.  It is the
% responsibility of the calling routine to add \cs{textfloatsep} (or
% whatever), where necessary, to ensure the floats are properly
% positioned with respect to the rest of the matter in the column.
%
% The \meta{double ind} parameter is either \verb'dbl' (if we're
% returning a double-top list) or empty (it's used to determine which
% separation to use in calculations (and in the case of returning
% multiple floats, even when making inter-float skips)
%    \begin{macrocode}
\newcommand{\NRC@return@floats}[4]{{%
%    \end{macrocode}
%
% \cs{@elt} macro for returning the first float in the list.  Note
% that it doesn't insert any separation of its own\dots
%    \begin{macrocode}
    \def\@elt##1{%
      \global\advance#3\@ne
      \global\advance\@colnum\@ne
      \@tempdima\ht##1%
      \advance\@tempdima\dp##1%
      \advance\@tempdima\csname#4textfloatsep\endcsname
      \csname NRC@advance@#4colspace\endcsname{#2}%
      \if@tempswa\vbox{\unvbox##1}\fi
%    \end{macrocode}
%
% now the \cs{@elt} macro for returning subsequent floats in the
% list.  Since we know that at least one float has already been added,
% we insert \cs{\#4floatsep} before inserting the float's actual body.
%    \begin{macrocode}
      \def\@elt####1{%
        \global\advance#3\@ne
        \global\advance\@colnum\@ne
        \@tempdima\ht####1%
        \advance\@tempdima\dp####1%
        \advance\@tempdima\csname#4floatsep\endcsname
        \csname NRC@advance@#4colspace\endcsname{#2}%
        \if@tempswa
          \vskip\csname#4floatsep\endcsname%
          \vbox{\unvbox####1}%
        \fi
      }%
    }%
%    \end{macrocode}
%
% Now we simply execute the list, and it will self-insert.
%    \begin{macrocode}
    #1%
  }%
%    \end{macrocode}
%
% Having closed the group in which \cs{@elt} was defined, we can
% safely do the following to return the list to the free list, since
% \cs{@elt} \emph{should} always be \cs{let} to \cs{relax}
%    \begin{macrocode}
  \let\@elt\relax
  \xdef\@freelist{\@freelist#1}%
  \xdef#1{}%
  \global\vsize\@colroom
}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\NRC@advance@colspace}
% \begin{macro}{\NRC@advance@dblcolspace}
%
% Add \cs{@tempdima} to the space available in the column(s).  The
% version for double-column floats also restores space to \cs{@colht}.
%    \begin{macrocode}
\newcommand{\NRC@advance@colspace}[1]{%
  \global\advance\@colroom\@tempdima
  \global\advance#1\@tempdima
}
\newcommand{\NRC@advance@dblcolspace}[1]{%
  \global\advance\@colroom\@tempdima
  \global\advance#1\@tempdima
  \global\advance\@colht\@tempdima
%    \end{macrocode}
%
% \cs{@topnum} gets advanced in the \cs{@elt} macros and shouldn't be
% in this case
%    \begin{macrocode}
  \global\advance\@topnum\m@ne
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% First stab at restarting double columns\dots
%
% \begin{macro}{\RestartDouble}
%
%    \begin{macrocode}
\newcommand{\RestartDouble}{%
  \penalty\z@
  {%
    \output{\NRC@gather@top}
    \vfill
    \eject
  }%
  \twocolumn[\unvbox\@tempboxb]%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\NRC@gather@top}
%
% Another dummy output routine, whose sole task is to salt away the
% contents of a (nominally) single-column output-page-so-far
%    \begin{macrocode}
\newcommand{\NRC@gather@top}{%
  \global\setbox\@tempboxb\vbox{\unvbox\@cclv}%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\LeftColumnBar}
% \begin{macro}{\RightColumnBar}
%
% \cs{LeftColumnBar} and \cs{RightColumnBar} place bars across
% columns, as are required to separate the two-column portion of the
% text from interposed full-width material.  They are to be used
% \emph{within} the full-width material, in vertical mode
%    \begin{macrocode}
\newcommand{\LeftColumnBar}{%
  \addvspace{0.75\baselineskip}%
  \hbox{\rule{\NRC@narrow@width}{\p@}}%
  \addvspace{0.75\baselineskip}%
}
\newcommand{\RightColumnBar}{%
  \par
  \addvspace{0.75\baselineskip}%
  \hb@xt@\textwidth{\hfill\rule{\NRC@narrow@width}{\p@}}%
  \addvspace{0.75\baselineskip}%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{environment}{WideText}
% \begin{macro}{\NRC@widetext@i}
% \begin{macro}{\NRC@widetext@ii}
%
% Syntax: \verb'\begin{WideText}'\oarg{left indent}\oarg{right indent}
%
% The \verb'WideText' environment allows variation of the text margins
% for a short period.  It will typically be used to narrow the right
% margin of full-width text in the two-column style, hence the default
% values for the argument of \emph{left}:~\verb'0pc',
% \emph{right}:~\verb'3pc'.
%
%    \begin{macrocode}
\newenvironment{WideText}{%
  \@testopt{\NRC@widetext@i}{\z@}%
}{%
  \endlist
}
\def\NRC@widetext@i[#1]{%
  \@testopt{\NRC@widetext@ii{#1}}{3pc}%
}
\def\NRC@widetext@ii#1[#2]{%
  \list{}{%
    \topsep\z@
    \leftmargin#1\relax
    \rightmargin#2\relax
    \listparindent\parindent
    \parsep\parskip
  }%
  \item[]%
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{environment}
%
% \noindent At the going down of the sun, and in the morning, we will
% remember them.
%
% \noindent 11:02 {\small GMT\@}, 8\textsuperscript{th} November
% 1998 (Remembrance Sunday).
