%\iffalse
% flowfram.dtx generated using makedtx version 0.94b (c) Nicola Talbot
% Command line args:
%   -src "flowfram.sty\Z=>flowfram.sty"
%   -doc "docstub.tex"
%   -author "Nicola Talbot"
%   -dir "source"
%   flowfram
% Created on 2010/1/23 11:35
%\fi
%\iffalse
%<*package>
%% \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         \~}
%</package>
%\fi
% \iffalse
% Doc-Source file to use with LaTeX2e
% Copyright (C) 2010 Nicola Talbot, all rights reserved.
% \fi
% \iffalse
%<*driver>
\documentclass{ltxdoc}

\CheckSum{9520}
\PageIndex

\usepackage{url}
\usepackage[colorlinks,hyperindex=false,
pdfauthor={Nicola L C Talbot},
pdftitle={Documented Source Code for flowfram.sty}]{hyperref}
\usepackage[style=altlist,toc,nonumberlist]{glossaries}

\newglossary[slg]{secondary}{sgi}{sgo}{Glossary}
\renewcommand{\acronymtype}{secondary}

\MakeShortVerb"
\DeleteShortVerb|

\newcommand{\sty}[1]{\textsf{#1}}
\newcommand{\env}[1]{\textsf{#1}}

\renewcommand{\usage}[1]{\textit{\hyperpage{#1}}}
\renewcommand{\main}[1]{\hyperpage{#1}}
\newcommand{\see}[2]{\emph{see} #1}
\makeatletter
\def\index@prologue{\section*{Index}
\addcontentsline{toc}{section}{Index}}
\makeatother


\newglossaryentry{typeblock}{name=typeblock,description={The 
area of the page where the main body of the text goes.
The width and height of this area are given by \cs{textwidth}
and \cs{textheight}},type=secondary}

\newglossaryentry{flow}{name=flow frame,description={The frames in 
a document such that the contents of the \env{document}
environment flow from one frame to the next in the order 
that they were defined. There must be at least one flow frame on
every page},type=secondary}

\newglossaryentry{static}{name=static frame,description={Frames
in which text is fixed in place. The contents are fixed until
explicitly changed},type=secondary}

\newglossaryentry{dynamic}{name=dynamic frame,description={Frames
in which text is fixed in place, but the contents are re-typeset
after each page},type=secondary}

\newglossaryentry{frame}{name=frame,description={A rectangular
area of the page in which text can be placed (not to be
confused with a frame making command). There are three types:
flow, static and dynamic},type=secondary}

\newglossaryentry{fcmd}{name=frame making command,description={A
\LaTeX\ command which places some kind of border around its
argument. For example: \cs{fbox}},type=secondary}

\newglossaryentry{pglist}{name=page list,description={A list of
pages. This can either be a single keyword: \texttt{all},
\texttt{odd}, \texttt{even} or \texttt{none}, or it can
be a comma-separated list of individual page numbers or
page ranges. For example: \texttt{\textless3,5,7-11,\textgreater15}
indicates pages 1,2,5,7,8,9,10,11 and all pages after page 15.
Note that these numbers refer to the actual value of the
page counter, not the absolute physical page number},
type=secondary}

\newglossaryentry{pgrange}{name=page range,description={Page
ranges can be closed, e.g.\ \texttt{5-10}, or open, e.g.
\texttt{\textless7} or \texttt{\textgreater9}},
type=secondary}

\newglossaryentry{bbox}{name=bounding box,plural=bounding boxes,
description={The smallest
possible rectangle that completely encompasses the object},
type=secondary}

\newacronym[name={identification number (IDN)},
description={A unique
number assigned to each frame, which you can use to identify
the frame when modifying its appearance. Example: if you
have defined 3 flow frames, 2 static frames and 1 dynamic
frame, the flow frames will have IDNs 1, 2 and 3, the static
frames will have IDNs 1 and 2, and the dynamic frame will
have IDN 1}]{idn}{IDN}{identification number}

\newacronym[name={identification label (IDL)},
description={A unique
label which can be assigned to a frame, enabling you to
refer to the frame by label instead of by its 
IDN}]{idl}{IDL}{identification label}

\makeglossaries

\begin{document}
\DocInput{flowfram.dtx}
\end{document}
%</driver>
%\fi
%\title{Documented Source Code for flowfram.sty v1.13}
%\author{Nicola L. C. Talbot}
%\date{23rd January 2010}
%\maketitle
%
%This is the documented source code for the flowfram package.
%For a user manual, see \url{ffuserguide.pdf}.
%
%\tableofcontents
%
%\printglossary[type=secondary]
%
%\StopEventually{\PrintIndex}
%
%
%\section{The Code}
%\iffalse
%    \begin{macrocode}
%<*flowfram.sty>
%    \end{macrocode}
%\fi
% \subsection{Package Initialisation}
% Declare package, and identify it as a \LaTeXe\ package.
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{flowfram}[2010/01/23 v1.13]
%    \end{macrocode}
% Load packages needed by this package
%    \begin{macrocode}
\RequirePackage{ifthen}
\RequirePackage{keyval}
\RequirePackage{graphics}
\RequirePackage{afterpage}
\@ifundefined{@ldc@l@r}{\RequirePackage{color}}{}
%    \end{macrocode}
% The colour of the \gls{bbox} borders when the draft 
% option is specified is given by the commands:
%    \begin{macrocode}
\newcommand{\setffdraftcolor}{\color[gray]{0.8}}
\newcommand{\setffdrafttypeblockcolor}{\color[gray]{0.9}}
%    \end{macrocode}
%\begin{macro}{\fflabelsep}
% In draft mode, each \gls{bbox} (apart from the one indicating
% the \gls{typeblock}), has a label positioned to the right of the
% box, at a distance of "\fflabelsep" from the right hand
% border.\DescribeMacro{\fflabelsep}
%    \begin{macrocode}
\newlength\fflabelsep
\fflabelsep=1pt
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\fflabelfont}
% The appearance of the label is set by the declaration:
%    \begin{macrocode}
\newcommand*{\fflabelfont}{\small\sffamily}
%    \end{macrocode}
%\end{macro}
% The command "\@ffdraft" is used to switch to draft mode.
% Allow user the option to show particular types of bounding
% boxes.
%    \begin{macrocode}
\newif\ifshowtypeblock
\newif\ifshowmargins
\newif\ifshowframebbox
%    \end{macrocode}
%\begin{macro}{\@ffdraft}
% Set all draft settings.
%    \begin{macrocode}
\newcommand*{\@ffdraft}{%
\showtypeblocktrue
\showmarginstrue
\showframebboxtrue
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ffnodraft}
% Unset all draft settings.
%    \begin{macrocode}
\newcommand*{\@ffnodraft}{%
\showtypeblockfalse
\showmarginsfalse
\showframebboxfalse
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@fr@meifdraft}
% Draw \gls{bbox}.
%    \begin{macrocode}
\newcommand*{\@fr@meifdraft}[3][\setffdraftcolor]{%
\def\ff@backcol{{none}}%
\@ifundefined{color}{\frame{#2}}{#1\frame{#2}}%
\ifthenelse{\equal{#3}{}}{}{%
\makebox[0pt][l]{\hskip\fflabelsep\fflabelfont{[#3]}}}}%
%    \end{macrocode}
%\end{macro}
% Colour setting commands, do nothing by default:
%    \begin{macrocode}
\newcommand*{\@s@tffcol}{}
\newcommand*{\@s@tfftextcol}{}
%    \end{macrocode}
%\begin{macro}{\@ffbackground}
% Deal with \gls{frame} background colour. Note that the background colour only
% extends to the limit of the \gls{frame}['s] \gls{bbox}. If you want the background
% colour to be flush with the \glspl{frame} border, you will have to create your own
% customised border.
%    \begin{macrocode}
\newcommand*{\@ffbackground}[1]{#1}
%    \end{macrocode}
%\end{macro}
% Now declare the options.  If draft, switch to draft definitions.
%    \begin{macrocode}
\DeclareOption{draft}{\@ffdraft}
%    \end{macrocode}
% If not draft, reset commands so that no \glspl{bbox}
% are drawn.
%    \begin{macrocode}
\DeclareOption{final}{\@ffnodraft}
%    \end{macrocode}
%\begin{macro}{\if@ttb@rotate}
% Allow provision to prevent rotation in the thumbtabs.
% If no rotation, thumbtab text will be stacked vertically.
% This will also affect whether or not to rotate \glspl{frame}.
%    \begin{macrocode}
\newif\if@ttb@rotate
\@ttb@rotatetrue
\DeclareOption{rotate}{\@ttb@rotatetrue}
\DeclareOption{norotate}{\@ttb@rotatefalse}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\rotateframe}
% Define command that will only rotate box if rotate option
% set.
%    \begin{macrocode}
\newcommand{\rotateframe}[2]{\if@ttb@rotate
\rotatebox{#1}{#2}%
\else
#2\relax
\fi}
%    \end{macrocode}
%\end{macro}
% Should the thumbtabs include number, title, both or
% neither?
%    \begin{macrocode}
\newif\if@ttb@num
\newif\if@ttb@title
\@ttb@numfalse
\@ttb@titletrue
\DeclareOption{ttbtitle}{\@ttb@titletrue}
\DeclareOption{ttbnotitle}{\@ttb@titlefalse}
\DeclareOption{ttbnum}{\@ttb@numtrue}
\DeclareOption{ttbnonum}{\@ttb@numfalse}
%    \end{macrocode}
% If color option specified, set up the default colours
% for the borders and text for all \gls{frame} types. Note that
% the colour name has to be grouped within the definition
% of "\flowframecol" and "\flowframetextcol". This
% was done so that you could do, for example, 
% "\renewcommand{\flowframecol}{[rgb]{1,1,0}}" so that
% you can specify the colour model as well.
% The commands "\@s@tffcol" and "\@s@tfftextcol"
% switch to the border and text colour, respectively. They
% both assume that "\ff@col" has been set to the 
% relevant colour before use.
%    \begin{macrocode}
\DeclareOption{color}{%
\def\flowframecol{{black}}\def\flowframetextcol{{black}}
\renewcommand*\@s@tffcol{\ifthenelse{\equal{\ff@col}{}}{}{%
\expandafter\color\ff@col}}
\renewcommand*\@s@tfftextcol{\ifthenelse{\equal{\ff@txtcol}{}}{}{%
\expandafter\color\ff@txtcol}}
\renewcommand*{\@ffbackground}[1]{%
\ifthenelse{\equal{\ff@backcol}{{none}}}{%
#1}{{\fboxsep=0pt\expandafter\colorbox\ff@backcol{#1}}}}
}
%    \end{macrocode}
% If nocolor is specified, ensure that the colour changing
% commands do nothing.
%    \begin{macrocode}
\DeclareOption{nocolor}{%
\def\flowframetextcol{}%
\def\flowframecol{}%
\renewcommand{\@s@tffcol}{}\renewcommand{\@s@tfftextcol}{}
\renewcommand{\@ffbackground}[1]{#1}
}
%    \end{macrocode}
%\begin{macro}{\iflefttorightcolumns}
% Determine whether to define the Ncolumn style frames from left
% to right or from right to left.
%\changes{1.12}{2009/11/25}{new}
%    \begin{macrocode}
\newif\iflefttorightcolumns
\lefttorightcolumnstrue
%    \end{macrocode}
%\end{macro}
% Define options that set the direction:
%    \begin{macrocode}
\DeclareOption{LR}{\lefttorightcolumnstrue}
\DeclareOption{RL}{\lefttorightcolumnsfalse}
%    \end{macrocode}
% Check to see if the document class has the draft option
% set. The easiest way to do this is to check the length
% of "\overfullrule" (the marker that indicates overfull
% hboxes).
%    \begin{macrocode} 
\ifdim\overfullrule=0pt
\ExecuteOptions{final}
\else
\ExecuteOptions{draft}
\fi
%    \end{macrocode}
% If the "\normalcolor" command is something other than 
% "\relax", then implement
% the color option as the default, otherwise implement the
% nocolor option as the default.
%    \begin{macrocode}
\ifx\normalcolor\relax
\ExecuteOptions{nocolor}
\else
\ExecuteOptions{color}
\fi
%    \end{macrocode}
% Now the defaults have all been set, the package options
% specified by the user can be processed:
%    \begin{macrocode}
\ProcessOptions
%    \end{macrocode}
% If color option has been specified, but no color
% package has been loaded yet, load color.sty
%    \begin{macrocode}
\ifx\normalcolor\relax
\ifthenelse{\equal{\flowframetextcol}{}}{}{%
\RequirePackage{color}}
\fi
%    \end{macrocode}
% User may want a non standard style for the first page of 
% each chapter, so modify chapter commands to take this into 
% account.\DescribeMacro{\chapterfirstpagestyle}
%    \begin{macrocode}
\@ifundefined{chapter}{}{%
\newcommand*{\chapterfirstpagestyle}{plain}
\let\@ff@OLD@chapter\@chapter
\let\@ff@OLD@schapter\@schapter
\renewcommand{\@chapter}{%
\thispagestyle{\chapterfirstpagestyle}\@ff@OLD@chapter}
\renewcommand{\@schapter}{%
\thispagestyle{\chapterfirstpagestyle}\@ff@OLD@schapter}
}
%    \end{macrocode}
% Now get on with the package.  First we need to set up 
% a register to store the number of \glspl{flow} that have been defined:
%    \begin{macrocode}
\newcounter{maxflow}
\c@maxflow=0\relax
%    \end{macrocode}
% Next define a counter to keep track of the \gls{idn} of the current
% \gls{flow}.
%    \begin{macrocode}
\newcounter{thisframe}
\c@thisframe=0\relax
\@ifpackageloaded{hyperref}{%
\def\theHthisframe{\thepage.\arabic{thisframe}}}{}
%    \end{macrocode}
%\begin{macro}{\labelflowidn}
%\changes{1.11}{2008/06/27}{new}
% Define a command to label the current \gls{flow} so that its
% \gls{idn} can be referenced:
%    \begin{macrocode}
\newcommand*{\labelflowidn}[1]{%
{\def\@currentlabel{\thethisframe}\label{#1}}}
%    \end{macrocode}
%\end{macro}
% Define a counter to store the current frame index for the current
% page. This will be the same as the \gls{idn} if all \glspl{flow}
% are displayed on the current page, but may be different to the
% \gls{idn} if some \glspl{flow} are not displayed.
%\changes{1.11}{2008/06/27}{displayedframe counter added}
%    \begin{macrocode}
\newcounter{displayedframe}
\c@displayedframe=0
\@ifpackageloaded{hyperref}{%
\def\theHdisplayedframe{\thepage.\arabic{displayedframe}}}{}
%    \end{macrocode}
%\begin{macro}{\labelflow}
%\changes{1.11}{2008/06/27}{new}
% Define a command to label the current \gls{flow} so that its
% displayed index can be referenced:
%    \begin{macrocode}
\newcommand*{\labelflow}[1]{%
{\def\@currentlabel{\thedisplayedframe}\label{#1}}}
%    \end{macrocode}
%\end{macro}
% Define a counter to store the total number of \glspl{static}:
%    \begin{macrocode}
\newcounter{maxstatic}
\c@maxstatic=0\relax
%    \end{macrocode}
% Define a counter to store the total number of \glspl{dynamic}:
%    \begin{macrocode}
\newcounter{maxdynamic}
\c@maxdynamic=0\relax
%    \end{macrocode}
% Define some temporary variables
%    \begin{macrocode}
\newcount\@colN
\newcount\@ff@tmpN
\newcount\ff@id
\newlength\@ff@offset
\newlength\@ff@tmp@x
\newlength\@ff@tmp@x@even
\newlength\@ff@tmp@y
%    \end{macrocode}
%\begin{macro}{\sdfparindent}
% Define a length to govern paragraph indentation within 
% static and dynamic frames.
% This is 0pt by default. 
%    \begin{macrocode}
\newlength\sdfparindent
%    \end{macrocode}
%\end{macro}
%
% \subsection{Flow Frames}
%\begin{macro}{\flowframesep}
% Set up default lengths. The gap between the text and the
% border is given by:
%    \begin{macrocode}
\newlength\flowframesep
\flowframesep=\fboxsep
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframerule}
% The width of the frame is given by:
%    \begin{macrocode}
\newlength\flowframerule
\flowframerule=\fboxrule
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframeshowlayout}
% Define command to show page layout.  This finishes the current
% page, temporarily sets draft mode, and prints an empty page.
% Only the \glspl{frame} for that page will be shown.
%\DescribeMacro{\flowframeshowlayout}
%    \begin{macrocode}
\newcommand*{\flowframeshowlayout}{%
\finishthispage
{\@ffdraft\mbox{}\finishthispage\clearpage}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\framebreak}
% If the \glspl{flow} are not all of the same width, the change
% in "\hsize" will not come into effect until the end
% of the paragraph. Provide a command to simulate a paragraph
% break, without making it look as though there is a paragraph.
% Provides an optional argument that is passed to 
% "\pagebreak".  Make sure it is grouped to localise
% the change in "\parfillskip" and "\parskip".
%    \begin{macrocode}
\newif\ifusedframebreak
\newcommand{\framebreak}[1][4]{%
\usedframebreaktrue
{\parfillskip=0pt\pagebreak[#1]\parskip=0pt\par\noindent}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\finishthispage}
% The commands "\newpage" and
% "\pagebreak" can be used to move on to the next
% \gls{flow}, but to finish the entire page, use 
% "\finishthispage".
%    \begin{macrocode}
\newcommand{\finishthispage}{%
\@colN=\c@thisframe
\newpage
\whiledo{\@colN<\c@maxflow}{\advance\@colN by 1\relax
\@ff@chckifthispg{\c@page}{\@colN}%
\if@notthiscol\else
\mbox{}\newpage%
\fi
}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\cleardoublepage}
% Modify the definition of "\cleardoublepage". This may
% or may not be defined so use "\def".
%    \begin{macrocode}
\def\cleardoublepage{\finishthispage
\if@twoside
\ifodd\c@page
\else
\hbox{}\finishthispage
\fi
\fi}
%    \end{macrocode}
%\end{macro}
% Disable "@twocolumn" flag, as it makes no sense.
%    \begin{macrocode}
\@twocolumnfalse
%    \end{macrocode}
% Disable "@mparswitch" flag, as each \gls{flow} has
% its own predefined margin setting.
%    \begin{macrocode}
\@mparswitchfalse
%    \end{macrocode}
%\begin{macro}{\globalreversemargin}
% The margins get switched during the output routine, so
% need the effect to be global.
%    \begin{macrocode}
\newcommand{\globalreversemargin}{%
\global\@mparbottom\z@\global\@reversemargintrue}
\newcommand{\globalnormalmargin}{%
\global\@mparbottom\z@\global\@reversemarginfalse}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@getmarginpos}
% Determine whether the margin should be on the right
% or left. This depends on the setting, which can either
% be "right" or "left" (self explanatory) or "inner" (on the 
% spine side, so left for odd pages and right for even
% pages) or "outer" (on the outside of the page, so right
% for odd pages and left for even pages.) When "\@getmarginpos"
% is finished, the setting is stored in "\ff@margin".
%    \begin{macrocode}
\newcommand{\@getmarginpos}[1]{%
\ifthenelse{\equal{#1}{inner}}{%
\if@twoside
\ifodd\c@page\def\ff@margin{left}\else\def\ff@margin{right}\fi
\else
\def\ff@margin{left}%
\fi
}{%
\ifthenelse{\equal{#1}{outer}}{%
\if@twoside
\ifodd\c@page\def\ff@margin{right}\else\def\ff@margin{left}\fi
\else
\def\ff@margin{right}%
\fi
}{%
\def\ff@margin{#1}}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setmargin}
% Set the margin for current \gls{flow}.
%    \begin{macrocode}
\newcommand{\setmargin}{%
\@getmarginpos{%
\csname @ff@margin@\romannumeral\c@thisframe\endcsname}%
\ifthenelse{\equal{\ff@margin}{left}}%
{\globalreversemargin}{\globalnormalmargin}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\newflowframe}
% Create a new \gls{flow}. Syntax:\newline
% \cs{newflowframe}\oarg{pages}\marg{width}\marg{height}\marg{x}\marg{y}\oarg{label}
%
% First increment "\c@maxflow", and define boolean
% to indicate whether or not the \gls{flow} has a border,
% Then check to see whether or not the starred version is
% begin used. All the settings must be global: the
% output routine will create a new \gls{flow}, if there are no
% more defined, and since changes made in the output routine
% are localised, the new \gls{frame} will be lost unless it is 
% globally defined. Flow frames should only be set up in the
% preamble, but if there are not enough \glspl{frame} to fit all
% the document text, the output routine will create a new \gls{flow}.
% So, define "\newflowframe" so that it calls 
% "\@n@wflowframe"
%    \begin{macrocode}
\newcommand{\newflowframe}{\@n@wflowframe}
%    \end{macrocode}
%\end{macro}
% Set the external command for use only in the preamble, an
% make the output routine use the internal command
%    \begin{macrocode}
\@onlypreamble{\newflowframe}
%    \end{macrocode}
%\begin{macro}{\@n@wflowframe}
%    \begin{macrocode}
\newcommand{\@n@wflowframe}{%
\global\advance\c@maxflow by 1\relax
\expandafter\global\expandafter
\newif\csname ifcolumnframe\romannumeral\c@maxflow\endcsname
\@ifstar\@snewflowframe\@newflowframe
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@snewflowframe}
% Starred version sets boolean flag to indicate a border
%    \begin{macrocode}
\newcommand{\@snewflowframe}{%
\expandafter\global\expandafter
\let\csname ifcolumnframe\romannumeral\c@maxflow\endcsname\iftrue
\@@newflowframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@newflowframe}
% The unstarred version unsets boolean flag to indicate
% no border.
%    \begin{macrocode}
\newcommand{\@newflowframe}{%
\expandafter\global\expandafter
\let\csname ifcolumnframe\romannumeral\c@maxflow\endcsname\iffalse
\@@newflowframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@newflowframe}
% Now get on with initialising the \gls{flow}. By default, it
% will apply the \gls{flow} to all pages, the optional argument
% can override this.
%    \begin{macrocode}
\newcommand{\@@newflowframe}[5][all]{%
\expandafter\global\expandafter
\newbox\csname column\romannumeral\c@maxflow\endcsname
\expandafter\global\expandafter
\newlength\csname colwidth\romannumeral\c@maxflow\endcsname
\expandafter\global\expandafter
\newlength\csname colheight\romannumeral\c@maxflow\endcsname
\expandafter\global\expandafter
\newlength\csname col@\romannumeral\c@maxflow @posx\endcsname
\expandafter\global\expandafter
\newlength\csname col@\romannumeral\c@maxflow @posy\endcsname
\expandafter\global\expandafter
\setlength\csname colwidth\romannumeral\c@maxflow\endcsname{#2}
\expandafter\global\expandafter
\setlength\csname colheight\romannumeral\c@maxflow\endcsname{#3}
\expandafter\global\expandafter
\setlength\csname col@\romannumeral\c@maxflow @posx\endcsname{#4}
\expandafter\global\expandafter
\setlength\csname col@\romannumeral\c@maxflow @posy\endcsname{#5}
\expandafter\global\expandafter
\newlength\csname col@\romannumeral\c@maxflow @evenx\endcsname
\expandafter\global\expandafter
\newlength\csname col@\romannumeral\c@maxflow @eveny\endcsname
\expandafter\global\expandafter
\setlength\csname col@\romannumeral\c@maxflow @evenx\endcsname{#4}
\expandafter\global\expandafter
\setlength\csname col@\romannumeral\c@maxflow @eveny\endcsname{#5}
\expandafter
\gdef\csname @ff@frametype@\romannumeral\c@maxflow\endcsname{fbox}%
\expandafter
\gdef\csname @ff@col@\romannumeral\c@maxflow\endcsname{\flowframecol}
\expandafter
\gdef\csname @ff@txtcol@\romannumeral\c@maxflow\endcsname{%
\flowframetextcol}
\expandafter
\gdef\csname @ff@backcol@\romannumeral\c@maxflow\endcsname{{none}}
\expandafter
\gdef\csname @ff@pages@\romannumeral\c@maxflow\endcsname{#1}
\expandafter
\gdef\csname @ff@offset@\romannumeral\c@maxflow\endcsname{compute}
\expandafter
\gdef\csname @ff@angle@\romannumeral\c@maxflow\endcsname{0}%
\expandafter
\gdef\csname @ff@margin@\romannumeral\c@maxflow\endcsname{right}
\ifnum\c@thisframe=0\relax
\ifthenelse{\equal{#1}{all}\TE@or\equal{#1}{odd}}{%
\c@thisframe=\c@maxflow
\global\setlength{\hsize}{#2}%
\global\usedframebreaktrue
}{\ifthenelse{\equal{#1}{even}\TE@or\equal{#1}{none}}{}{%
\def\ff@pages{#1}%
\@for\@ff@pp:=\ff@pages\do{%
\def\@ff@numstart{0}\def\@ff@numend{0}%
\@ff@getrange{\@ff@pp}%
\ifnum\@ff@numstart=0\def\@ff@numstart{1}\fi
\ifnum\@ff@numstart=1\relax
\c@thisframe=\c@maxflow
\global\setlength{\hsize}{#2}%
\global\usedframebreaktrue
\fi
}}}%
\fi
\@ifnextchar[{\@s@tflowframeid{\c@maxflow}}{%
\@s@tflowframeid{\c@maxflow}[\number\c@maxflow]}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tflowframeid}
% If square brackets occur after "\newflowframe", take
% the contents to be the label, otherwise the label will be
% the \gls{flow} number.
%    \begin{macrocode}
\def\@s@tflowframeid#1[#2]{%
\edef\ff@label{#2}%
\@ff@checkuniqueidl{#1}{\ff@label}%
\expandafter
\xdef\csname @col@id@\romannumeral#1\endcsname{\ff@label}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checkuniqueidl}
% Check \gls{idl} "#2" for \gls{flow} "#1" is unique
%    \begin{macrocode}
\newcommand*{\@ff@checkuniqueidl}[2]{%
{\@colN=0\relax
\whiledo{\@colN<\c@maxflow}{%
\advance\@colN by 1\relax
\ifnum\@colN=#1\relax
\else
\ifthenelse{\equal{#2}{%
\csname @col@id@\romannumeral\@colN\endcsname}}{%
\PackageError{flowfram}{Flow frame IDL '#2' already defined}{%
You can't assign this label, as it is already defined
for flow frame \number\@colN}}{}%
\fi
}}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getflowlabel}
%\changes{1.11}{2008/06/27}{new}
%\cs{getflowlabel}\marg{idn}
% Gets the \gls{idl} for the \gls{flow} identified by its
% \gls{idn}.
%    \begin{macrocode}
\newcommand*{\getflowlabel}[1]{%
\csname @col@id@\romannumeral#1\endcsname}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getflowid}
%\changes{1.11}{2008/06/27}{new}
%\cs{getflowid}\marg{cmd}\marg{idl}
% Gets the \gls{idn} for the \gls{flow} identified by its
% \gls{idl} and stores in \meta{cmd} which must be a control
% sequence.
%    \begin{macrocode}
\newcommand*{\getflowid}[2]{%
\@flowframeid{#2}\edef#1{\number\ff@id}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowframeid}
% Work out the \gls{flow} \gls{idn} from the label. This
% iterates through the \glspl{flow}, so if you have a lot of
% them it is quicker to identifiy them by their \gls{idn}
% rather than their \gls{idl}.
% The \gls{idn} stored in "\ff@id".
%    \begin{macrocode}
\newcommand*{\@flowframeid}[1]{\@colN=0\relax
\ff@id=0\relax
\whiledo{\@colN<\c@maxflow}{\advance\@colN by 1\relax
\ifthenelse{%
\equal{#1}{\csname @col@id@\romannumeral\@colN\endcsname}}{%
\ff@id=\@colN\relax
% break out of loop
\@colN=\c@maxflow}{}}%
\ifnum\ff@id=0\relax
\PackageError{flowfram}{Can't find flow frame id '#1'}{}\fi}
%    \end{macrocode}
%\end{macro}
% Set up the keys for use with "\setflowframe", 
% "\setstaticframe" and "\setdynamicframe".
%
% Frame width is stored in "\ff@width".
%    \begin{macrocode}
\define@key{flowframe}{width}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'width' key}{}}{}%
\def\ff@width{#1}}
%    \end{macrocode}
% Frame height is stored in "\ff@height".
%    \begin{macrocode}
\define@key{flowframe}{height}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'height' key}{}}{}%
\def\ff@height{#1}}
%    \end{macrocode}
% Frame $x$ co-ordinate (odd and even pages) is stored
% in "\ff@x".
%    \begin{macrocode}
\define@key{flowframe}{x}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'x' key}{}}{}%
\def\ff@x{#1}}
%    \end{macrocode}
% Frame $y$ co-ordinate (odd and even pages) is stored
% in "\ff@y".
%    \begin{macrocode}
\define@key{flowframe}{y}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'y' key}{}}{}%
\def\ff@y{#1}}
%    \end{macrocode}
% Frame $x$ co-ordinate (even pages only) is stored
% in "\ff@evenx".
%    \begin{macrocode}
\define@key{flowframe}{evenx}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'evenx' key}{}}{}%
\def\ff@evenx{#1}}
%    \end{macrocode}
% Frame $y$ co-ordinate (even pages only) is stored in
% "\ff@eveny".
%    \begin{macrocode}
\define@key{flowframe}{eveny}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'eveny' key}{}}{}%
\def\ff@eveny{#1}}
%    \end{macrocode}
% Frame $x$ co-ordinate (odd pages only if twoside implemented)
% is stored in "\ff@oddx".
%    \begin{macrocode}
\define@key{flowframe}{oddx}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'oddx' key}{}}{}%
\def\ff@oddx{#1}}
%    \end{macrocode}
% Frame $y$ co-ordinate (odd pages only if twoside implemented)
% is stored in "\ff@oddy".
%    \begin{macrocode}
\define@key{flowframe}{oddy}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'oddy' key}{}}{}%
\def\ff@oddy{#1}}
%    \end{macrocode}
% New \gls{idl} for \gls{frame} is stored in "\ff@label".
%    \begin{macrocode}
\define@key{flowframe}{label}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'label' key}{}}{}%
\def\ff@label{#1}}
%    \end{macrocode}
% Frame border. If "none", define "\ff@frame" as "false", 
% otherwise define "\ff@frame" as "true". If "plain", define
% "\ff@frametype" as "fbox", otherwise define it to be
% the specified type, which should be the name of a
% \gls{fcmd} without the preceding backslash.
%    \begin{macrocode}
\define@key{flowframe}{border}[plain]{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'border' key - use
'none' for no border}{}}{}%
\ifthenelse{\equal{#1}{none}}{%
\def\ff@frame{false}}{\def\ff@frame{true}%
\ifthenelse{\equal{#1}{plain}}{\def\ff@frametype{fbox}}{%
\def\ff@frametype{#1}}}}
%    \end{macrocode}
% Frame's border colour. (This may not work for non-standard
% \glspl{fcmd}.)
%    \begin{macrocode}
\define@key{flowframe}{bordercolor}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'bordercolor' key}{}}{}%
\def\ff@col{#1}}
%    \end{macrocode}
% Frame's text colour.
%    \begin{macrocode}
\define@key{flowframe}{textcolor}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'textcolor' key}{}}{}%
\def\ff@txtcol{#1}}
%    \end{macrocode}
% The background colour of the \gls{frame}. Note this only covers
% the region of the \gls{bbox}, not any extra space between
% the \gls{bbox} and the border. If you want the background
% colour to go right up to the border, you will need to 
% define your own customised border.
%    \begin{macrocode}
\define@key{flowframe}{backcolor}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'backcolor' key}{}}{}%
\def\ff@backcol{#1}}
%    \end{macrocode}
% \Gls{pglist} for which the \gls{frame} should appear.
%    \begin{macrocode}
\define@key{flowframe}{pages}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'pages' key}{}}{}%
\def\ff@pages{#1}}
%    \end{macrocode}
% The border takes up extra space, which needs to be
% adjusted. This can be done for standard border types,
% but non-standard borders may require some help.
%    \begin{macrocode}
\define@key{flowframe}{offset}{\def\ff@offset{#1}%
\ifthenelse{\equal{#1}{}}{\PackageError{flowframe}{%
Invalid value for key 'offset'}{%
'offset' can either be 'compute' (to compute it according
to certain pre-defined rules) or a length}}{}}
%    \end{macrocode}
% Angle to rotate \gls{flow}:
%    \begin{macrocode}
\define@key{flowframe}{angle}{\def\ff@angle{#1}%
}
%    \end{macrocode}
% This key is only for \glspl{flow}:
%    \begin{macrocode}
\define@key{flowframe}{margin}{%
\ifthenelse{\equal{#1}{left} \or \equal{#1}{right} 
\or \equal{#1}{inner} \or \equal{#1}{outer}}{%
\def\ff@margin{#1}}{\PackageError{flowfram}{invalid value of 
'margin' key}{Key 'margin' can only take the values 
'left' or 'right'}}}
%    \end{macrocode}
% This key is only for \glspl{static}:
%    \begin{macrocode}
\define@key{flowframe}{clear}[true]{%
\ifthenelse{\equal{#1}{true}\or\equal{#1}{false}}{%
\def\ff@clear{#1}}{\PackageError{flowfram}{Key 'clear' is 
boolean}{You can only specify the values 'true' or 'false'}}}
%    \end{macrocode}
% This key is only for \glspl{dynamic}:
%    \begin{macrocode}
\define@key{flowframe}{style}{\ifthenelse{\equal{#1}{}}{%
\PackageError{flowfram}{Missing value for 'style' key}{}}{}%
\ifthenelse{\equal{#1}{none}}{\def\ff@style{relax}}{\def\ff@style{#1}}}
%    \end{macrocode}
% This key is only for \glspl{static} and \glspl{dynamic}.
%    \begin{macrocode}
\define@key{flowframe}{shape}{\def\ff@shape{#1}%
}
%    \end{macrocode}
% This key is only for \glspl{static} and \glspl{dynamic}.
%    \begin{macrocode}
\define@key{flowframe}{valign}{\ifthenelse{\equal{#1}{c} \or
\equal{#1}{t} \or \equal{#1}{b}}{\def\ff@valign{#1}}{%
\PackageError{flowfram}{Invalid value for 'valign' key}{You
may only specify 'c', 't' or 'b'}}}
%    \end{macrocode}
%\begin{macro}{\setallflowframes}
% Provide a command to change the settings for all flow
% frames. This just iterates through all the \glspl{flow},
% and sets each one in turn.
%    \begin{macrocode}
\newcommand*{\setallflowframes}[1]{%
\@colN=0\whiledo{\@colN<\c@maxflow}{\advance\@colN by 1\relax
\@@setflowframe{\@colN}{#1}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setflowframe}
% Define "\setflowframe" command. Check to see
% whether or not the starred version is being used.
%    \begin{macrocode}
\newcommand*{\setflowframe}{\@ifstar\@ssetflowframe\@setflowframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ssetflowframe}
% This is the starred version. It finds the \gls{idn} for
% each label in the comma-separated list (first argument), 
% and applies the setting for that numbered \gls{flow}.
%    \begin{macrocode}
\newcommand{\@ssetflowframe}[2]{%
\@for\@ff@id:=#1\do{%
\@flowframeid{\@ff@id}%
\@@setflowframe{\ff@id}{#2}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setflowframe}
% This is the unstarred version. It iterates through
% each \gls{idn} in the comma-separated list passed
% as the first argument, but it also checks for number
% ranges, and sets the values for that \gls{flow}. Ensures
% that number ranges do not lie out of bounds.
%    \begin{macrocode}
\newcommand*{\@setflowframe}[2]{%
\ifthenelse{\equal{#1}{all}}{%
\setallflowframes{#2}}{%
\ifthenelse{\equal{#1}{odd} \TE@or \equal{#1}{even}}{%
\ifthenelse{\equal{#1}{odd}}{\@colN=1}{\@colN=2}%
\whiledo{\@colN<\c@maxflow\TE@or\@colN=\c@maxflow}{%
\@@setflowframe{\@colN}{#2}%
\advance\@colN by 2\relax}%
}{%
\@for\@ff@id:=#1\do{%
\def\@ff@numstart{0}\def\@ff@numend{10000}%
\@ff@getrange{\@ff@id}%
\ifnum\@ff@numstart=0\relax
  \def\@ff@numstart{1}%
\fi
\ifnum\@ff@numend>\c@maxflow\relax
  \def\@ff@numend{\c@maxflow}%
\fi
\@colN=\@ff@numstart\relax
\whiledo{\@colN<\@ff@numend \TE@or \@colN=\@ff@numend}{%
\@@setflowframe{\@colN}{#2}%
\advance\@colN by 1\relax
}}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@setflowframe}
% This is the command that actually sets the values for
% the \gls{flow} whose \gls{idn} is specified by the first
% parameter.
%\changes{1.11}{2008/06/27}{removed unwanted spaces}
%    \begin{macrocode}
\newcommand*{\@@setflowframe}[2]{%
\def\ff@frame{}\def\ff@width{}\def\ff@height{}\def\ff@margin{}%
\def\ff@x{}\def\ff@y{}\def\ff@frametype{}\def\ff@col{}%
\def\ff@valign{}\def\ff@style{}%
\def\ff@txtcol{}\def\ff@clear{}\def\ff@offset{}\def\ff@pages{}%
\def\ff@label{}\def\ff@backcol{}\def\ff@evenx{}\def\ff@eveny{}%
\def\ff@oddx{}\def\ff@oddy{}\def\ff@angle{}\def\ff@shape{\empty}%
\setkeys{flowframe}{#2}%
\ifthenelse{\equal{\ff@frame}{}}{}{%
\setboolean{columnframe\romannumeral#1}{\ff@frame}}%
\ifthenelse{\equal{\ff@width}{}}{}{%
\expandafter\setlength\csname colwidth\romannumeral#1\endcsname
{\ff@width}}%
\ifthenelse{\equal{\ff@height}{}}{}{%
\expandafter\setlength\csname colheight\romannumeral#1\endcsname
{\ff@height}}%
\ifthenelse{\equal{\ff@x}{}}{}{%
\expandafter\setlength\csname col@\romannumeral#1@posx\endcsname
{\ff@x}%
\expandafter\setlength\csname col@\romannumeral#1@evenx\endcsname
{\ff@x}}
\ifthenelse{\equal{\ff@y}{}}{}{%
\expandafter\setlength\csname col@\romannumeral#1@posy\endcsname
{\ff@y}%
\expandafter\setlength\csname col@\romannumeral#1@eveny\endcsname
{\ff@y}}%
\ifthenelse{\equal{\ff@evenx}{}}{}{%
\expandafter\setlength\csname col@\romannumeral#1@evenx\endcsname
{\ff@evenx}}%
\ifthenelse{\equal{\ff@eveny}{}}{}{%
\expandafter\setlength\csname col@\romannumeral#1@eveny\endcsname
{\ff@eveny}}%
\ifthenelse{\equal{\ff@oddx}{}}{}{%
\expandafter\setlength\csname col@\romannumeral#1@posx\endcsname
{\ff@oddx}}%
\ifthenelse{\equal{\ff@oddy}{}}{}{%
\expandafter\setlength\csname col@\romannumeral#1@posy\endcsname
{\ff@oddy}}%
\ifthenelse{\equal{\ff@label}{}}{}{%
\@s@tflowframeid{#1}[\ff@label]}%
\ifthenelse{\equal{\ff@frametype}{}}{}{%
\expandafter\edef\csname @ff@frametype@\romannumeral#1\endcsname
{\ff@frametype}}%
\ifthenelse{\equal{\ff@col}{}}{}{%
\expandafter\@setframecol\ff@col\end{#1}{col}{ff}}%
\ifthenelse{\equal{\ff@txtcol}{}}{}{%
\expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{ff}}%
\ifthenelse{\equal{\ff@backcol}{}}{}{%
\expandafter\@setframecol\ff@backcol\end{#1}{backcol}{ff}}%
\ifthenelse{\equal{\ff@margin}{}}{}{%
\expandafter\xdef\csname @ff@margin@\romannumeral#1\endcsname
{\ff@margin}}%
\ifthenelse{\equal{\ff@pages}{}}{}{%
\expandafter\xdef\csname @ff@pages@\romannumeral#1\endcsname
{\ff@pages}}%
\ifthenelse{\equal{\ff@offset}{}}{}{%
\expandafter\xdef\csname @ff@offset@\romannumeral#1\endcsname
{\ff@offset}}%
\ifthenelse{\equal{\ff@angle}{}}{}{%
\expandafter\xdef\csname @ff@angle@\romannumeral#1\endcsname
{\ff@angle}}%
\ifthenelse{\equal{\ff@clear}{}}{}{%
\PackageError{flowfram}%
{Key 'clear' not available for flow frames}{}}%
\ifthenelse{\equal{\ff@style}{}}{}{%
\PackageError{flowfram}%
{Key 'style' not available for flow frames}{}}%
\if\ff@shape\empty
\else
\PackageError{flowfram}%
{Key 'shape' not available for flow frames}{}%
\fi
\ifthenelse{\equal{\ff@valign}{}}{}{%
\PackageError{flowfram}%
{Key 'valign' not available for flow frames}{}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffswapoddeven}
% Swap odd and even offsets for a given \gls{flow}. Do the main stuff for 
% a given \gls{flow} \gls{idn}.
%    \begin{macrocode}
\newcommand*{\@@flowframeswapcoords}[1]{%
\setlength{\@ff@tmp@x}%
{\csname col@\romannumeral#1@evenx\endcsname}
\expandafter\setlength\csname col@\romannumeral#1@evenx\endcsname
{\csname col@\romannumeral#1@posx\endcsname}%
\expandafter\setlength\csname col@\romannumeral#1@posx\endcsname
{\@ff@tmp@x}%
\setlength{\@ff@tmp@y}%
{\csname col@\romannumeral#1@eveny\endcsname}
\expandafter\setlength\csname col@\romannumeral#1@eveny\endcsname
{\csname col@\romannumeral#1@posy\endcsname}%
\expandafter\setlength\csname col@\romannumeral#1@posy\endcsname
{\@ff@tmp@y}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffswapoddeven}
% Allow user to specify \gls{flow} either by \gls{idn} or \gls{idl}:
%    \begin{macrocode}
\newcommand*{\ffswapoddeven}{%
\@ifstar\@sflowframeswapcoords\@flowframeswapcoords}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sflowframeswapcoords}
% Starred form
%    \begin{macrocode}
\newcommand*{\@sflowframeswapcoords}[1]{%
\@for\@ff@id:=#1\do{%
\@flowframeid{\@ff@id}%
\@@flowframeswapcoords{\ff@id}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@flowframeswapcoords}
% Unstarred form:
%    \begin{macrocode}
\newcommand*{\@flowframeswapcoords}[1]{%
\ifthenelse{\equal{#1}{all}}{%
\ff@id=0\relax
\whiledo{\ff@id<\c@maxflow}{\advance\ff@id by 1\relax
\@@flowframeswapcoords{\ff@id}}%
}{%
\ifthenelse{\equal{#1}{odd} \TE@or \equal{#1}{even}}{%
\ifthenelse{\equal{#1}{odd}}{\@colN=1}{\@colN=2}%
\whiledo{\@colN<\c@maxflow\TE@or\@colN=\c@maxflow}{%
\@@flowframeswapcoords{\@colN}%
\advance\@colN by 2\relax}%
}{%
\@for\@ff@id:=#1\do{%
\def\@ff@numstart{0}\def\@ff@numend{10000}%
\@ff@getrange{\@ff@id}%
\ifnum\@ff@numstart=0\relax
  \def\@ff@numstart{1}%
\fi
\ifnum\@ff@numend>\c@maxflow
  \def\@ff@numend{\c@maxflow}%
\fi
\@colN=\@ff@numstart
\whiledo{\@colN<\@ff@numend \TE@or \@colN=\@ff@numend}{%
\@@flowframeswapcoords{\@colN}%
\advance\@colN by 1\relax
}}}}}
%    \end{macrocode}
%\end{macro}
%
% Allow user to get the dimensions of \gls{flow} (useful for
% \glspl{flow} created using "\Ncolumns" etc.) Only the \gls{idn} can
% be used for these commands.
%\begin{macro}{\flowframex}
%    \begin{macrocode}
\newcommand*{\flowframex}[1]{%
\csname col@\romannumeral#1@posx\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframey}
%    \begin{macrocode}
\newcommand*{\flowframey}[1]{%
\csname col@\romannumeral#1@posy\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframeevenx}
%    \begin{macrocode}
\newcommand*{\flowframeevenx}[1]{%
\csname col@\romannumeral#1@evenx\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframeeveny}
%    \begin{macrocode}
\newcommand*{\flowframeeveny}[1]{%
\csname col@\romannumeral#1@eveny\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframewidth}
%    \begin{macrocode}
\newcommand{\flowframewidth}[1]{%
\csname colwidth\romannumeral#1\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframeheight}
%    \begin{macrocode}
\newcommand*{\flowframeheight}[1]{%
\csname colheight\romannumeral#1\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setframecol}
% Set the colour of the frame, this is a little tricky 
% because the model may need to be specified in square
% brackets. First check to see if a colour model has been
% specified
%    \begin{macrocode}
\def\@setframecol{\@ifnextchar[\@@setframecol\@@setfr@mecol}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@setframecol}
% A colour model has been specified.
%    \begin{macrocode}
\def\@@setframecol[#1]#2\end#3#4#5{%
\expandafter\edef\csname @#5@#4@\romannumeral#3\endcsname{%
[#1]{#2}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@setfr@mecol}
% A colour model has not been specified.
%    \begin{macrocode}
\def\@@setfr@mecol#1\end#2#3#4{%
\expandafter\edef\csname @#4@#3@\romannumeral#2\endcsname{{#1}}}
%    \end{macrocode}
%\end{macro}
%
% \subsection{Static Frames}
%\begin{macro}{\newstaticframe}
% Now deal with setting up the \glspl{static}.  This is
% similar to the \glspl{flow}, except it has an 
% associated \LaTeX\ savebox rather than a \TeX\ box.
% Syntax:\newline
% \cs{newstaticframe}\oarg{pages}\marg{width}\marg{height}\marg{x}\marg{y}\oarg{label}\par
% As with "\newflowframe", the final optional argument is 
% dealt with at the end.
%    \begin{macrocode}
\newcommand*{\newstaticframe}{\@n@wstaticframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@n@wstaticframe}
%    \begin{macrocode}
\newcommand*{\@n@wstaticframe}{%
\global\advance\c@maxstatic by 1\relax
\newboolean{staticframe\romannumeral\c@maxstatic}%
\@ifstar\@snewstaticframe\@newstaticframe
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@snewstaticframe}
% Starred version (has a border):
%    \begin{macrocode}
\newcommand{\@snewstaticframe}{%
\setboolean{staticframe\romannumeral\c@maxstatic}{true}%
\@@newstaticframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@newstaticframe}
% Unstarred version (no border):
%    \begin{macrocode}
\newcommand{\@newstaticframe}{%
\setboolean{staticframe\romannumeral\c@maxstatic}{false}%
\@@newstaticframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@newstaticframe}
% Now set up the \gls{static}:
%    \begin{macrocode}
\newcommand*{\@@newstaticframe}[5][all]{%
\expandafter
\newbox\csname @staticframe@\romannumeral\c@maxstatic\endcsname
\expandafter
\newlength\csname @sf@\romannumeral\c@maxstatic @posx\endcsname
\expandafter
\newlength\csname @sf@\romannumeral\c@maxstatic @posy\endcsname
\expandafter\setlength
\csname @sf@\romannumeral\c@maxstatic @posx\endcsname{#4}%
\expandafter\setlength
\csname @sf@\romannumeral\c@maxstatic @posy\endcsname{#5}%
\expandafter\newlength
\csname @sf@\romannumeral\c@maxstatic @evenx\endcsname
\expandafter\newlength
\csname @sf@\romannumeral\c@maxstatic @eveny\endcsname
\expandafter\setlength
\csname @sf@\romannumeral\c@maxstatic @evenx\endcsname{#4}%
\expandafter\setlength
\csname @sf@\romannumeral\c@maxstatic @eveny\endcsname{#5}%
{\@ff@tmp@x=#2\relax
\@ff@tmp@y=#3\relax
\expandafter
\xdef\csname @sf@dim@\romannumeral\c@maxstatic\endcsname{%
[c][\the\@ff@tmp@y][c]{\the\@ff@tmp@x}}}%
\expandafter
\def\csname @sf@col@\romannumeral\c@maxstatic\endcsname{%
\flowframecol}%
\expandafter
\def\csname @sf@txtcol@\romannumeral\c@maxstatic\endcsname{%
\flowframetextcol}%
\expandafter
\def\csname @sf@backcol@\romannumeral\c@maxstatic\endcsname{%
{none}}%
\expandafter
\xdef\csname @sf@pages@\romannumeral\c@maxstatic\endcsname{#1}%
\expandafter
\gdef\csname @sf@offset@\romannumeral\c@maxstatic\endcsname{%
compute}%
\expandafter
\gdef\csname @sf@angle@\romannumeral\c@maxstatic\endcsname{0}%
\expandafter
\gdef\csname @sf@shape@\romannumeral\c@maxstatic\endcsname{\relax}%
\expandafter
\def\csname @sf@frametype@\romannumeral\c@maxstatic\endcsname{%
fbox}%
\newboolean{@sf@clear@\romannumeral\c@maxstatic}%
\setboolean{@sf@clear@\romannumeral\c@maxstatic}{false}
\@ifnextchar[{\@s@tstaticframeid{\c@maxstatic}}%
{\@s@tstaticframeid{\c@maxstatic}[\number\c@maxstatic]}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tstaticframeid}
% Set the label for the \gls{static}:
%    \begin{macrocode}
\def\@s@tstaticframeid#1[#2]{%
\edef\ff@label{#2}%
\@sf@checkuniqueidl{#1}{\ff@label}%
\expandafter
\xdef\csname @sf@id@\romannumeral#1\endcsname{\ff@label}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sf@checkuniqueidl}
% Check \gls{idl} "#2" for \gls{static} "#1" is unique
%    \begin{macrocode}
\newcommand*{\@sf@checkuniqueidl}[2]{%
\@colN=0\relax
\whiledo{\@colN<\c@maxstatic}{%
\advance\@colN by 1\relax
\ifnum\@colN=#1\relax
\else
\ifthenelse{%
\equal{#2}{\csname @sf@id@\romannumeral\@colN\endcsname}}{%
\PackageError{flowfram}{Static frame IDL '#2' already defined}{%
You can't assign this label, as it is already defined
for static frame \number\@colN}}{}%
\fi
}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getstaticlabel}
%\changes{1.11}{2008/06/27}{new}
%\cs{getstaticlabel}\marg{idn}
% Gets the \gls{idl} for the \gls{static} identified by its
% \gls{idn}.
%    \begin{macrocode}
\newcommand*{\getstaticlabel}[1]{%
\csname @sf@id@\romannumeral#1\endcsname}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getstaticid}
%\changes{1.11}{2008/06/27}{new}
%\cs{getstaticid}\marg{cmd}\marg{idl}
% Gets the \gls{idn} for the \gls{static} identified by its
% \gls{idl} and stores in \meta{cmd} which must be a control
% sequence.
%    \begin{macrocode}
\newcommand*{\getstaticid}[2]{%
\@staticframeid{#2}\edef#1{\number\ff@id}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticframeid}
% Work out the \gls{idn} of the \gls{static} with the
% given label.  This iterates through each \gls{static},
% so if there are a lot of \glspl{static}, it may take a while.
% The \gls{idn} stored in "\ff@id".
%    \begin{macrocode}
\newcommand*{\@staticframeid}[1]{\@colN=0\relax
\ff@id=0\relax
\whiledo{\@colN<\c@maxstatic}{\advance\@colN by 1\relax
\ifthenelse{%
\equal{#1}{\csname @sf@id@\romannumeral\@colN\endcsname}}{%
\ff@id=\@colN\relax
% break out of loop
\@colN=\c@maxstatic}{}}%
\ifnum\ff@id=0\PackageError{flowfram}{Can't find static frame 
id '#1'}{}\fi}
%    \end{macrocode}
%\end{macro}
%
% Make it easier to get the x and y values for static
% frames. (Width and height stored differently.)
%\begin{macro}{\staticframex}
%    \begin{macrocode}
\newcommand*{\staticframex}[1]{%
\csname @sf@\romannumeral#1@posx\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticframey}
%    \begin{macrocode}
\newcommand*{\staticframey}[1]{%
\csname @sf@\romannumeral#1@posy\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticframeevenx}
%    \begin{macrocode}
\newcommand*{\staticframeevenx}[1]{%
\csname @sf@\romannumeral#1@evenx\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticframeeveny}
%    \begin{macrocode}
\newcommand*{\staticframeeveny}[1]{%
\csname @sf@\romannumeral#1@eveny\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setallstaticframes}
% Modify the settings for all the \glspl{static}:
%    \begin{macrocode}
\newcommand*{\setallstaticframes}[1]{%
\@colN=0\whiledo{\@colN<\c@maxstatic}{\advance\@colN by 1\relax
\@@setstaticframe{\@colN}{#1}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setstaticframe}
% Modify the settings for the specified \glspl{static}:
%    \begin{macrocode}
\newcommand*{\setstaticframe}{%
\@ifstar\@ssetstaticframe\@setstaticframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ssetstaticframe}
% Starred version: Iterate through the comma-separated
% list of labels.
%    \begin{macrocode}
\newcommand*{\@ssetstaticframe}[2]{%
\@for\@ff@id:=#1\do{%
\@staticframeid{\@ff@id}%
\@@setstaticframe{\ff@id}{#2}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setstaticframe}
% Unstarred version. Iterate through the comma-separated
% list of \glspl{idn}, and check for number ranges.
% Ensures that number ranges do not lie out of bounds.
%    \begin{macrocode}
\newcommand*{\@setstaticframe}[2]{%
\ifthenelse{\equal{#1}{all}}{%
\setallstaticframes{#2}}{%
\ifthenelse{\equal{#1}{odd} \TE@or \equal{#1}{even}}{%
\ifthenelse{\equal{#1}{odd}}{\@colN=1}{\@colN=2}%
\whiledo{\@colN<\c@maxstatic\TE@or\@colN=\c@maxstatic}{%
\@@setstaticframe{\@colN}{#2}%
\advance\@colN by 2\relax}%
}{%
\@for\@ff@id:=#1\do{%
\def\@ff@numstart{0}\def\@ff@numend{10000}%
\@ff@getrange{\@ff@id}%
\ifnum\@ff@numstart=0\relax
  \def\@ff@numstart{1}%
\fi
\ifnum\@ff@numend>\c@maxstatic\relax
  \def\@ff@numend{\c@maxstatic}%
\fi
\@colN=\@ff@numstart\relax
\whiledo{\@colN<\@ff@numend \TE@or \@colN=\@ff@numend}{%
\@@setstaticframe{\@colN}{#2}%
\advance\@colN by 1\relax
}}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@setstaticframe}
% Modify the settings for the \gls{static} whose \gls{idn}\
% is given by the first argument.
%    \begin{macrocode}
\newcommand*{\@@setstaticframe}[2]{%
\expandafter\expandafter\expandafter
\@ff@getstaticpos\csname @sf@dim@\romannumeral#1\endcsname
\def\ff@frame{}\edef\ff@width{\the\@ff@tmp@x}\def\ff@angle{}%
\edef\ff@height{\the\@ff@tmp@y}\def\ff@style{}\def\ff@frametype{}%
\def\ff@x{}\def\ff@y{}\def\ff@col{}\def\ff@txtcol{}%
\def\ff@backcol{}\def\ff@shape{0}%
\def\ff@clear{}\def\ff@margin{}\def\ff@offset{}\def\ff@pages{}%
\def\ff@label{}\def\ff@evenx{}\def\ff@eveny{}%
\def\ff@oddx{}\def\ff@oddy{}%
\setkeys{flowframe}{#2}%
\ifthenelse{\equal{\ff@frame}{}}{}{%
\setboolean{staticframe\romannumeral#1}{\ff@frame}}%
\ifthenelse{\equal{\ff@x}{}}{}{%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@posx\endcsname
{\ff@x}%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@evenx\endcsname
{\ff@x}}%
\ifthenelse{\equal{\ff@y}{}}{}{%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@posy\endcsname
{\ff@y}%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@eveny\endcsname
{\ff@y}}%
\ifthenelse{\equal{\ff@evenx}{}}{}{%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@evenx\endcsname
{\ff@evenx}}%
\ifthenelse{\equal{\ff@eveny}{}}{}{%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@eveny\endcsname
{\ff@eveny}}%
\ifthenelse{\equal{\ff@oddx}{}}{}{%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@posx\endcsname
{\ff@oddx}}%
\ifthenelse{\equal{\ff@oddy}{}}{}{%
\expandafter\global
\expandafter\setlength\csname @sf@\romannumeral#1@posy\endcsname
{\ff@oddy}}%
\expandafter
\xdef\csname @sf@dim@\romannumeral#1\endcsname{%
[c][\ff@height][\ff@valign]{\ff@width}}%
\ifthenelse{\equal{\ff@frametype}{}}{}{%
\expandafter
\xdef\csname @sf@frametype@\romannumeral#1\endcsname{%
\ff@frametype}}%
\ifthenelse{\equal{\ff@label}{}}{}{%
\@s@tstaticframeid{#1}[\ff@label]}
\ifthenelse{\equal{\ff@col}{}}{}{%
\expandafter\@setframecol\ff@col\end{#1}{col}{sf}}%
\ifthenelse{\equal{\ff@txtcol}{}}{}{%
\expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{sf}}%
\ifthenelse{\equal{\ff@backcol}{}}{}{%
\expandafter\@setframecol\ff@backcol\end{#1}{backcol}{sf}}%
\ifthenelse{\equal{\ff@offset}{}}{}{%
\expandafter
\xdef\csname @sf@offset@\romannumeral#1\endcsname{\ff@offset}}%
\ifthenelse{\equal{\ff@angle}{}}{}{%
\expandafter
\xdef\csname @sf@angle@\romannumeral#1\endcsname{\ff@angle}}%
\if0\ff@shape
\else
\expandafter\global\expandafter
\let\csname @sf@shape@\romannumeral#1\endcsname\ff@shape
\fi
\ifthenelse{\equal{\ff@pages}{}}{}{%
\expandafter
\xdef\csname @sf@pages@\romannumeral#1\endcsname{\ff@pages}}%
\ifthenelse{\equal{\ff@clear}{}}{}{%
\setboolean{@sf@clear@\romannumeral#1}{\ff@clear}}%
\ifthenelse{\equal{\ff@margin}{}}{}{%
\PackageError{flowfram}{Key 'margin' not available for 
static frames}{Static frames don't have marginal notes}}%
\ifthenelse{\equal{\ff@style}{}}{}{%
\PackageError{flowfram}{Key 'style' not available for 
static frames}{}}%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\simpar}
% Simulate paragraph break inside "\shapepar"
%    \begin{macrocode}
 %\newcommand*{\simpar}{\hfil\vadjust{\vskip\parskip}\break\indent}
\newcommand*{\simpar}{\hfill\\\indent\mbox{}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffpshpar}
% Provide means to allow parshape to be carried over a paragraph 
% break.
%    \begin{macrocode}
\let\FLForgpar\par
\newcommand{\ffpshpar}{\edef\flf@next{\hangafter=\the\hangafter
\hangindent=\the\hangindent}\FLForgpar\flf@next
\edef\flf@next{\prevgraf=\the\prevgraf}\@ff@parshape\indent\mbox{}\flf@next}
%    \end{macrocode}
%\end{macro}
%
% Provide a means to have section headings within "\parshape".
%\begin{macro}{\@ff@parshape}
%    \begin{macrocode}
\def\@ff@parshape{\parshape=0}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@sectionhead}
%    \begin{macrocode}
\newcommand*{\@ff@sectionhead}[1]{%
\def\ff@sechead{#1}%
\ffpshpar
\@ifstar{\@s@ff@heading}{\@dblarg\@ff@heading}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@ff@heading}
%    \begin{macrocode}
\def\@s@ff@heading#1{%
\@ifundefined{@ff@old\ff@sechead}{\PackageError{flowfram}{Unknown
heading command '\ff@sechead'}{}}{%
\begingroup
\edef\flf@next{\hangafter=\the\hangafter
\hangindent=\the\hangindent}\FLForgpar\flf@next
\let\par=\FLForgpar
\edef\flf@next{\prevgraf=\the\prevgraf}%
\csname @ff@old\ff@sechead\endcsname*{\@ff@parshape\flf@next 
#1}%
\xdef\flf@next{\@ff@parshape
\prevgraf=\the\prevgraf}%
\endgroup
}%
\mbox{}\flf@next\let\flf@next\undefined}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@heading}
%    \begin{macrocode}
\def\@ff@heading[#1]#2{%
\@ifundefined{@ff@old\ff@sechead}{\PackageError{flowfram}{Unknown
heading command '\ff@sechead'}{}}{%
\begingroup
\edef\flf@next{\hangafter=\the\hangafter
\hangindent=\the\hangindent}\FLForgpar\flf@next
\let\par=\FLForgpar
\edef\flf@next{\prevgraf=\the\prevgraf}%
\csname @ff@old\ff@sechead\endcsname[#1]{\@ff@parshape\flf@next 
#2}%
\xdef\flf@next{\@ff@parshape
\prevgraf=\the\prevgraf}%
\endgroup}%
\mbox{}\flf@next\let\flf@next\undefined}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@setsecthead}
% Define command to switch to adjusted section headings:
%    \begin{macrocode}
\newcommand*{\@ff@setsecthead}{%
\let\@ff@oldsection=\section
\let\@ff@oldsubsection=\subsection
\let\@ff@oldsubsubsection=\subsubsection
\let\@ff@oldparagraph=\paragraph
\let\@ff@oldsubparagraph=\subparagraph
\def\section{\@ff@sectionhead{section}}%
\def\subsection{\@ff@sectionhead{subsection}}%
\def\subsubsection{\@ff@sectionhead{subsubsection}}%
\def\paragraph{\@ff@sectionhead{paragraph}}%
\def\subparagraph{\@ff@sectionhead{subparagraph}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@getshape}
% Determine what shape command is being used:
%    \begin{macrocode}
\def\@ff@getshape#1#2\relax{%
\ifx#1\parshape
\def\ff@shape{1}%
\else
\ifx#1\shapepar
\def\ff@shape{2}%
\else
\ifx#1\relax
\def\ff@shape{0}%
\else
\PackageError{flowfram}{Unknown shape \string#1}{}%
\def\ff@shape{2}%
\fi
\fi
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@disablesec}
% Disable sectioning commands
%    \begin{macrocode}
\newcommand*{\@ff@disablesec}{%
\def\section{\PackageError{flowfram}{You can't have
sectioning commands within a \string\shapepar}{}}%
\def\subsection{\PackageError{flowfram}{You can't have
sectioning commands within a \string\shapepar}{}}%
\def\subsubsection{\PackageError{flowfram}{You can't have
sectioning commands within a \string\shapepar}{}}%
\def\paragraph{\PackageError{flowfram}{You can't have
sectioning commands within a \string\shapepar}{}}%
\def\subparagraph{\PackageError{flowfram}{You can't have
sectioning commands within a \string\shapepar}{}}%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{environment}{staticcontents}
% Set the contents of the \gls{static} given by its \gls{idn}.
% Syntax: "\begin{staticcontents}"\marg{idn}.
%    \begin{macrocode}
\newbox\staticframe
\newenvironment{staticcontents}[1]{%
\let\continueonframe=\@staticcontinueonframe
\@beginstaticcontents{#1}%
}{%
\@endstaticcontents
\ignorespaces}
%    \end{macrocode}
%\end{environment}
%\begin{environment}{staticcontents*}
% Set the contents of the \gls{static} given by its \gls{idl}.
% Syntax: "\begin{staticcontents*}"\marg{label}.
%    \begin{macrocode}
\newenvironment{staticcontents*}[1]{\@staticframeid{#1}%
\let\continueonframe=\@staticscontinueonframe
\@beginstaticcontents{\ff@id}%
}{%
\@endstaticcontents
\ignorespaces}
%    \end{macrocode}
%\end{environment}
%
% Begin staticcontents stuff.
%    \begin{macrocode}
\newcommand{\@beginstaticcontents}[1]{%
\@ifundefined{@staticframe@\romannumeral#1}{%
\PackageError{flowfram}{Static frame '#1' not defined}{}}{}%
\expandafter\let\expandafter\@ff@parshape\csname @sf@shape@\romannumeral#1\endcsname
\expandafter\@ff@getshape\@ff@parshape\relax
\ifcase\ff@shape
% no shape
\edef\@sf@mpg{%
\noexpand
\begin{minipage}\csname @sf@dim@\romannumeral#1\endcsname
\noexpand\begingroup
\noexpand\let\noexpand\FLForgpar=\noexpand\par
}%
\or
% \parshape
\edef\@sf@mpg{%
\noexpand
\begin{minipage}\csname @sf@dim@\romannumeral#1\endcsname
\@ff@parshape
\noexpand\begingroup
\noexpand\let\noexpand\FLForgpar=\noexpand\par
\noexpand\let\noexpand\par=\noexpand\ffpshpar
\noexpand\@ff@setsecthead
}%
\or
% \shapepar
\edef\@sf@mpg{%
\noexpand
\begin{minipage}\csname @sf@dim@\romannumeral#1\endcsname
\noexpand\begingroup
\noexpand\@ff@disablesec
\noexpand\@ff@parshape
}%
\fi
\edef\@sf@thisframe{\csname @staticframe@\romannumeral#1\endcsname}%
\begin{lrbox}{\staticframe}%
\edef\ff@txtcol{\csname @sf@txtcol@\romannumeral#1\endcsname}%
\@s@tfftextcol\noindent
\@sf@mpg
\setlength\parindent\sdfparindent
}
%    \end{macrocode}
% End staticcontents stuff
%    \begin{macrocode}
\newcommand*{\@endstaticcontents}{%
\ifnum\ff@shape=2\par
\else\FLForgpar\fi\endgroup\end{minipage}\end{lrbox}%
\expandafter\global\expandafter\sbox\@sf@thisframe{%
\usebox\staticframe}}
%    \end{macrocode}
%
%\begin{macro}{\setstaticcontents}
% Provide a command version.
% Syntax: \cs{setstaticcontents}\marg{idn}\marg{text}.
%    \begin{macrocode}
\newcommand{\setstaticcontents}{%
\@ifstar\@sstaticconts\@staticconts}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sstaticconts}
% Starred version: \gls{static} identified by label.
%    \begin{macrocode}
\newcommand{\@sstaticconts}[2]{\begin{staticcontents*}{#1}%
#2\end{staticcontents*}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@staticconts}
% Unstarred version: \gls{static} identified by \gls{idn}.
%    \begin{macrocode}
\newcommand{\@staticconts}[2]{\begin{staticcontents}{#1}%
#2\end{staticcontents}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@@staticframeswapcoords}
% Swap odd and even offsets for a given \gls{static}. Do the main stuff for 
% a given \gls{static} \gls{idn}.
%    \begin{macrocode}
\newcommand*{\@@staticframeswapcoords}[1]{%
\setlength{\@ff@tmp@x}%
{\csname @sf@\romannumeral#1@evenx\endcsname}
\expandafter\setlength\csname @sf@\romannumeral#1@evenx\endcsname
{\csname @sf@\romannumeral#1@posx\endcsname}%
\expandafter\setlength\csname @sf@\romannumeral#1@posx\endcsname
{\@ff@tmp@x}%
\setlength{\@ff@tmp@y}%
{\csname @sf@\romannumeral#1@eveny\endcsname}
\expandafter\setlength\csname @sf@\romannumeral#1@eveny\endcsname
{\csname @sf@\romannumeral#1@posy\endcsname}%
\expandafter\setlength\csname @sf@\romannumeral#1@posy\endcsname
{\@ff@tmp@y}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\sfswapoddeven}
% Allow user to specify \gls{flow} either by \gls{idn} or \gls{idl}:
%    \begin{macrocode}
\newcommand*{\sfswapoddeven}{%
\@ifstar\@sstaticframeswapcoords\@staticframeswapcoords}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sstaticframeswapcoords}
% Starred form
%    \begin{macrocode}
\newcommand*{\@sstaticframeswapcoords}[1]{%
\@for\@ff@id:=#1\do{%
\@staticframeid{\@ff@id}%
\@@staticframeswapcoords{\ff@id}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@staticframeswapcoords}
% Unstarred form:
%    \begin{macrocode}
\newcommand*{\@staticframeswapcoords}[1]{%
\ifthenelse{\equal{#1}{all}}{%
\ff@id=0\relax
\whiledo{\ff@id<\c@maxflow}{\advance\ff@id by 1\relax
\@@staticframeswapcoords{\ff@id}}%
}{%
\ifthenelse{\equal{#1}{odd} \TE@or \equal{#1}{even}}{%
\ifthenelse{\equal{#1}{odd}}{\@colN=1}{\@colN=2}%
\whiledo{\@colN<\c@maxflow\TE@or\@colN=\c@maxflow}{%
\@@staticframeswapcoords{\@colN}%
\advance\@colN by 2\relax}%
}{%
\@for\@ff@id:=#1\do{%
\def\@ff@numstart{0}\def\@ff@numend{10000}%
\@ff@getrange{\@ff@id}%
\ifnum\@ff@numstart=0\relax
  \def\@ff@numstart{1}%
\fi
\ifnum\@ff@numend>\c@maxflow
  \def\@ff@numend{\c@maxflow}%
\fi
\@colN=\@ff@numstart
\whiledo{\@colN<\@ff@numend \TE@or \@colN=\@ff@numend}{%
\@@staticframeswapcoords{\@colN}%
\advance\@colN by 1\relax
}}}}}
%    \end{macrocode}
%\end{macro}
%
% \subsection{Dynamic Frames}
% Now deal with the \glspl{dynamic}. These are very similar
% to the \glspl{static}, but instead of having a savebox,
% the contents of the \gls{dynamic} are stored in a macro.
%\begin{macro}{\newdynamicframe}
% Syntax:\newline
% \cs{newdynamicframe}\oarg{pages}\marg{width}\marg{height}\marg{x}\marg{y}\oarg{label}
%    \begin{macrocode}
\newcommand*{\newdynamicframe}{%
\@n@wdynamicframe}
\newcommand*{\@n@wdynamicframe}{%
\global\advance\c@maxdynamic by 1\relax
\newboolean{dynamicframe\romannumeral\c@maxdynamic}
\@ifstar\@snewdynamicframe\@newdynamicframe
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@snewdynamicframe}
% Starred version: has a border.
%    \begin{macrocode}
\newcommand*{\@snewdynamicframe}{%
\setboolean{dynamicframe\romannumeral\c@maxdynamic}{true}%
\@@newdynamicframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@newdynamicframe}
% Unstarred version: no border.
%    \begin{macrocode}
\newcommand*{\@newdynamicframe}{%
\setboolean{dynamicframe\romannumeral\c@maxdynamic}{false}%
\@@newdynamicframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@newdynamicframe}
% Create new \gls{dynamic}:
%    \begin{macrocode}
\newcommand*{\@@newdynamicframe}[5][all]{%
\expandafter
\gdef\csname @dynamicframe@\romannumeral\c@maxdynamic\endcsname{}%
\expandafter
\newlength\csname @df@\romannumeral\c@maxdynamic @posx\endcsname
\expandafter
\newlength\csname @df@\romannumeral\c@maxdynamic @posy\endcsname
\expandafter\setlength
\csname @df@\romannumeral\c@maxdynamic @posx\endcsname{#4}%
\expandafter\setlength
\csname @df@\romannumeral\c@maxdynamic @posy\endcsname{#5}%
\expandafter\newlength
\csname @df@\romannumeral\c@maxdynamic @evenx\endcsname
\expandafter\newlength
\csname @df@\romannumeral\c@maxdynamic @eveny\endcsname
\expandafter\setlength
\csname @df@\romannumeral\c@maxdynamic @evenx\endcsname{#4}%
\expandafter\setlength
\csname @df@\romannumeral\c@maxdynamic @eveny\endcsname{#5}%
{\@ff@tmp@x=#2\relax
\@ff@tmp@y=#3\relax
\expandafter
\xdef\csname @df@dim@\romannumeral\c@maxdynamic\endcsname{%
[c][\the\@ff@tmp@y][t]{\the\@ff@tmp@x}}}%
\expandafter
\gdef\csname @df@col@\romannumeral\c@maxdynamic\endcsname{%
\flowframecol}%
\expandafter
\gdef\csname @df@txtcol@\romannumeral\c@maxdynamic\endcsname{%
\flowframetextcol}%
\expandafter
\gdef\csname @df@backcol@\romannumeral\c@maxdynamic\endcsname{%
{none}}%
\expandafter
\gdef\csname @df@pages@\romannumeral\c@maxdynamic\endcsname{#1}%
\expandafter
\gdef\csname @df@frametype@\romannumeral\c@maxdynamic\endcsname{%
fbox}%
\expandafter
\gdef\csname @df@style@\romannumeral\c@maxdynamic\endcsname{relax}%
\expandafter
\gdef\csname @df@offset@\romannumeral\c@maxdynamic\endcsname{compute}%
\expandafter
\gdef\csname @df@angle@\romannumeral\c@maxdynamic\endcsname{0}%
\expandafter
\gdef\csname @df@shape@\romannumeral\c@maxdynamic\endcsname{\relax}%
\newboolean{@df@clear@\romannumeral\c@maxdynamic}%
\setboolean{@df@clear@\romannumeral\c@maxdynamic}{false}%
\@ifnextchar[{\@s@tdynamicframeid{\c@maxdynamic}}%
{\@s@tdynamicframeid{\c@maxdynamic}[\number\c@maxdynamic]}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tdynamicframeid}
% Set the label for the given \gls{dynamic}:
%    \begin{macrocode}
\def\@s@tdynamicframeid#1[#2]{%
\edef\ff@label{#2}%
\@df@checkuniqueidl{#1}{\ff@label}%
\expandafter
\xdef\csname @df@id@\romannumeral#1\endcsname{\ff@label}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@df@checkuniqueidl}
% Check \gls{idl} "#2" for \gls{static} "#1" is unique
%    \begin{macrocode}
\newcommand*{\@df@checkuniqueidl}[2]{%
\@colN=0\relax
\whiledo{\@colN<\c@maxdynamic}{%
\advance\@colN by 1\relax
\ifnum\@colN=#1\relax
\else
\ifthenelse{\equal{#2}%
{\csname @df@id@\romannumeral\@colN\endcsname}}{%
\PackageError{flowfram}{Dynamic frame IDL '#2' already defined}{%
You can't assign this label, as it is already defined
for dynamic frame \number\@colN}}{}%
\fi
}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getdynamiclabel}
%\changes{1.11}{2008/06/27}{new}
%\cs{getdynamiclabel}\marg{idn}
% Gets the \gls{idl} for the \gls{dynamic} identified by its
% \gls{idn}.
%    \begin{macrocode}
\newcommand*{\getdynamiclabel}[1]{%
\csname @df@id@\romannumeral#1\endcsname}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getdynamicid}
%\changes{1.11}{2008/06/27}{new}
%\cs{getdynamicid}\marg{cmd}\marg{idl}
% Gets the \gls{idn} for the \gls{dynamic} identified by its
% \gls{idl} and stores in \meta{cmd} which must be a control
% sequence.
%    \begin{macrocode}
\newcommand*{\getdynamicid}[2]{%
\@dynamicframeid{#2}\edef#1{\number\ff@id}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicframeid}
% Determine the \gls{idn} of the \gls{dynamic} from its label.
% The \gls{idn} is stored in "\ff@id".
%    \begin{macrocode}
\newcommand*{\@dynamicframeid}[1]{\@colN=0\relax
\ff@id=0\relax
\whiledo{\@colN<\c@maxdynamic}{\advance\@colN by 1\relax
\ifthenelse{%
\equal{#1}{\csname @df@id@\romannumeral\@colN\endcsname}}{%
\ff@id=\@colN\relax
% break out of loop
\@colN=\c@maxdynamic}{}}%
\ifnum\ff@id=0\PackageError{flowfram}{Can't find dynamic frame 
id '#1'}{}\fi}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@getframeid}
% \cs{@getframeid}\marg{type}\marg{idl}
%
% Gets the \gls{idl} for the frame of type \meta{type} whose \gls{idl}
% is given by \meta{idl}. The \gls{idn} is stored in "\ff@id".
%    \begin{macrocode}
\newcommand*{\@getframeid}[2]{%
\@ifdefined{@#1frameid}{\csname @#1frameid\endcsname{#2}}{%
\PackageError{flowfram}{Unknown frame type `#1'}{Frame types can
be one of: flow, static or dynamic}}}
%    \end{macrocode}
%\end{macro}
%
% Make it easier to get the x and y values for dynamic
% frames. (Width and height stored differently.)
%\begin{macro}{\dynamicframex}
%    \begin{macrocode}
\newcommand*{\dynamicframex}[1]{%
\csname @df@\romannumeral#1@posx\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicframey}
%    \begin{macrocode}
\newcommand*{\dynamicframey}[1]{%
\csname @df@\romannumeral#1@posy\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicframeevenx}
%    \begin{macrocode}
\newcommand*{\dynamicframeevenx}[1]{%
\csname @df@\romannumeral#1@evenx\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicframeeveny}
%    \begin{macrocode}
\newcommand*{\dynamicframeeveny}[1]{%
\csname @df@\romannumeral#1@eveny\endcsname}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setalldynamicframes}
% Change the settings for all the \glspl{dynamic}:
%    \begin{macrocode}
\newcommand*{\setalldynamicframes}[1]{%
\@colN=0\whiledo{\@colN<\c@maxdynamic}{\advance\@colN by 1\relax
\@@setdynamicframe{\@colN}{#1}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setdynamicframe}
% Change the settings for specified \glspl{dynamic}:
%    \begin{macrocode}
\newcommand*{\setdynamicframe}{%
\@ifstar\@ssetdynamicframe\@setdynamicframe}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ssetdynamicframe}
% Starred version: iterate through comma-separated list
% of labels.
%    \begin{macrocode}
\newcommand*{\@ssetdynamicframe}[2]{%
\@for\@ff@id:=#1\do{%
\@dynamicframeid{\@ff@id}%
\@@setdynamicframe{\ff@id}{#2}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setdynamicframe}
% Unstarred version: iterate through comma-separated list
% of ID numbers. Include provision for number ranges.
% If necessary, modify number ranges to ensure they are valid.
%    \begin{macrocode}
\newcommand*{\@setdynamicframe}[2]{%
\ifthenelse{\equal{#1}{all}}{%
\setalldynamicframes{#2}}{%
\ifthenelse{\equal{#1}{odd} \TE@or \equal{#1}{even}}{%
\ifthenelse{\equal{#1}{odd}}{\@colN=1}{\@colN=2}%
\whiledo{\@colN<\c@maxdynamic\TE@or\@colN=\c@maxdynamic}{%
\@@setdynamicframe{\@colN}{#2}%
\advance\@colN by 2\relax}%
}{%
\@for\@ff@id:=#1\do{%
\def\@ff@numstart{0}\def\@ff@numend{10000}%
\@ff@getrange{\@ff@id}%
\ifnum\@ff@numstart=0\relax
  \def\@ff@numstart{1}%
\fi
\ifnum\@ff@numend>\c@maxdynamic\relax
  \def\@ff@numend{\c@maxdynamic}%
\fi
\@colN=\@ff@numstart\relax
\whiledo{\@colN<\@ff@numend \TE@or \@colN=\@ff@numend}{%
\@@setdynamicframe{\@colN}{#2}%
\advance\@colN by 1\relax
}}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@setdynamicframe}
% Change the setting for the \gls{dynamic} given by its \gls{idn}.
%\changes{1.11}{2008/06/27}{removed unwanted space}
%\changes{1.11}{2008/06/27}{fixed bug in clear key}
%    \begin{macrocode}
\newcommand*{\@@setdynamicframe}[2]{%
\expandafter\expandafter\expandafter
\@ff@getstaticpos\csname @df@dim@\romannumeral#1\endcsname
\def\ff@frame{}\edef\ff@width{\the\@ff@tmp@x}%
\edef\ff@height{\the\@ff@tmp@y}\def\ff@style{}\def\ff@frametype{}%
\def\ff@x{}\def\ff@y{}\def\ff@col{}\def\ff@txtcol{}\def\ff@backcol{}%
\def\ff@clear{}\def\ff@margin{}\def\ff@offset{}\def\ff@pages{}%
\def\ff@label{}\def\ff@evenx{}\def\ff@eveny{}%
\def\ff@oddx{}\def\ff@oddy{}\def\ff@angle{}\def\ff@shape{0}%
\setkeys{flowframe}{#2}%
\ifthenelse{\equal{\ff@frame}{}}{}{%
\setboolean{dynamicframe\romannumeral#1}{\ff@frame}}%
\ifthenelse{\equal{\ff@x}{}}{}{%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@posx\endcsname{\ff@x}%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@evenx\endcsname{\ff@x}}%
\ifthenelse{\equal{\ff@y}{}}{}{%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@posy\endcsname{\ff@y}%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@eveny\endcsname{\ff@y}}%
\ifthenelse{\equal{\ff@evenx}{}}{}{%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@evenx\endcsname{\ff@evenx}}%
\ifthenelse{\equal{\ff@eveny}{}}{}{%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@eveny\endcsname{\ff@eveny}}%
\ifthenelse{\equal{\ff@oddx}{}}{}{%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@posx\endcsname{\ff@oddx}}%
\ifthenelse{\equal{\ff@oddy}{}}{}{%
\expandafter\global\expandafter\setlength
\csname @df@\romannumeral#1@posy\endcsname{\ff@oddy}}%
\expandafter\xdef\csname @df@dim@\romannumeral#1\endcsname{%
[c][\ff@height][\ff@valign]{\ff@width}}%
\ifthenelse{\equal{\ff@label}{}}{}{%
\@s@tdynamicframeid{#1}[\ff@label]}%
\ifthenelse{\equal{\ff@frametype}{}}{}{%
\expandafter
\xdef\csname @df@frametype@\romannumeral#1\endcsname{%
\ff@frametype}}%
\ifthenelse{\equal{\ff@col}{}}{}{%
\expandafter\@setframecol\ff@col\end{#1}{col}{df}}%
\ifthenelse{\equal{\ff@txtcol}{}}{}{%
\expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{df}}%
\ifthenelse{\equal{\ff@backcol}{}}{}{%
\expandafter\@setframecol\ff@backcol\end{#1}{backcol}{df}}%
\ifthenelse{\equal{\ff@offset}{}}{}{%
\expandafter
\xdef\csname @df@offset@\romannumeral#1\endcsname{\ff@offset}}%
\ifthenelse{\equal{\ff@angle}{}}{}{%
\expandafter
\xdef\csname @df@angle@\romannumeral#1\endcsname{\ff@angle}}%
\if0\ff@shape
\else
\expandafter\global\expandafter
\let\csname @df@shape@\romannumeral#1\endcsname\ff@shape
\fi
\ifthenelse{\equal{\ff@pages}{}}{}{%
\expandafter\xdef\csname @df@pages@\romannumeral#1\endcsname{%
\ff@pages}}%
\ifthenelse{\equal{\ff@style}{}}{}{%
\@ifundefined{\ff@style}{\PackageError{flowfram}%
{Unknown style '\ff@style'}{The command \expandafter
\string\csname\ff@style\endcsname\space has not been defined}}{%
\expandafter
\xdef\csname @df@style@\romannumeral#1\endcsname{\ff@style}}}%
\ifthenelse{\equal{\ff@clear}{}}{}{%
\setboolean{@df@clear@\romannumeral#1}{\ff@clear}%
}%
\ifthenelse{\equal{\ff@margin}{}}{}{%
\PackageError{flowfram}{Key 'margin' not available for dynamic 
frames}{dynamic frames don't have marginal notes}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@dynamicframeswapcoords}
% Swap odd and even offsets for a given \gls{static}. Do the main stuff for 
% a given \gls{static} \gls{idn}.
%    \begin{macrocode}
\newcommand*{\@@dynamicframeswapcoords}[1]{%
\setlength{\@ff@tmp@x}%
{\csname @df@\romannumeral#1@evenx\endcsname}%
\expandafter\setlength
\csname @df@\romannumeral#1@evenx\endcsname
{\csname @df@\romannumeral#1@posx\endcsname}%
\expandafter\setlength
\csname @df@\romannumeral#1@posx\endcsname{\@ff@tmp@x}%
\setlength{\@ff@tmp@y}%
{\csname @df@\romannumeral#1@eveny\endcsname}%
\expandafter\setlength
\csname @df@\romannumeral#1@eveny\endcsname
{\csname @df@\romannumeral#1@posy\endcsname}%
\expandafter\setlength\csname @df@\romannumeral#1@posy\endcsname
{\@ff@tmp@y}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dfswapoddeven}
% Allow user to specify \gls{flow} either by \gls{idn} or \gls{idl}:
%    \begin{macrocode}
\newcommand*{\dfswapoddeven}{%
\@ifstar\@sdynamicframeswapcoords\@dynamicframeswapcoords}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sdynamicframeswapcoords}
% Starred form
%    \begin{macrocode}
\newcommand*{\@sdynamicframeswapcoords}[1]{%
\@for\@ff@id:=#1\do{%
\@dynamicframeid{\@ff@id}%
\@@dynamicframeswapcoords{\ff@id}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dynamicframeswapcoords}
% Unstarred form:
%    \begin{macrocode}
\newcommand*{\@dynamicframeswapcoords}[1]{%
\ifthenelse{\equal{#1}{all}}{%
\ff@id=0\relax
\whiledo{\ff@id<\c@maxflow}{\advance\ff@id by 1\relax
\@@dynamicframeswapcoords{\ff@id}}%
}{%
\ifthenelse{\equal{#1}{odd} \TE@or \equal{#1}{even}}{%
\ifthenelse{\equal{#1}{odd}}{\@colN=1}{\@colN=2}%
\whiledo{\@colN<\c@maxflow\TE@or\@colN=\c@maxflow}{%
\@@dynamicframeswapcoords{\@colN}%
\advance\@colN by 2\relax}%
}{%
\@for\@ff@id:=#1\do{%
\def\@ff@numstart{0}\def\@ff@numend{10000}%
\@ff@getrange{\@ff@id}%
\ifnum\@ff@numstart=0\relax
  \def\@ff@numstart{1}%
\fi
\ifnum\@ff@numend>\c@maxflow
  \def\@ff@numend{\c@maxflow}%
\fi
\@colN=\@ff@numstart
\whiledo{\@colN<\@ff@numend \TE@or \@colN=\@ff@numend}{%
\@@dynamicframeswapcoords{\@colN}%
\advance\@colN by 1\relax
}}}}}
%    \end{macrocode}
%\end{macro}
% Set the contents of a \gls{dynamic}.
%
%\begin{environment}{dynamiccontents}
% Syntax: "\begin{dynamiccontents}"\marg{idn}
%
% The contents of the \env{dynamiccontents} environment needs
% to be stored in the control sequence "\@dynamicframe@"\meta{rn}
% (where \meta{rn} is the \meta{idn} as a roman numeral.)
%    \begin{macrocode}
\newenvironment{dynamiccontents}[1]{%
\def\@flf@{dynamiccontents}%
\xdynamiccontents{#1}}{%
\endxdynamiccontents
}
%    \end{macrocode}
%\end{environment}
% Token to store contents of environment:
%    \begin{macrocode}
\newtoks\@dynamictok
%    \end{macrocode}
% Start of the environment (unstarred):
%    \begin{macrocode}
\def\xdynamiccontents#1{%
\def\@flf@idn{#1}%
\@dynamictok{}\@flf@get@body
}
%    \end{macrocode}
% Get the body of the environment:
%    \begin{macrocode}
\long\def\@flf@get@body#1\end{%
\@flf@checkcontinued#1\continueonframe\@nil
\ifdfcontinued
   \expandafter\flf@ta\expandafter{\@flf@tmpa}%
   \edef\@flf@tmp{\the\@dynamictok\the\flf@ta}%
   \@dynamictok\expandafter{\@flf@tmp}%
\else
   \@dynamictok\expandafter{\the\@dynamictok#1}%
\fi
\@flf@find@end}
%    \end{macrocode}
% Check if \cs{continueonframe} has been used.
%    \begin{macrocode}
\newif\ifdfcontinued
\long\def\@flf@checkcontinued#1\continueonframe#2\@nil{%
\long\def\@flf@tmpa{#1}\long\def\@flf@tmpb{#2}%
\ifx\@flf@tmpb\@lempty
  \dfcontinuedfalse
\else
  \dfcontinuedtrue
  \flf@getcontargs#2\@ff@text\@ff@nextid\@ff@rest
\fi
}
%    \end{macrocode}
% Long equivalent of \cs{@empty}:
%    \begin{macrocode}
\long\def\@lempty{}
%    \end{macrocode}
% Get the first optional argument and store in the forth argument
% (which should be a control sequence). Get the second argument and
% store in the fifth argument (which should be a control sequence).
% Get the third argument and
% store in the sixth argument (which should be a control sequence).
%    \begin{macrocode}
\def\flf@getcontargs{%
\@ifnextchar[{\@flf@getcontargs}{\@flf@getcontargs[]}}
%    \end{macrocode}
%    \begin{macrocode}
\long\def\@flf@getcontargs[#1]#2#3\continueonframe#4#5#6{%
\def#4{#1}\def#5{#2}\def#6{#3}%
}
%    \end{macrocode}
% Find the end of the environment:
%    \begin{macrocode}
\def\@flf@find@end#1{%
\def\@tempa{#1}%
\global\let\flf@next=\relax
\ifdfcontinued
  \@dynamictok\expandafter
     {\the\@dynamictok\ffcontinuedtextlayout}%
  \protected@edef\@tmpa{\the\@dynamictok{\@ff@text}}%
  \@dynamictok\expandafter{\@tmpa}%
  \toks@\expandafter{\@ff@rest}%
  \edef\flf@next{\noexpand\@flf@get@body\noexpand\end{#1}%
     \noexpand\begin{#1}{\@ff@nextid}\noexpand\par
     \noexpand\noindent\noexpand\ignorespaces
     \the\toks@\noexpand\end{#1}}%
\else
  \ifx\@tempa\@flf@
    \let\flf@next=\@flf@endxdynamiccontents
  \else
    \@dynamictok\expandafter
      {\the\@dynamictok\end{#1}}%
    \let\flf@next=\@flf@get@body
  \fi
\fi
\flf@next
}
%    \end{macrocode}
% End of the environment:
%    \begin{macrocode}
\let\endxdynamiccontents\relax
\def\@flf@endxdynamiccontents{%
\ifnum\@flf@idn>\c@maxdynamic
  \PackageError{flowfram}{Dynamic frame \number\@flf@idn\ does not exist}{%
  You have specified dynamic frame number \number\@flf@idn, but there are 
  only \number\c@maxdynamic\space dynamic frames currently defined}%
\else
  \expandafter
  \xdef\csname @dynamicframe@\romannumeral\@flf@idn\endcsname{%
     \the\@dynamictok}%
  \expandafter
\fi
\expandafter\end\expandafter{\@flf@}%
}
%    \end{macrocode}
%\begin{environment}{dynamiccontents*}
% Starred version
%    \begin{macrocode}
\newenvironment{dynamiccontents*}[1]{%
\def\@flf@{dynamiccontents*}%
\@dynamicframeid{#1}%
\xdynamiccontents{\ff@id}}{%
\enddynamiccontents
}
%    \end{macrocode}
%\end{environment}
%
%\begin{macro}{\setdynamiccontents}
%    \begin{macrocode}
\newcommand{\setdynamiccontents}{%
\@ifstar\@ssetdynamiccontents\@setdynamiccontents}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ssetdynamiccontents}
% Starred version: identify \gls{dynamic} by its \gls{idl}:
%    \begin{macrocode}
\newcommand{\@ssetdynamiccontents}[2]{%
\@dynamicframeid{#1}\@setdynamiccontents{\ff@id}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setdynamiccontents}
% Unstarred version: identify \gls{dynamic} by its \gls{idn}:
%    \begin{macrocode}
\newcommand{\@setdynamiccontents}[2]{%
\ifnum#1>\c@maxdynamic
\PackageError{flowfram}{Dynamic frame \number#1\ does not exist}{%
You have specified dynamic frame number \number#1, but there are 
only \number\c@maxdynamic\space dynamic frames currently defined}%
\else
\expandafter
\gdef\csname @dynamicframe@\romannumeral#1\endcsname{#2}%
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\appenddynamiccontents}
% Append information to \gls{dynamic}. First check to
% see if starred or unstarred version is being used.
%    \begin{macrocode}
\newcommand{\appenddynamiccontents}{%
\@ifstar\@sappenddynamic\@appenddynamic}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sappenddynamic}
% Starred version: find the \gls{idn} and pass it to
% the unstarred version.
%    \begin{macrocode}
\newcommand{\@sappenddynamic}[2]{%
\@dynamicframeid{#1}\@appenddynamic{\ff@id}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@appenddynamic}
% Unstarred version.
%    \begin{macrocode}
\newcommand{\@appenddynamic}[2]{%
\ifnum#1>\c@maxdynamic
  \PackageError{flowfram}{Dynamic frame \number#1 does not exist}{%
  You have specified dynamic frame number \number#1, 
  but there are only
  \number\c@maxdynamic\space dynamic frames currently defined}%
\else
  \expandafter\@ff@addtolist
  \csname @dynamicframe@\romannumeral#1\endcsname\entry{#2}%
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@addtolist}
% Append "#2" onto the end of "#1".
%    \begin{macrocode}
\newtoks\flf@ta \newtoks\flf@tb
\long\def\@ff@addtolist#1\entry#2{\flf@ta={{#2}}%
\flf@tb=\expandafter{#1}%
\xdef#1{\the\flf@tb\the\flf@ta}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\continueonframe}
% \cs{continueonframe}\oarg{text}\marg{id}
% Ends current \env{staticcontents} or \env{dynamiccontents}
% environment and starts environment of the same type for frame 
% given by \meta{id}. Can only be used inside \env{staticcontents}
% or \env{dynamiccontents} environments. If the starred version of
% the environment is used, \marg{id} refers to the \gls{idl}, otherwise
% it refers to the \gls{idn} of the new frame.
%    \begin{macrocode}
\newcommand{\continueonframe}{\PackageError{flowfram}{Can't continue
to new frame: not in static or dynamic frame}{%
\string\continueonframe\space may only
be used inside `staticcontents' or `dynamiccontents' environments
(of their starred versions)}}
%    \end{macrocode}
%\end{macro}
% \cs{@scontinueonframe} and \cs{@continueonframe} are set
% by \env{staticcontents} and \env{dynamiccontents} environments
% (and their starred forms).
%
% Static starred version uses \gls{idl}
%    \begin{macrocode}
\newcommand*{\@staticscontinueonframe}[2][]{%
\ffcontinuedtextlayout{#1}%
\end{staticcontents*}%
\begin{staticcontents*}{#2}\par\noindent\ignorespaces}
%    \end{macrocode}
% Static unstarred version uses \gls{idn}
%    \begin{macrocode}
\newcommand*{\@staticcontinueonframe}[2][]{%
\ffcontinuedtextlayout{#1}%
\end{staticcontents}%
\begin{staticcontents}{#2}\par\noindent\ignorespaces}
%    \end{macrocode}
%
%\begin{macro}{\ffcontinuedtextlayout}
%Displays the continued text used by \cs{continueonframe}.
%    \begin{macrocode}
\newcommand{\ffcontinuedtextlayout}[1]{%
\parfillskip=0pt\par\hfill\ffcontinuedtextfont{#1}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffcontinuedtextfont}
%Sets the font to display the continuation text used by
%\cs{continueonframe}
%    \begin{macrocode}
\newcommand*{\ffcontinuedtextfont}[1]{\emph{\small #1}}
%    \end{macrocode}
%\end{macro}
%
%\subsection{Determining Dimensions and Locations}
%\begin{macro}{\computeleftedgeodd}
% Compute the position of the left most edge of the page, 
% relative to the left side of the \gls{typeblock}. Since odd and
% even pages may have a different offset if "\oddsidemargin"
% and "\evensidemargin" have different values, it is necessary
% to have two separate commands for odd and even pages.
% First the odd pages.
%    \begin{macrocode}
\newcommand*{\computeleftedgeodd}[1]{%
\setlength{#1}{-1in}%
\addtolength{#1}{-\hoffset}%
\addtolength{#1}{-\oddsidemargin}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computeleftedgeeven}
% Now for the even pages
%    \begin{macrocode}
\newcommand*{\computeleftedgeeven}[1]{%
\setlength{#1}{-1in}%
\addtolength{#1}{-\hoffset}%
\addtolength{#1}{-\evensidemargin}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computetopedge}
% Compute the top edge of the page, relative to the bottom of 
% the \gls{typeblock}.
%    \begin{macrocode}
\newcommand*{\computetopedge}[1]{%
\setlength{#1}{\textheight}%
\addtolength{#1}{\headheight}%
\addtolength{#1}{\headsep}%
\addtolength{#1}{1in}%
\addtolength{#1}{\voffset}%
\addtolength{#1}{\topmargin}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computebottomedge}
% Compute the bottom edge of the page, relative to the bottom 
% of the \gls{typeblock}.
%    \begin{macrocode}
\newcommand*{\computebottomedge}[1]{%
\computetopedge{#1}%
\addtolength{#1}{-\paperheight}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computerightedgeodd}
% Compute the right edge of the page, relative to the left edge 
% of the \gls{typeblock}. Again, two commands are needed for odd
% and even pages. First the odd pages.
%    \begin{macrocode}
\newcommand*{\computerightedgeodd}[1]{%
\computeleftedgeodd{#1}%
\addtolength{#1}{\paperwidth}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computerightedgeeven}
% Now for the even pages.
%    \begin{macrocode}
\newcommand*{\computerightedgeeven}[1]{%
\computeleftedgeeven{#1}%
\addtolength{#1}{\paperwidth}}
%    \end{macrocode}
%\end{macro}
% Compute the minimum area surrounding the listed \glspl{flow}.
% Values stored in "\ffareawidth", "\ffareaheight", "\ffareax"
% and "\ffareay"
%    \begin{macrocode}
\newlength\ffareawidth
\newlength\ffareaheight
\newlength\ffareax
\newlength\ffareay
\newlength\ffareaevenx
\newlength\ffareaeveny
%    \end{macrocode}
%\begin{macro}{\computeflowframearea}
% Starred version identifies frame by \gls{idl}, unstarred
% version identifies frame by \gls{idn}.
%    \begin{macrocode}
\newcommand*{\computeflowframearea}{%
\@ifstar\@scomputeffarea\@computeffarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@scomputeffarea}
% Starred version.
%    \begin{macrocode}
\newcommand*{\@scomputeffarea}[1]{%
\setlength{\ffareax}{\paperwidth}%
\setlength{\ffareay}{\paperheight}%
\setlength{\@ff@tmp@x}{0pt}%
\setlength{\@ff@tmp@y}{0pt}%
\@for\@ff@id:=#1\do{\@flowframeid{\@ff@id}%
%\ff@id is the IDN
\ifnum\ffareax>\flowframex{\ff@id}%
\setlength{\ffareax}{\flowframex{\ff@id}}%
\fi
\ifnum\ffareay>\flowframey{\ff@id}%
\setlength{\ffareay}{\flowframey{\ff@id}}%
\fi
\setlength{\@ff@offset}{\flowframex{\ff@id}}%
\addtolength{@ff@offset}{\flowframewidth{\ff@id}}%
\ifnum\@ff@tmp@x<\@ff@offset
\setlength{\@ff@tmp@x}{\@ff@offset}%
\fi
\setlength{\@ff@offset}{\flowframey{\ff@id}}%
\addtolength{@ff@offset}{\flowframeheight{\ff@id}}%
\ifnum\@ff@tmp@y<\@ff@offset
\setlength{\@ff@tmp@y}{\@ff@offset}%
\fi
}%
\setlength{\ffareawidth}{\@ff@tmp@x}%
\addtolength{\ffareawidth}{-\ffareax}%
\setlength{\ffareaheight}{\@ff@tmp@y}%
\addtolength{\ffareaheight}{-\ffareay}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@computeffarea}
% Unstarred version.
%    \begin{macrocode}
\newcommand*{\@computeffarea}[1]{%
\setlength{\ffareax}{\paperwidth}%
\setlength{\ffareay}{\paperheight}%
\setlength{\@ff@tmp@x}{0pt}%
\setlength{\@ff@tmp@y}{0pt}%
\@for\@ff@id:=#1\do{%
\ff@id=\@ff@id\relax
\setlength{\@ff@offset}{\flowframex{\ff@id}}%
\ifdim\ffareax>\@ff@offset
\setlength{\ffareax}{\@ff@offset}%
\fi
\setlength{\@ff@offset}{\flowframey{\ff@id}}%
\ifdim\ffareay>\@ff@offset
\setlength{\ffareay}{\@ff@offset}%
\fi
\setlength{\@ff@offset}{\flowframex{\ff@id}}%
\addtolength{\@ff@offset}{\flowframewidth{\ff@id}}%
\ifdim\@ff@tmp@x<\@ff@offset
\setlength{\@ff@tmp@x}{\@ff@offset}%
\fi
\setlength{\@ff@offset}{\flowframey{\ff@id}}%
\addtolength{\@ff@offset}{\flowframeheight{\ff@id}}%
\ifdim\@ff@tmp@y<\@ff@offset
\setlength{\@ff@tmp@y}{\@ff@offset}%
\fi
}%
\setlength{\ffareawidth}{\@ff@tmp@x}%
\addtolength{\ffareawidth}{-\ffareax}%
\setlength{\ffareaheight}{\@ff@tmp@y}%
\addtolength{\ffareaheight}{-\ffareay}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@swaplen}
% Swap the values of two lengths
%    \begin{macrocode}
\newcommand*{\@ff@swaplen}[2]{%
\setlength{\@ff@tmp@x}{#1}%
\setlength{#1}{#2}%
\setlength{#2}{\@ff@tmp@x}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@getdim}
% Get the dimensions for the given type of frame.
% The first parameter should be a number indictating
% type of frame : 1 (flow), 2 (static), 3 (dynamic).
% The second number is its \gls{idn}. Values are stored in
% "\ffareax", "\ffareay", "\ffareawidth" and "\ffareaheight".
%    \begin{macrocode}
\newcommand*{\@ff@getdim}[2]{%
\ifnum#2<1\relax
  \PackageError{flowfram}{Frame IDNs start from 1}{%
  You have specified a frame IDN of '\number#2'}%
\fi
\ifcase#1\relax
  \PackageError{flowfram}{Unknown frame ID type '#1'}{%
  Frame ID types are: 1 (flow), 2 (static) and 3 (dynamic)}%
\or 
  \ifnum#2>\c@maxflow\relax
    \PackageError{flowfram}{Invalid flow frame IDN '\number#2'}{%
    Flow frame IDNs go from 1 to \number\c@maxflow}%
  \else
    \setlength{\ffareax}{\flowframex{#2}}%
    \setlength{\ffareay}{\flowframey{#2}}%
    \setlength{\ffareaevenx}{\flowframeevenx{#2}}%
    \setlength{\ffareaeveny}{\flowframeeveny{#2}}%
    \setlength{\ffareawidth}{\flowframewidth{#2}}%
    \setlength{\ffareaheight}{\flowframeheight{#2}}%
  \fi
\or
  \ifnum#2>\c@maxstatic\relax
    \PackageError{flowfram}{Invalid static frame IDN '\number#2'}{%
    Static frame IDNs go from 1 to \number\c@maxstatic}%
  \else
    \setlength{\ffareax}{\staticframex{#2}}%
    \setlength{\ffareay}{\staticframey{#2}}%
    \setlength{\ffareaevenx}{\staticframeevenx{#2}}%
    \setlength{\ffareaeveny}{\staticframeeveny{#2}}%
    \expandafter\expandafter\expandafter
    \@ff@getstaticpos
    \csname @sf@dim@\romannumeral#2\endcsname
    \setlength{\ffareawidth}{\@ff@tmp@x}%
    \setlength{\ffareaheight}{\@ff@tmp@y}%
  \fi
\or 
  \ifnum#2>\c@maxdynamic\relax
    \PackageError{flowfram}{Invalid dynamic frame IDN '\number#2'}{%
    Dynamic frame IDNs go from 1 to \number\c@maxdynamic}%
  \else
    \setlength{\ffareax}{\dynamicframex{#2}}%
    \setlength{\ffareay}{\dynamicframey{#2}}%
    \setlength{\ffareaevenx}{\dynamicframeevenx{#2}}%
    \setlength{\ffareaeveny}{\dynamicframeeveny{#2}}%
    \expandafter\expandafter\expandafter
    \@ff@getstaticpos
    \csname @df@dim@\romannumeral#2\endcsname
    \setlength{\ffareawidth}{\@ff@tmp@x}%
    \setlength{\ffareaheight}{\@ff@tmp@y}%
   \fi
\else
  \PackageError{flowfram}{Unknown frame ID type '#1'}{%
  Frame ID types are: 1 (flow), 2 (static) and 3 (dynamic)}%
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@getevendim}
%\changes{1.11}{2008/06/27}{new}
% Get the dimensions for the given type of frame on even pages.
% The first parameter should be a number indictating
% type of frame : 1 (flow), 2 (static), 3 (dynamic).
% The second number is its \gls{idn}. Values are stored in
% "\ffareax", "\ffareay", "\ffareawidth" and "\ffareaheight".
%    \begin{macrocode}
\newcommand*{\@ff@getevendim}[2]{%
\ifnum#2<1\relax
  \PackageError{flowfram}{Frame IDNs start from 1}{%
  You have specified a frame IDN of '\number#2'}%
\fi
\ifcase#1\relax
  \PackageError{flowfram}{Unknown frame ID type '#1'}{%
  Frame ID types are: 1 (flow), 2 (static) and 3 (dynamic)}
\or 
  \ifnum#2>\c@maxflow
    \PackageError{flowfram}{Invalid flow frame IDN '\number#2'}{%
    Flow frame IDNs go from 1 to \number\c@maxflow}%
  \else
    \setlength{\ffareax}{\flowframeevenx{#2}}%
    \setlength{\ffareay}{\flowframeeveny{#2}}%
    \setlength{\ffareawidth}{\flowframewidth{#2}}%
    \setlength{\ffareaheight}{\flowframeheight{#2}}%
  \fi
\or
  \ifnum#2>\c@maxstatic\relax
    \PackageError{flowfram}{Invalid static frame IDN '\number#2'}{%
    Static frame IDNs go from 1 to \number\c@maxstatic}%
  \else
    \setlength{\ffareax}{\staticframeevenx{#2}}%
    \setlength{\ffareay}{\staticframeeveny{#2}}%
    \expandafter\expandafter\expandafter
    \@ff@getstaticpos
    \csname @sf@dim@\romannumeral#2\endcsname
    \setlength{\ffareawidth}{\@ff@tmp@x}%
    \setlength{\ffareaheight}{\@ff@tmp@y}%
  \fi
\or 
  \ifnum#2>\c@maxdynamic\relax
    \PackageError{flowfram}{Invalid dynamic frame IDN '\number#2'}{%
    Dynamic frame IDNs go from 1 to \number\c@maxdynamic}%
  \else
    \setlength{\ffareax}{\dynamicframeevenx{#2}}%
    \setlength{\ffareay}{\dynamicframeeveny{#2}}%
    \expandafter\expandafter\expandafter
    \@ff@getstaticpos
    \csname @df@dim@\romannumeral#2\endcsname
    \setlength{\ffareawidth}{\@ff@tmp@x}%
    \setlength{\ffareaheight}{\@ff@tmp@y}%
  \fi
\else
  \PackageError{flowfram}{Unknown frame ID type '#1'}{%
  Frame ID types are: 1 (flow), 2 (static) and 3 (dynamic)}
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getstaticbounds}
% Convenience method for calling the above. Firstly for static
% frames:
%    \begin{macrocode}
\newcommand*{\getstaticbounds}{%
\@ifstar\@sgetstaticbounds\@getstaticbounds}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetstaticbounds}
% Starred version (specify by \gls{idl}):
%    \begin{macrocode}
\newcommand*{\@sgetstaticbounds}[1]{%
\@staticframeid{#1}\@getstaticbounds{\ff@id}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@getstaticbounds}
% Unstarred version (specify by \gls{idn}):
%\changes{1.11}{2008/06/27}{fixed bug: changed frame id from
% 1 to 2 (thanks to Lutz Goldmann for pointing it out)}
%    \begin{macrocode}
\newcommand*{\@getstaticbounds}[1]{\@ff@getdim{2}{#1}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getstaticevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Even pages
%    \begin{macrocode}
\newcommand*{\getstaticevenbounds}{%
\@ifstar\@sgetstaticevenbounds\@getstaticevenbounds}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetstaticevenbounds}
% Starred version (specify by \gls{idl}):
%    \begin{macrocode}
\newcommand*{\@sgetstaticevenbounds}[1]{%
\@staticframeid{#1}\@getstaticevenbounds{\ff@id}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@getstaticevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Unstarred version (specify by \gls{idn}):
%    \begin{macrocode}
\newcommand*{\@getstaticevenbounds}[1]{\@ff@getevendim{2}{#1}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getflowbounds}
% Next flow frames:
%    \begin{macrocode}
\newcommand*{\getflowbounds}{%
\@ifstar\@sgetflowbounds\@getflowbounds}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetflowbounds}
% Starred version (specify by \gls{idl}):
%    \begin{macrocode}
\newcommand*{\@sgetflowbounds}[1]{%
\@flowframeid{#1}\@getflowbounds{\ff@id}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@getflowbounds}
% Unstarred version (specify by \gls{idn}):
%\changes{1.11}{2008/06/27}{fixed bug: changed frame id from
% 2 to 1 (thanks to Lutz Goldmann for pointing it out)}
%    \begin{macrocode}
\newcommand*{\@getflowbounds}[1]{\@ff@getdim{1}{#1}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\getflowevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Even pages:
%    \begin{macrocode}
\newcommand*{\getflowevenbounds}{%
\@ifstar\@sgetflowevenbounds\@getflowevenbounds}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetflowevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Starred version (specify by \gls{idl}):
%    \begin{macrocode}
\newcommand*{\@sgetflowevenbounds}[1]{%
\@flowframeid{#1}\@getflowevenbounds{\ff@id}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@getflowevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Unstarred version (specify by \gls{idn}):
%    \begin{macrocode}
\newcommand*{\@getflowevenbounds}[1]{\@ff@getevendim{1}{#1}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getdynamicbounds}
% Next dynamic frames:
%    \begin{macrocode}
\newcommand*{\getdynamicbounds}{%
\@ifstar\@sgetdynamicbounds\@getdynamicbounds}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetdynamicbounds}
% Starred version (specify by \gls{idl}):
%    \begin{macrocode}
\newcommand*{\@sgetdynamicbounds}[1]{%
\@dynamicframeid{#1}\@getdynamicbounds{\ff@id}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@getdynamicbounds}
% Unstarred version (specify by \gls{idn}):
%    \begin{macrocode}
\newcommand*{\@getdynamicbounds}[1]{\@ff@getdim{3}{#1}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getdynamicevenbounds}
% Even pages:
%    \begin{macrocode}
\newcommand*{\getdynamicevenbounds}{%
\@ifstar\@sgetdynamicevenbounds\@getdynamicevenbounds}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetdynamicevenbounds}
% Starred version (specify by \gls{idl}):
%    \begin{macrocode}
\newcommand*{\@sgetdynamicevenbounds}[1]{%
\@dynamicframeid{#1}\@getdynamicevenbounds{\ff@id}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@getdynamicevenbounds}
% Unstarred version (specify by \gls{idn}):
%    \begin{macrocode}
\newcommand*{\@getdynamicevenbounds}[1]{\@ff@getevendim{3}{#1}}
%    \end{macrocode}
%\end{macro}
%
% \subsection{Determining the relative location of one frame from 
% another}
%\changes{1.11}{2008/06/27}{added relative location commands}
% The commands in this section set the following boolean variables:
%    \begin{macrocode}
\newif\ifFLFabove
\newif\ifFLFbelow
\newif\ifFLFleft
\newif\ifFLFright
%    \end{macrocode}
% These can then be used after one of the \cs{checkifframe}\meta{loc}
% commands defined below. For example:
%\begin{verbatim}
%\checkifframeabove{static}{1}{flow}{1}
%\ifFLFabove
%  Static frame is above flow frame.
%\else
%  Static frame isn't above flow frame.
%\fi
%\end{verbatim}
%
%\begin{macro}{\checkifframeabove}
%\changes{1.11}{2008/06/27}{new}
%\cs{checkifframeabove}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
%
% Checks if the first frame is above the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2}. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be above the
% second frame if they overlap. This code checks the page number to
% determine whether to use \cs{oddcheckifframeabove} or
% \cs{evencheckifframeabove} so it should not be used in the
% first paragraph of the first \gls{flow} on the page if the paragraph
% spans the page break.
%    \begin{macrocode}
\newcommand*{\checkifframeabove}{%
\@ifstar\@scheckifframeabove\@checkifframeabove}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@scheckifframeabove}[4]{%
\ifodd\c@page
  \@soddcheckifframeabove{#1}{#2}{#3}{#4}%
\else
  \@sevencheckifframeabove{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@checkifframeabove}[4]{%
\ifodd\c@page
  \@oddcheckifframeabove{#1}{#2}{#3}{#4}%
\else
  \@evencheckifframeabove{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\oddcheckifframeabove}
%\changes{1.11}{2008/06/27}{new}
%\cs{oddcheckifframeabove}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is above the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2} for odd pages. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be above the
% second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\oddcheckifframeabove}{%
\@ifstar\@soddcheckifframeabove\@oddcheckifframeabove}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@soddcheckifframeabove}[4]{%
\@ifundefined{@sget#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1bounds\endcsname{#2}%
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@sget#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3bounds\endcsname{#4}%
\advance\ffareay by \ffareaheight\relax
\expandafter\ifdim\@ff@check>\ffareay
  \FLFabovetrue
\else
  \FLFabovefalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@oddcheckifframeabove}[4]{%
\@ifundefined{@get#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1bounds\endcsname{#2}%
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@get#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3bounds\endcsname{#4}%
\advance\ffareay by \ffareaheight\relax
\expandafter\ifdim\@ff@check>\ffareay
  \FLFabovetrue
\else
  \FLFabovefalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\checkifframebelow}
%\changes{1.11}{2008/06/27}{new}
%\cs{checkifframebelow}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is below the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2}. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be below the
% second frame if they overlap. This code checks the page number to
% determine whether to use \cs{oddcheckifframebelow} or
% \cs{evencheckifframebelow} so it should not be used in the
% first paragraph of the first \gls{flow} on the page if the paragraph
% spans the page break.
%    \begin{macrocode}
\newcommand*{\checkifframebelow}{%
\@ifstar\@scheckifframebelow\@checkifframebelow}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@scheckifframebelow}[4]{%
\ifodd\c@page
  \@soddcheckifframebelow{#1}{#2}{#3}{#4}%
\else
  \@sevencheckifframebelow{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@checkifframebelow}[4]{%
\ifodd\c@page
  \@oddcheckifframebelow{#1}{#2}{#3}{#4}%
\else
  \@evencheckifframebelow{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\oddcheckifframebelow}
%\changes{1.11}{2008/06/27}{new}
%\cs{oddcheckifframebelow}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
%
% Checks if the first frame is below the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2} on odd pages. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be below the
% second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\oddcheckifframebelow}{%
\@ifstar\@soddcheckifframebelow\@oddcheckifframebelow}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@soddcheckifframebelow}[4]{%
\@ifundefined{@sget#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1bounds\endcsname{#2}%
\advance\ffareay by \ffareaheight\relax
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@sget#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3bounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareay
  \FLFbelowtrue
\else
  \FLFbelowfalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@oddcheckifframebelow}[4]{%
\@ifundefined{@get#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1bounds\endcsname{#2}%
\advance\ffareay by \ffareaheight\relax
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@get#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3bounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareay
  \FLFbelowtrue
\else
  \FLFbelowfalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\checkifframeleft}
%\changes{1.11}{2008/06/27}{new}
%\cs{checkifframeleft}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is to the left of the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2}. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be to the 
% left of the second frame if they overlap. This code checks the page number to
% determine whether to use \cs{oddcheckifframeleft} or
% \cs{evencheckifframeleft} so it should not be used in the
% first paragraph of the first \gls{flow} on the page if the paragraph
% spans the page break.
%    \begin{macrocode}
\newcommand*{\checkifframeleft}{%
\@ifstar\@scheckifframeleft\@checkifframeleft}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@scheckifframeleft}[4]{%
\ifodd\c@page
  \@soddcheckifframeleft{#1}{#2}{#3}{#4}%
\else
  \@sevencheckifframeleft{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@checkifframeleft}[4]{%
\ifodd\c@page
  \@oddcheckifframeleft{#1}{#2}{#3}{#4}%
\else
  \@evencheckifframeleft{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\oddcheckifframeleft}
%\changes{1.11}{2008/06/27}{new}
%\cs{oddcheckifframeleft}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
%
% Checks if the first frame is to the left of the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2} on odd pages. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be to the 
% left of the second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\oddcheckifframeleft}{%
\@ifstar\@soddcheckifframeleft\@oddcheckifframeleft}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@soddcheckifframeleft}[4]{%
\@ifundefined{@sget#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1bounds\endcsname{#2}%
\advance\ffareax by \ffareawidth\relax
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@sget#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3bounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareax
  \FLFlefttrue
\else
  \FLFleftfalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@oddcheckifframeleft}[4]{%
\@ifundefined{@get#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1bounds\endcsname{#2}%
\advance\ffareax by \ffareawidth\relax
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@get#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3bounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareax
  \FLFlefttrue
\else
  \FLFleftfalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\checkifframeright}
%\changes{1.11}{2008/06/27}{new}
%\cs{checkifframeright}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is to the right of the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2}. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be to the 
% right of the second frame if they overlap. This code checks the page number to
% determine whether to use \cs{oddcheckifframeright} or
% \cs{evencheckifframeright} so it should not be used in the
% first paragraph of the first \gls{flow} on the page if the paragraph
% spans the page break.
%    \begin{macrocode}
\newcommand*{\checkifframeright}{%
\@ifstar\@scheckifframeright\@checkifframeright}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@scheckifframeright}[4]{%
\ifodd\c@page
  \@soddcheckifframeright{#1}{#2}{#3}{#4}%
\else
  \@sevencheckifframeright{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@checkifframeright}[4]{%
\ifodd\c@page
  \@oddcheckifframeright{#1}{#2}{#3}{#4}%
\else
  \@evencheckifframeright{#1}{#2}{#3}{#4}%
\fi}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\oddcheckifframeright}
%\changes{1.11}{2008/06/27}{new}
%\cs{oddcheckifframeright}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
%
% Checks if the first frame is to the right of the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2} on odd pages. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be to the 
% right of the second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\oddcheckifframeright}{%
\@ifstar\@soddcheckifframeright\@oddcheckifframeright}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@soddcheckifframeright}[4]{%
\@ifundefined{@sget#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1bounds\endcsname{#2}%
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@sget#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3bounds\endcsname{#4}%
\advance\ffareax by \ffareawidth\relax
\expandafter\ifdim\@ff@check>\ffareax
  \FLFrighttrue
\else
  \FLFrightfalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@oddcheckifframeright}[4]{%
\@ifundefined{@get#1bounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1bounds\endcsname{#2}%
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@get#3bounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3bounds\endcsname{#4}%
\advance\ffareax by \ffareawidth\relax
\expandafter\ifdim\@ff@check>\ffareax
  \FLFrighttrue
\else
  \FLFrightfalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframeabove}
%\changes{1.11}{2008/06/27}{new}
%\cs{evencheckifframeabove}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is above the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2} for even pages. 
% The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be above the
% second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\evencheckifframeabove}{%
\@ifstar\@sevencheckifframeabove\@evencheckifframeabove}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@sevencheckifframeabove}[4]{%
\@ifundefined{@sget#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1evenbounds\endcsname{#2}%
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@sget#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3evenbounds\endcsname{#4}%
\advance\ffareay by \ffareaheight\relax
\expandafter\ifdim\@ff@check>\ffareay
  \FLFabovetrue
\else
  \FLFabovefalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@evencheckifframeabove}[4]{%
\@ifundefined{@get#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1evenbounds\endcsname{#2}%
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@get#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3evenbounds\endcsname{#4}%
\advance\ffareay by \ffareaheight\relax
\expandafter\ifdim\@ff@check>\ffareay
  \FLFabovetrue
\else
  \FLFabovefalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframebelow}
%\changes{1.11}{2008/06/27}{new}
%\cs{checkifframebelow}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is below the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2}. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be below the
% second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\evencheckifframebelow}{%
\@ifstar\@sevencheckifframebelow\@evencheckifframebelow}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@sevencheckifframebelow}[4]{%
\@ifundefined{@sget#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1evenbounds\endcsname{#2}%
\advance\ffareay by \ffareaheight\relax
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@sget#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3evenbounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareay
  \FLFbelowtrue
\else
  \FLFbelowfalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@evencheckifframebelow}[4]{%
\@ifundefined{@get#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1evenbounds\endcsname{#2}%
\advance\ffareay by \ffareaheight\relax
\edef\@ff@check{\the\ffareay}%
\@ifundefined{@get#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3evenbounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareay
  \FLFbelowtrue
\else
  \FLFbelowfalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframeleft}
%\changes{1.11}{2008/06/27}{new}
%\cs{evencheckifframeleft}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is to the left of the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2}. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be to the 
% left of the second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\evencheckifframeleft}{%
\@ifstar\@sevencheckifframeleft\@evencheckifframeleft}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@sevencheckifframeleft}[4]{%
\@ifundefined{@sget#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1evenbounds\endcsname{#2}%
\advance\ffareax by \ffareawidth\relax
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@sget#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3evenbounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareax
  \FLFlefttrue
\else
  \FLFleftfalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@evencheckifframeleft}[4]{%
\@ifundefined{@get#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1evenbounds\endcsname{#2}%
\advance\ffareax by \ffareawidth\relax
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@get#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3evenbounds\endcsname{#4}%
\expandafter\ifdim\@ff@check<\ffareax
  \FLFlefttrue
\else
  \FLFleftfalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframeright}
%\changes{1.11}{2008/06/27}{new}
%\cs{evencheckifframeright}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Checks if the first frame is to the right of the second frame where the
% first frame is of type \meta{type1} with \gls{idn} given by 
% \meta{id1} and the second frame is of type \meta{type2} with \gls{idn}
% given by \meta{id2}. The starred version uses the \gls{idl} instead
% of the \gls{idn}. The first frame is not considered to be to the 
% right of the second frame if they overlap.
%    \begin{macrocode}
\newcommand*{\evencheckifframeright}{%
\@ifstar\@sevencheckifframeright\@evencheckifframeright}
%    \end{macrocode}
% The starred version
%    \begin{macrocode}
\newcommand*{\@sevencheckifframeright}[4]{%
\@ifundefined{@sget#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#1evenbounds\endcsname{#2}%
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@sget#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @sget#3evenbounds\endcsname{#4}%
\advance\ffareax by \ffareawidth\relax
\expandafter\ifdim\@ff@check>\ffareax
  \FLFrighttrue
\else
  \FLFrightfalse
\fi
}
%    \end{macrocode}
% The unstarred version
%    \begin{macrocode}
\newcommand*{\@evencheckifframeright}[4]{%
\@ifundefined{@get#1evenbounds}{\PackageError{flowfram}{Unknown frame
type `#1'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#1evenbounds\endcsname{#2}%
\edef\@ff@check{\the\ffareax}%
\@ifundefined{@get#3evenbounds}{\PackageError{flowfram}{Unknown frame
type `#3'}{Frame types may only be one of: static, dynamic or
flow}}{}%
\csname @get#3evenbounds\endcsname{#4}%
\advance\ffareax by \ffareawidth\relax
\expandafter\ifdim\@ff@check>\ffareax
  \FLFrighttrue
\else
  \FLFrightfalse
\fi
}
%    \end{macrocode}
%\end{macro}
%
% Textual labels used to indicate relative location of one frame
% to another.
%\begin{macro}{\FFaboveleft}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFaboveleft}{above left}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFaboveright}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFaboveright}{above right}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFbelowleft}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFbelowleft}{below left}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFbelowright}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFbelowright}{below right}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFleft}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFleft}{on the left}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFbelowright}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFright}{on the right}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFabove}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFabove}{above}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFbelow}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFbelow}{below}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FFoverlap}
%\changes{1.11}{2008/06/27}{new}
%    \begin{macrocode}
\newcommand*{\FFoverlap}{overlap}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\relativeframelocation}
%\changes{1.11}{2008/06/27}{new}
%\cs{relativeframelocation}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
% Displays one of the above commands depending on the relative
% locations of the first frame to the second frame. The arguments
% \meta{id1} and \meta{id2} refer to the \gls{idn} for the unstarred
% version and to the \gls{idl} for the starred version.
%    \begin{macrocode}
\DeclareRobustCommand*{\relativeframelocation}{%
\@ifstar\@srelativeframelocation\@relativeframelocation}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@srelativeframelocation}[4]{%
\@scheckifframeabove{#1}{#2}{#3}{#4}%
\@scheckifframebelow{#1}{#2}{#3}{#4}%
\@scheckifframeleft{#1}{#2}{#3}{#4}%
\@scheckifframeright{#1}{#2}{#3}{#4}%
\ifFLFabove
  \ifFLFleft
    \FFaboveleft
  \else
    \ifFLFright
      \FFaboveright
    \else
       \FFabove
    \fi
  \fi 
\else
  \ifFLFbelow
    \ifFLFleft
      \FFbelowleft
    \else
      \ifFLFright
        \FFbelowright
      \else
         \FFbelow
      \fi
    \fi 
  \else
    \ifFLFleft
      \FFleft
    \else
      \ifFLFright
        \FFright
      \else
         \FFoverlap
      \fi
    \fi 
  \fi
\fi
}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@relativeframelocation}[4]{%
\@checkifframeabove{#1}{#2}{#3}{#4}%
\@checkifframebelow{#1}{#2}{#3}{#4}%
\@checkifframeleft{#1}{#2}{#3}{#4}%
\@checkifframeright{#1}{#2}{#3}{#4}%
\ifFLFabove
  \ifFLFleft
    \FFaboveleft
  \else
    \ifFLFright
      \FFaboveright
    \else
       \FFabove
    \fi
  \fi 
\else
  \ifFLFbelow
    \ifFLFleft
      \FFbelowleft
    \else
      \ifFLFright
        \FFbelowright
      \else
         \FFbelow
      \fi
    \fi 
  \else
    \ifFLFleft
      \FFleft
    \else
      \ifFLFright
        \FFright
      \else
         \FFoverlap
      \fi
    \fi 
  \fi
\fi
}
%    \end{macrocode}
%\end{macro}
%
% Short cut commands for \glspl{frame} of the same type.
%\begin{macro}{\reldynamicloc}
%\changes{1.11}{2008/06/27}{new}
%\cs{reldynamicloc}\marg{id1}\marg{id2}
%    \begin{macrocode}
\DeclareRobustCommand*{\reldynamicloc}{%
\@ifstar\@sreldynamicloc\@reldynamicloc}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@sreldynamicloc}[2]{
\@srelativeframelocation{dynamic}{#1}{dynamic}{#2}}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@reldynamicloc}[2]{
\@relativeframelocation{dynamic}{#1}{dynamic}{#2}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\relstaticloc}
%\changes{1.11}{2008/06/27}{new}
%\cs{relstaticloc}\marg{id1}\marg{id2}
%    \begin{macrocode}
\DeclareRobustCommand*{\relstaticloc}{%
\@ifstar\@srelstaticloc\@relstaticloc}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@srelstaticloc}[2]{
\@srelativeframelocation{static}{#1}{static}{#2}}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@relstaticloc}[2]{
\@relativeframelocation{static}{#1}{static}{#2}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\relflowloc}
%\changes{1.11}{2008/06/27}{new}
%\cs{relflowloc}\marg{id1}\marg{id2}
%    \begin{macrocode}
\DeclareRobustCommand*{\relflowloc}{%
\@ifstar\@srelflowloc\@relflowloc}
%    \end{macrocode}
% Starred version:
%    \begin{macrocode}
\newcommand*{\@srelflowloc}[2]{
\@srelativeframelocation{flow}{#1}{flow}{#2}}
%    \end{macrocode}
% Unstarred version:
%    \begin{macrocode}
\newcommand*{\@relflowloc}[2]{
\@relativeframelocation{flow}{#1}{flow}{#2}}
%    \end{macrocode}
%\end{macro}
%
%\subsection{Initialise Flow Frames}
%\begin{macro}{\setinitialframe}
% Specify initial frame. This should be the first flow 
% frame that is defined on the first page of the document.
% Having another \gls{flow} as the initial frame is not
% a good idea, and may have unexpected results.
%    \begin{macrocode}
\newcommand*{\setinitialframe}[1]{\c@thisframe=#1%
\global\usedframebreaktrue
\global\setlength{\hsize}{%
\csname colwidth\romannumeral\c@thisframe\endcsname}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setframes}
% Set the initial frame.
%    \begin{macrocode}
\newif\if@setfr@mes
\@setfr@mesfalse
\newcommand*{\setframes}{%
\ifnum\c@thisframe=0\relax
\PackageWarning{flowfram}{Can't find a flow frame on page 1.
\MessageBreak
Attempting to find the first page with a flow frame}%
\@nxtcol=1\relax
\c@curpg=1\relax
\@g@tnextcol{\@nxtcol}%
%    \end{macrocode}
% shipout pages without flow frames
%    \begin{macrocode}
\advance\c@curpg by -1\relax
  \whiledo{\c@curpg>0}{\advance\c@curpg by -1\relax
  \setbox\@outputbox\vbox{\hbox to \textwidth{\@ff@do@allframes}}%
\@outputpage}%
\c@thisframe=\@nxtcol
\fi
\@setcol{\c@thisframe}\relax
\@setfr@mestrue
\edef\ff@txtcol{%
\csname @ff@txtcol@\romannumeral\c@thisframe\endcsname}%
\@s@tfftextcol
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\emulatetwocolumn}
% Emulate original "\twocolumn" declaration.
% This is provided for backward compatibilty, and
% may be removed in later versions.
%    \begin{macrocode}
\newcommand{\emulatetwocolumn}[1][]{%
\finishthispage
\setallflowframes{pages=none}%
\settoheight{\@ff@staticH}{#1}%
\settodepth{\@ff@tmp@y}{#1}%
\addtolength{\@ff@staticH}{\@ff@tmp@y}%
\ifdim\@ff@staticH>0pt\relax
\twocolumnStop[\c@page]{\@ff@staticH}%
\c@thisframe=\c@maxflow
\advance\c@thisframe by -1\relax
\@twocolumn[>\c@page]%
\setstaticcontents{\c@maxstatic}{#1}%
\else
\@twocolumn
\c@thisframe=\c@maxflow
\advance\c@thisframe by -1\relax
\fi
\@setcol{\c@thisframe}\relax
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\emulateonecolumn}
% Emulate original "\onecolumn" declaration.
% This is provided for backward compatibilty, and
% may be removed in later versions.
%    \begin{macrocode}
\newcommand{\emulateonecolumn}[1][]{%
\finishthispage
\setallflowframes{pages=none}%
\settoheight{\@ff@staticH}{#1}%
\settodepth{\@ff@tmp@y}{#1}%
\addtolength{\@ff@staticH}{\@ff@tmp@y}%
\ifdim\@ff@staticH>0pt\relax
\onecolumnStop[\c@page]{\@ff@staticH}%
\c@thisframe=\c@maxflow
\advance\c@thisframe by -1\relax
\@onecolumn[>\c@page]%
\setstaticcontents{\c@maxstatic}{#1}%
\else
\@twocolumn
\c@thisframe=\c@maxflow
\advance\c@thisframe by -1\relax
\fi
\@setcol{\c@thisframe}\relax
}
%    \end{macrocode}
%\end{macro}
% If no flow frames have been defined, create one big one
% the size of the \gls{typeblock}, and initialise the frames.
%    \begin{macrocode}
\AtBeginDocument{%
\ifnum\c@maxflow=0\relax
\PackageWarning{flowfram}{No flow frames, adding one}%
\@onecolumn
\fi
\setframes
\renewcommand{\onecolumn}[1][]{\PackageWarning{flowfram}{%
Ignoring \string\onecolumn\space found in document environment.
Frames must be defined in the preamble}#1}%
\renewcommand{\twocolumn}[1][]{\PackageWarning{flowfram}{%
Ignoring \string\twocolumn\space found in document environment.
Frames must be defined in the preamble}#1}%
}
%    \end{macrocode}
% If the document finishes before the last frame on the last
% page, need to finish off to ensure the final page is
% shipped out, otherwise the text on the last page will be lost.  
%    \begin{macrocode}
%\AtEndDocument{\finishthispage}
%    \end{macrocode}
%\subsection{Output Routine}
%\begin{macro}{\@setcol}
% Set up the output box so it has the correct dimensions for
% specified \gls{flow}. This is used by the output routine.
%\changes{1.11}{2008/06/27}{added displayedframe increment}
%    \begin{macrocode}
\newcommand{\@setcol}[1]{%
\ifnum\c@maxflow<#1\relax
  \PackageError{flowfram}{Can't set frame '\number#1', doesn't
  exist}{}%
\else
  \expandafter\global\expandafter\columnwidth
  \csname colwidth\romannumeral#1\endcsname
  \ifdim\hsize=\columnwidth
  \else
    \ifusedframebreak
    \else
      \PackageWarning{flowfram}{Moving to flow frame of unequal
      width,\MessageBreak use of \string\framebreak\space advised, 
      or text might not appear correctly}%
    \fi
  \fi
  \global\usedframebreakfalse
  \global\hsize\columnwidth
  \expandafter\global
  \expandafter\vsize\csname colheight\romannumeral#1\endcsname
  \global\@colht\vsize
  \global\@colroom\@colht
  \global\linewidth\columnwidth
  \setmargin
\fi
\stepcounter{displayedframe}%
}
%    \end{macrocode}
%\end{macro}
% Modify the output routine so that it uses "\vsize"
% instead of "\textheight". 
%    \begin{macrocode}
\output={\let\par\@@par
\ifnum\outputpenalty <-\@M
  \@specialoutput
\else
  \@makecol
  \@opcol \@startcolumn
  \@whilesw \if@fcolmade \fi {\@opcol \@startcolumn }%
\fi
\ifnum\outputpenalty>-\@Miv
  \ifdim\@colroom<1.5\baselineskip
    \ifdim\@colroom<\vsize
      \@latex@warning@no@line{Text page \thepage \space 
      contains only floats}\@emptycol
    \else
      \global\vsize\@colroom
    \fi
  \else
    \global\vsize\@colroom
  \fi
\else
  \global\vsize\maxdimen
\fi
}
%    \end{macrocode}
%\begin{macro}{\@doclearpage}
% Modify "\@doclearpage", again replace "\textheight"
% with "\vsize", and only use the twocolumn stuff.
%    \begin{macrocode}
\def\@doclearpage{%
\ifvoid\footins
  \setbox\@tempboxa\vsplit\@cclv to\z@
  \unvbox\@tempboxa
  \setbox\@tempboxa\box\@cclv
  \xdef\@deferlist{\@toplist\@botlist\@deferlist}%
\global\let\@toplist\@empty
\global\let\@botlist\@empty
\global\@colroom\@colht
  \ifx\@currlist\@empty
  \else
    \@latexerr{Float(s) lost}\@ehb
    \global\let\@currlist\@empty
  \fi
  \@makefcolumn
  \@deferlist
  \@whilesw \if@fcolmade \fi {\@opcol
     \@makefcolumn
     \@deferlist}%
\if@firstcolumn
     \xdef\@dbldeferlist{\@dbltoplist\@dbldeferlist}%
\global\let\@dbltoplist\@empty
\global\@colht\vsize
\begingroup
  \@dblfloatplacement
  \@makefcolumn
  \@dbldeferlist
  \@whilesw \if@fcolmade \fi {\@outputpage
\@makefcolumn\@dbldeferlist}%
\endgroup
\else
  \vbox{}\clearpage
\fi
\else
  \setbox\@cclv\vbox{\box\@cclv\vfil}%
\@makecol\@opcol\clearpage\fi}
%    \end{macrocode}
%\end{macro}
% Modify "\@outputpage" slightly. Add provision for
% turning headers and footers into \glspl{dynamic}.
%
%\begin{macro}{\@dothehead}
% First define macro to do the header. This will be
% modified if it is turned into a \gls{dynamic}.
%    \begin{macrocode}
\newcommand{\@dothehead}{\vbox to \headheight{%
\color@hbox\normalcolor\hbox to \textwidth{%
\@thehead}\color@endbox}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dothefoot}
% Same again for the footer.
%    \begin{macrocode}
\newcommand{\@dothefoot}{%
\color@hbox\normalcolor\hbox to \textwidth{%
\@thefoot}\color@endbox}
\newcommand{\@dodynamicthehead}{}
\newcommand{\@dodynamicthefoot}{}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@outputpage}
% Now for the modified version of "\@outputpage". The 
% page style stuff has been moved to "\@outputdblcol"
% so that the headers and footers can be set in \glspl{dynamic}
% before the \glspl{dynamic} are put on the page.
%    \begin{macrocode}
\def\@outputpage{%
\begingroup
  \let\protect\noexpand
  \@resetactivechars
  \global\let\@@if@newlist\if@newlist
  \global\@newlistfalse\@parboxrestore
  \shipout\vbox{\set@typeset@protect
    \aftergroup
    \endgroup
    \aftergroup
    \set@typeset@protect
    \reset@font\normalsize\normalsfcodes
    \let\label\@gobble
    \let\index\@gobble
    \let\glossary\@gobble
    \baselineskip\z@skip
    \lineskip\z@skip
    \lineskiplimit\z@
    \vskip\topmargin\moveright\@themargin
    \vbox{%
      \vskip\headheight
      \vskip\headsep
      \box\@outputbox
    }}%
  \global\let\if@newlist\@@if@newlist
  \stepcounter{page}%
  \setcounter{displayedframe}{0}%
  \let\firstmark\botmark}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\makedfheaderfooter}
% Make the headers and footers be in \glspl{dynamic}. There
% will initially be no difference in appearance until
% the settings are changed using "\setdynamicframe".
% The header frame is given the \gls{idl} "header", and the
% footer is given the \gls{idl} "footer".
%    \begin{macrocode}
\newcommand*{\makedfheaderfooter}{%
% create dynamic frames at the standard location
\setlength{\@ff@tmp@y}{\textheight}%
\addtolength{\@ff@tmp@y}{\headsep}%
\newdynamicframe{\textwidth}{\headheight}{0pt}{\@ff@tmp@y}[header]%
\newdynamicframe{\textwidth}{\headheight}{0pt}{-\footskip}[footer]%
\renewcommand{\@dothehead}{}%
\renewcommand{\@dothefoot}{}%
\renewcommand{\@dodynamicthehead}{%
\@dynamicframeid{header}%
\expandafter
\def\csname @dynamicframe@\romannumeral\ff@id\endcsname{%
\vfill\@thehead\vfill}%
}%
\renewcommand{\@dodynamicthefoot}{%
\@dynamicframeid{footer}%
\expandafter
\def\csname @dynamicframe@\romannumeral\ff@id\endcsname{%
\vfill\@thefoot\vfill}%
}%
}
%    \end{macrocode}
%\end{macro}
% This should only be done in the preamble.
%    \begin{macrocode}
\@onlypreamble{\makedfheaderfooter}
%    \end{macrocode}
%\begin{macro}{\footnotecolor}
% Set footnotes in "\footnotecolor" rather than "\normalcolor"
% This ensures that the footnotes appear in the same colour
% as the text colour for the \gls{flow} to which they belong.
%    \begin{macrocode}
\newcommand{\footnotecolor}{%
\@ifundefined{@ff@txtcol@\romannumeral\c@thisframe}{%
\normalcolor}{%
\edef\ff@txtcol{%
\csname @ff@txtcol@\romannumeral\c@thisframe\endcsname}%
\@s@tfftextcol}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makecol}
% Modify "\@makecol" so that the footnotes, and the 
% footnote rule are in the colour for that frame.
%    \begin{macrocode}
\renewcommand{\@makecol}{%
\ifvoid\footins 
  \setbox\@outputbox\box\@cclv 
\else 
  \setbox\@outputbox\vbox{%
\boxmaxdepth\@maxdepth\@tempdima\dp\@cclv 
    \unvbox\@cclv 
    \vskip\skip\footins 
    \color@begingroup 
      \footnotecolor 
      \footnoterule 
      \unvbox\footins 
    \color@endgroup 
}\fi 
\xdef\@freelist{\@freelist \@midlist }%
\global\let\@midlist\@empty 
\@combinefloats 
\ifvbox\@kludgeins 
  \@makespecialcolbox 
\else 
  \setbox\@outputbox\vbox to\@colht{%
\@texttop\dimen@\dp\@outputbox 
  \unvbox \@outputbox
  \vskip -\dimen@\@textbottom 
}\fi 
\global\maxdepth\@maxdepth}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@opcol}
% Modify "\@opcol", as "\if@twocolumn" is now
% irrelevant.
%    \begin{macrocode}
\def\@opcol{\@outputdblcol
\global\@mparbottom\z@
\global\@textfloatsheight\z@
\@floatplacement
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checkifmoreframes}
% Check to see if there are more \glspl{flow} defined, and
% set "\if@ff@moreframes" as appropriate. This involves
% iterating through all \glspl{flow}, and through each 
% frame's \gls{pglist}.
%    \begin{macrocode}
\newif\if@ff@moreframes
\newcommand*{\@ff@checkifmoreframes}{%
\@ff@moreframesfalse
\@colN=\c@thisframe
\whiledo{\@colN<\c@maxflow}{%
\advance\@colN by 1\relax
\edef\ff@pages{\csname @ff@pages@\romannumeral\@colN\endcsname}%
\@ff@checkpages{\ff@pages}%
}%
\if@ff@moreframes
\else
\@ff@tmpN=\c@page
\advance\@ff@tmpN by 1\relax
\@colN=0\relax
\whiledo{\@colN<\c@thisframe}{%
\advance\@colN by 1\relax
\edef\ff@pages{\csname @ff@pages@\romannumeral\@colN\endcsname}%
\@ff@checkpages[\@ff@tmpN]{\ff@pages}%
}%
\fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checkpages}
% Check to see if the current page lies in the \gls{pglist}
% given by "#1".
%    \begin{macrocode}
\newcommand*{\@ff@checkpages}[2][\c@page]{%
\@for\@ff@pp:=#2\do{%
\@ff@checkthispage{#1}{\@ff@pp}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checkthispage}
% Check to see if the current page lies in the \gls{pgrange}
% given by "#1". If the \gls{pgrange} is specified by
% "all", "odd" or "even" then there are definitely more
% frames available, otherwise check to see if the current page 
% lies within the number range. If the \gls{pgrange} is "none", 
% ignore it.
%    \begin{macrocode}
\newcommand*{\@ff@checkthispage}[2]{%
\ifthenelse{\equal{#2}{all}\or\equal{#2}{even}\or\equal{#2}{odd}}{%
\@ff@moreframestrue}{%
\ifthenelse{\equal{#2}{none}}{}{%
\@ff@checknumrange{#1}{#2}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checknumrange}
% The number range could be a single number, a closed range
% (e.g.\ "2-6") or an open range (e,g.\ "<4" or ">10").
% Use "\@ff@getrange" to find the start and end ranges.
% For open ended ranges assume a maximum value of 10000.
% If the current page is less than or equal to the maximum, 
% there are still more \glspl{flow} available.
%    \begin{macrocode}
\newcommand*{\@ff@checknumrange}[2]{%
\def\@ff@numstart{0}\def\@ff@numend{10000}%
\@ff@getrange{#2}%
\ifnum\@ff@numend>#1\relax
\@ff@moreframestrue
\else
\ifnum\@ff@numend=#1\relax
\@ff@moreframestrue
\fi
\fi
}
%    \end{macrocode}
%\end{macro}
% Work out the minimum and maximum values of a number range
% which could either be a single number, a closed number
% range or an open number range. If the first character
% is "<" or ">" then it is an open range, otherwise it is
% a closed range or a single number. Define a counter
% to use whilst determining the range.
%    \begin{macrocode}
\newcount\c@ffrangenum
%    \end{macrocode}
%\begin{macro}{\@ff@getrange}
% Now to find out what kind of range it is. If it is a single
% number, e.g.\ "24", then it will do, e.g.\ 
% "\@ff@@getrange24-\relax".
% If it is a closed range, e.g. "30-40", it will do , e.g.\ 
% "\@ff@@getrange30-40-\relax". If it is an open range, e.g.\ 
% ">25", it will do, e.g.\ "\@ff@@getrange>25-\relax".
%    \begin{macrocode}
\newcommand*{\@ff@getrange}[1]{%
\expandafter\@ff@@getrange#1-\relax\end}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@@getrange}
% The ranges can now be picked out. If the first character
% is a "<" or ">" it is an open ended range, otherwise it
% is either a single value, or a close ended range.
%    \begin{macrocode}
\def\@ff@@getrange#1#2\end{%
\ifx#1<\relax
 \@ff@getrangeless#1#2\end
\else
  \ifx#1>\relax
    \@ff@getrangegreater#1#2\end
  \else
    \@@ff@getrange#1#2\end
  \fi
\fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@getrangeless}
% Get the values for an open ended range with an
% upper bound. A minimum value of "0" is assumed.
%    \begin{macrocode}
\def\@ff@getrangeless<#1-\relax\end{%
\c@ffrangenum=#1\relax
\advance\c@ffrangenum by -1\relax
\def\@ff@numstart{0}%
\edef\@ff@numend{\number\c@ffrangenum}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@getrangegreater}
% Get the values for an open ended range with a lower
% bound. A maximum value of "10000" is assumed.
%    \begin{macrocode}
\def\@ff@getrangegreater>#1-\relax\end{%
\c@ffrangenum=#1\relax
\advance\c@ffrangenum by 1\relax
\edef\@ff@numstart{\number\c@ffrangenum}%
\def\@ff@numend{10000}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@ff@getrange}
% Determine whether we have a single number or
% a closed range. If "#2" is "\relax", it is a single
% value, otherwise it is a range.
%    \begin{macrocode}
\def\@@ff@getrange#1-#2\end{%
\ifx\relax#2\relax
\def\@ff@numstart{#1}\def\@ff@numend{#1}%
\else
\def\@ff@numstart{#1}%
\@@@ff@getrange#2\end
\fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@@ff@getrange}
% Extract the end value from the closed range.
%    \begin{macrocode}
\def\@@@ff@getrange#1-\relax\end{%
\def\@ff@numend{#1}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@g@tnextcol}
% Find the next \gls{flow}. If there are no more flow
% frames, define a new one the size of the \gls{typeblock}.
% (Otherwise the remaining document text will be lost.)
%    \begin{macrocode}
\newif\if@notthiscol
\newif\if@ff@nwpg
\newcount\c@curpg
\newcommand*{\@g@tnextcol}[1]{%
\@ff@checkifmoreframes
\if@ff@moreframes
\else
% No more frames, add new frame
\PackageWarning{flowfram}{Run out of flows frames, 
adding new one}%
\@onecolumn
#1=\c@maxflow
\fi
\@notthiscoltrue
\@ff@nwpgfalse
\@colN=#1\relax
\c@curpg=\c@page
\loop
\ifnum\@colN=\c@maxflow
 \@colN=1\@ff@nwpgtrue
 \advance\c@curpg by 1\relax
\else
 \advance\@colN by 1\relax
\fi
\@ff@chckifthispg{\c@curpg}{\@colN}%
\if@notthiscol
\repeat
#1=\@colN
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@chckifthispg}
% This is used to determine the next \gls{flow}, since not
% all \glspl{flow} may be defined on every page. Checks to
% see if \gls{flow} "#2" is defined on page "#1".
% First set up some variables.
%    \begin{macrocode}
\newcommand*{\@ff@chckifthispg}[2]{%
\@notthiscoltrue
\edef\ff@pages{\csname @ff@pages@\romannumeral#2\endcsname}%
\@@ff@chckifthispg{#1}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@ff@chckifthispg}
% Now go ahead and check.
%    \begin{macrocode}
\newcommand*{\@@ff@chckifthispg}[1]{%
\ifthenelse{\equal{\ff@pages}{none}}{}{%
\ifthenelse{\equal{\ff@pages}{all}}{\@notthiscolfalse}{%
\ifthenelse{\equal{\ff@pages}{odd}}{%
\ifodd#1\@notthiscolfalse\fi}{%
\ifthenelse{\equal{\ff@pages}{even}}{%
\ifodd#1\else\@notthiscolfalse\fi}{%
% check through list of page numbers
\@for\@ff@pp:=\ff@pages\do{%
\def\@ff@numstart{0}\def\@ff@numend{0}%
\@ff@getrange{\@ff@pp}%
\ifthenelse{#1<\@ff@numstart \or #1>\@ff@numend}{}{%
\@notthiscolfalse}%
}%
}}}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sf@chckifthispg}
% Checks to see if \gls{static} "#1" is defined on the
% current page.
%    \begin{macrocode}
\newcommand*{\@sf@chckifthispg}[1]{%
\@notthiscoltrue
\edef\ff@pages{\csname @sf@pages@\romannumeral#1\endcsname}%
\@@ff@chckifthispg{\c@page}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@df@chckifthispg}
% Checks to see if \gls{dynamic} "#1" is defined on the
% current page.
%    \begin{macrocode}
\newcommand*{\@df@chckifthispg}[1]{%
\@notthiscoltrue
\edef\ff@pages{\csname @df@pages@\romannumeral#1\endcsname}%
\@@ff@chckifthispg{\c@page}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setcolbox}
% Sets the \TeX\ box defining the \gls{flow} to the output
% box. This saves the output until the page is shipped out after
% all the \glspl{flow} have been filled for that page.
%    \begin{macrocode}
\newcommand*{\@setcolbox}[1]{%
\expandafter\global\expandafter\setbox
\csname column\romannumeral#1\endcsname\box\@outputbox
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@docolbox}
% Put \gls{flow} on the page with the correct border, if it
% has one.
%    \begin{macrocode}
\newcommand*{\@docolbox}[1]{%
\edef\ff@frametype{%
\csname @ff@frametype@\romannumeral#1\endcsname}%
\edef\ff@col{\csname @ff@col@\romannumeral#1\endcsname}%
\edef\ff@txtcol{\csname @ff@txtcol@\romannumeral#1\endcsname}%
\edef\ff@backcol{\csname @ff@backcol@\romannumeral#1\endcsname}%
\@ff@setoffset{#1}%
\rotateframe{\csname @ff@angle@\romannumeral#1\endcsname}{%
\ifthenelse{\boolean{columnframe\romannumeral#1}}{%
\@ff@fbox{\csname colwidth\romannumeral#1\endcsname}%
{\csname colheight\romannumeral#1\endcsname}{%
\expandafter\box\csname column\romannumeral#1\endcsname}{%
\csname\ff@frametype\endcsname}%
}{%
\@ff@box{\csname colwidth\romannumeral#1\endcsname}%
{\csname colheight\romannumeral#1\endcsname}{%
\expandafter\box\csname column\romannumeral#1\endcsname}%
}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@docolbbox}
% Do the \gls{bbox} for given \gls{flow}.
%    \begin{macrocode}
\newcommand*{\@docolbbox}[1]{%
\@ff@setoffset{#1}%
\def\ff@col{}\def\ff@txtcol{}%
\@fr@meifdraft{%
\@ff@box{\csname colwidth\romannumeral#1\endcsname}%
{\csname colheight\romannumeral#1\endcsname}{%
\expandafter\box\csname column\romannumeral#1\endcsname}}%
{F:\number#1;\csname @col@id@\romannumeral#1\endcsname}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@fbox}
% Put the \TeX\ box "#3" of width "#1" and
% height "#2", and frame making command
% specified by "#4".
%    \begin{macrocode}
\newcommand{\@ff@fbox}[4]{{%
\fboxsep=\flowframesep\fboxrule=\flowframerule\@s@tffcol 
\kern\@ff@offset
#4{\@ff@box{#1}{#2}{#3}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@box}
% Put the \TeX\ box "#3" of width "#1" and height "#2" on
% the page.
%    \begin{macrocode}
\newcommand{\@ff@box}[3]{{\@ffbackground{\vbox to#2
{\hb@xt@ #1{\hss{\@s@tfftextcol #3}\hss}\vss\kern\z@}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putcolbox}
% Display the \gls{flow} on the page, at its given position.
% If the document is two-sided, need to check whether
% the current page is odd or even to determine the correct
% location.
%    \begin{macrocode}
\newcommand*{\@putcolbox}[1]{%
\@ff@chckifthispg{\c@page}{#1}%
\if@notthiscol
\else
\@killglue
\if@twoside
\ifodd\c@page
\expandafter\raise\csname col@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname col@\romannumeral#1@posx\endcsname
\@docolbox{#1}\hss}%
\else
\expandafter\raise\csname col@\romannumeral#1@eveny\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname col@\romannumeral#1@evenx\endcsname
\@docolbox{#1}\hss}%
\fi
\else
\expandafter\raise\csname col@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname col@\romannumeral#1@posx\endcsname
\@docolbox{#1}\hss}%
\fi
\fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putcolbbox}
% Same for \gls{flow} \gls{bbox}:
%    \begin{macrocode}
\newcommand*{\@putcolbbox}[1]{%
\@ff@chckifthispg{\c@page}{#1}%
\if@notthiscol
\else
\@killglue
\if@twoside
\ifodd\c@page
\expandafter\raise\csname col@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname col@\romannumeral#1@posx\endcsname
\@docolbbox{#1}\hss}%
\else
\expandafter\raise\csname col@\romannumeral#1@eveny\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname col@\romannumeral#1@evenx\endcsname
\@docolbbox{#1}\hss}%
\fi
\else
\expandafter\raise\csname col@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname col@\romannumeral#1@posx\endcsname
\@docolbbox{#1}\hss}%
\fi
\fi
}
%    \end{macrocode}
%\end{macro}
% If an offset hasn't been specified, compute it.  If the 
% frame making command is known (e.g. doublebox), compute
% the offset according to known specifications, otherwise
% set the negative offset to "\flowframesep" plus 
% "\flowframerule", which may or may not be correct.
%
%\begin{macro}{\@ff@s@t@doubleboxoffset}
% Compute offset for "\doublebox":
%    \begin{macrocode}
\newcommand*{\@ff@s@t@doubleboxoffset}{%
\setlength{\@ff@offset}{-\flowframesep}%
\addtolength{\@ff@offset}{-3.75\flowframerule}%
\addtolength{\@ff@offset}{-.5pt}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@s@t@ovalboxoffset}
% Compute offset for "\ovalbox":
%    \begin{macrocode}
\newcommand*{\@ff@s@t@ovalboxoffset}{%
\@ff@offset=-\fontdimen 8\tenln\relax
\advance\@ff@offset by -\flowframesep\relax
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@s@t@Ovalboxoffset}
% Compute offset for "\ovalbox":
%    \begin{macrocode}
\newcommand*{\@ff@s@t@Ovalboxoffset}{%
\@ff@offset=-\fontdimen 8\tenlnw\relax
\advance\@ff@offset by -\flowframesep\relax
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@s@t@defaultoffset}
% Compute default offset:
%    \begin{macrocode}
\newcommand*{\@ff@s@t@defaultoffset}{%
\@ff@offset=-\flowframesep\relax
\addtolength{\@ff@offset}{-\flowframerule}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@setoffset}
% Compute offset for \gls{flow} "#1". Stores offset value
% in "\ff@offset".
%    \begin{macrocode}
\newcommand*{\@ff@setoffset}[1]{%
\ifthenelse{\equal{\csname @ff@offset@\romannumeral#1\endcsname}%
{compute}}{%
\ifthenelse{\boolean{columnframe\romannumeral#1}}{%
\ifthenelse{%
\equal{\csname @ff@frametype@\romannumeral#1\endcsname}%
{doublebox}}{%
\@ff@s@t@doubleboxoffset
}{%
\ifthenelse{%
\equal{\csname @ff@frametype@\romannumeral#1\endcsname}%
{ovalbox}}{%
\@ff@s@t@ovalboxoffset
}{%
\ifthenelse{%
\equal{\csname @ff@frametype@\romannumeral#1\endcsname}%
{Ovalbox}}{%
\@ff@s@t@Ovalboxoffset}{%
\@ff@s@t@defaultoffset
}}}%
}{}%
}{%
\setlength{\@ff@offset}%
{\csname @ff@offset@\romannumeral#1\endcsname}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sf@setoffset}
% Compute offset for \gls{static} "#1". Stores offset value
% in "\ff@offset".
%    \begin{macrocode}
\newcommand*{\@sf@setoffset}[1]{%
\ifthenelse{%
\equal{\csname @sf@offset@\romannumeral#1\endcsname}%
{compute}}{%
\ifthenelse{\boolean{staticframe\romannumeral#1}}{%
\ifthenelse{%
\equal{\csname @sf@frametype@\romannumeral#1\endcsname}%
{doublebox}}{%
\@ff@s@t@doubleboxoffset
}{%
\ifthenelse{%
\equal{\csname @sf@frametype@\romannumeral#1\endcsname}%
{ovalbox}}{%
\@ff@s@t@ovalboxoffset
}{%
\ifthenelse{%
\equal{\csname @sf@frametype@\romannumeral#1\endcsname}%
{Ovalbox}}{%
\@ff@s@t@Ovalboxoffset
}{%
\@ff@s@t@defaultoffset
}}}%
}{}%
}{%
\setlength{\@ff@offset}%
{\csname @sf@offset@\romannumeral#1\endcsname}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@df@setoffset}
% Compute offset for \gls{dynamic} "#1". Stores offset value
% in "\ff@offset".
%    \begin{macrocode}
\newcommand*{\@df@setoffset}[1]{%
\ifthenelse{%
\equal{\csname @df@offset@\romannumeral#1\endcsname}%
{compute}}{%
\setlength{\@ff@offset}{0pt}%
\ifthenelse{\boolean{dynamicframe\romannumeral#1}}{%
\ifthenelse{%
\equal{\csname @df@frametype@\romannumeral#1\endcsname}%
{doublebox}}{%
\@ff@s@t@doubleboxoffset
}{%
\ifthenelse{%
\equal{\csname @df@frametype@\romannumeral#1\endcsname}%
{ovalbox}}{%
\@ff@s@t@ovalboxoffset
}{%
\ifthenelse{%
\equal{\csname @df@frametype@\romannumeral#1\endcsname}%
{Ovalbox}}{%
\@ff@s@t@Ovalboxoffset}{%
\@ff@s@t@defaultoffset
}}}%
}{}%
}{%
\setlength{\@ff@offset}%
{\csname @df@offset@\romannumeral#1\endcsname}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putmarginbox}
% Draw box representing the margin for \gls{flow} "#1".
%    \begin{macrocode}
\newcommand*{\@putmarginbox}[1]{%
\@ff@chckifthispg{\c@page}{#1}%
\if@notthiscol
\else
\@killglue
\if@twoside
\ifodd\c@page
\edef\ff@x{\csname col@\romannumeral#1@posx\endcsname}%
\edef\ff@y{\csname col@\romannumeral#1@posy\endcsname}%
\else
\edef\ff@x{\csname col@\romannumeral#1@evenx\endcsname}%
\edef\ff@y{\csname col@\romannumeral#1@eveny\endcsname}%
\fi
\else
\edef\ff@x{\csname col@\romannumeral#1@posx\endcsname}%
\edef\ff@y{\csname col@\romannumeral#1@posy\endcsname}%
\fi
\setlength{\@ff@tmp@x}{\ff@x}%
\setlength{\@ff@tmp@y}{\ff@y}%
\@getmarginpos{\csname @ff@margin@\romannumeral#1\endcsname}%
\ifthenelse{\equal{\ff@margin}{left}}{%
\addtolength{\@ff@tmp@x}{-\marginparwidth}%
\addtolength{\@ff@tmp@x}{-\marginparsep}%
\ifthenelse{\boolean{columnframe\romannumeral#1}}{%
}{}%
}{%
\addtolength{\@ff@tmp@x}%
{\csname colwidth\romannumeral#1\endcsname}%
\addtolength{\@ff@tmp@x}{\marginparsep}%
\ifthenelse{\boolean{columnframe\romannumeral#1}}{%
}{}%
}%
\raise\@ff@tmp@y
\hb@xt@\z@{%
\expandafter\kern\@ff@tmp@x
\@fr@meifdraft{\@ff@box{\marginparwidth}%
{\csname colheight\romannumeral#1\endcsname}{}}%
{M:\number#1}\hss}\fi
\ignorespaces}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@drawmargins}
% Draw all the margins associated with the \glspl{flow} defined
% on the current page.
%    \begin{macrocode}
\newcommand*{\@ff@drawmargins}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxflow}{%
\advance\@colN by 1\relax
\makebox[0pt][l]{\@putmarginbox{\@colN}}%
}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@getstaticpos}
% Extract the width and height for static or \gls{dynamic}
% specified in the form \oarg{c}\oarg{height}\oarg{valign}\marg{width}
%    \begin{macrocode}
\def\@ff@getstaticpos[#1][#2][#3]#4{\@ff@tmp@x=#4\relax
\@ff@tmp@y=#2\relax
\def\ff@valign{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dostaticbox}
% Display the savebox associated with \gls{static} "#1"
%    \begin{macrocode}
\newcommand*{\@dostaticbox}[1]{%
\edef\ff@frametype{%
\csname @sf@frametype@\romannumeral#1\endcsname}%
\edef\ff@col{\csname @sf@col@\romannumeral#1\endcsname}%
\edef\ff@backcol{\csname @sf@backcol@\romannumeral#1\endcsname}%
\@sf@setoffset{#1}%
\expandafter\expandafter\expandafter
\@ff@getstaticpos\csname @sf@dim@\romannumeral#1\endcsname
\rotateframe{\csname @sf@angle@\romannumeral#1\endcsname}{%
\ifthenelse{\boolean{staticframe\romannumeral#1}}{%
\@ff@fbox{\@ff@tmp@x}{\@ff@tmp@y}{%
\expandafter\usebox\csname @staticframe@\romannumeral#1\endcsname}
{\csname\ff@frametype\endcsname}%
}{%
\@ff@box{\@ff@tmp@x}{\@ff@tmp@y}%
{\expandafter\usebox\csname @staticframe@\romannumeral#1\endcsname}%
}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dostaticbbox}
% Now for the \gls{bbox}:
%    \begin{macrocode}
\newcommand*{\@dostaticbbox}[1]{%
\edef\ff@col{}%
\@sf@setoffset{#1}%
\expandafter\expandafter\expandafter
\@ff@getstaticpos\csname @sf@dim@\romannumeral#1\endcsname
\@fr@meifdraft{%
\@ff@box{\@ff@tmp@x}{\@ff@tmp@y}%
{\expandafter\usebox\csname @staticframe@\romannumeral#1\endcsname}%
}{S:\number#1;\csname @sf@id@\romannumeral#1\endcsname}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putstaticbox}
% Put the static box "#1" at its given position, with its
% associated border.
%    \begin{macrocode}
\newcommand*{\@putstaticbox}[1]{%
\@sf@chckifthispg{#1}%
\if@notthiscol\else
\@killglue
\if@twoside
\ifodd\c@page
\expandafter\raise\csname @sf@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @sf@\romannumeral#1@posx\endcsname
\@dostaticbox{#1}\hss}%
\else
\expandafter\raise\csname @sf@\romannumeral#1@eveny\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @sf@\romannumeral#1@evenx\endcsname
\@dostaticbox{#1}\hss}%
\fi
\else
\expandafter\raise\csname @sf@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @sf@\romannumeral#1@posx\endcsname
\@dostaticbox{#1}\hss}%
\fi
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putstaticbbox}
% Now for the \gls{bbox}:
%    \begin{macrocode}
\newcommand*{\@putstaticbbox}[1]{%
\@sf@chckifthispg{#1}%
\if@notthiscol\else
\@killglue
\if@twoside
\ifodd\c@page
\expandafter\raise\csname @sf@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @sf@\romannumeral#1@posx\endcsname
\@dostaticbbox{#1}\hss}\ignorespaces
\else
\expandafter\raise\csname @sf@\romannumeral#1@eveny\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @sf@\romannumeral#1@evenx\endcsname
\@dostaticbbox{#1}\hss}\ignorespaces
\fi
\else
\expandafter\raise\csname @sf@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @sf@\romannumeral#1@posx\endcsname
\@dostaticbbox{#1}\hss}\ignorespaces
\fi
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@resetst@tics}
% Clear the contents of all the \glspl{static} that have
% the "clear" option set.
%    \begin{macrocode}
\newcommand*{\@resetst@tics}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxstatic}{\advance\@colN by 1\relax
\ifthenelse{\boolean{@sf@clear@\romannumeral\@colN}}{%
\global\sbox{%
\csname @staticframe@\romannumeral\@colN\endcsname}{}}{}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@resetdyn@mics}
% Clear the contents of the \glspl{dynamic} that have the "clear" option
% set.
%    \begin{macrocode}
\newcommand*{\@resetdyn@mics}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxdynamic}{\advance\@colN by 1\relax
\ifthenelse{\boolean{@df@clear@\romannumeral\@colN}}{%
\expandafter\global\expandafter
\gdef\csname @dynamicframe@\romannumeral\@colN\endcsname{}}{}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dodfparbox}
% Display contents of dynamic box (contents stored in
% "\ff@contents", style given by "\ff@style"):
%    \begin{macrocode}
\newcommand*{\@dodfparbox}[1]{%
\expandafter\let\expandafter
\@ff@parshape\csname @df@shape@\romannumeral#1\endcsname
\expandafter\@ff@getshape\@ff@parshape\relax
\ifcase\ff@shape
% no shape
\expandafter\expandafter\expandafter
\parbox\csname @df@dim@\romannumeral#1\endcsname
{%
\setlength\parindent\sdfparindent
\csname\ff@style\endcsname{\ff@contents}}%
\or
% \parshape
\expandafter\expandafter\expandafter
\parbox\csname @df@dim@\romannumeral#1\endcsname
{%
\setlength\parindent\sdfparindent
\csname\ff@style\endcsname{{%
\let\oldpar=\par
\let\par=\ffpshpar
\@ff@setsecthead
\@ff@parshape
\ff@contents\oldpar}}}%
\or
% \shapepar
\expandafter\expandafter\expandafter
\parbox\csname @df@dim@\romannumeral#1\endcsname
{%
\setlength\parindent\sdfparindent
\csname\ff@style\endcsname{{\@ff@disablesec\@ff@parshape
\ff@contents\par}}}%
\fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dodynamicbox}
% Typeset the dynamic box with its associated border.
%    \begin{macrocode}
\newcommand*{\@dodynamicbox}[1]{%
\edef\ff@frametype{%
\csname @df@frametype@\romannumeral#1\endcsname}%
\edef\ff@col{\csname @df@col@\romannumeral#1\endcsname}%
\edef\ff@txtcol{\csname @df@txtcol@\romannumeral#1\endcsname}%
\edef\ff@backcol{\csname @df@backcol@\romannumeral#1\endcsname}%
\edef\ff@style{\csname @df@style@\romannumeral#1\endcsname}%
\def\ff@contents{\csname @dynamicframe@\romannumeral#1\endcsname}%
\@df@setoffset{#1}%
\expandafter\expandafter\expandafter
\@ff@getstaticpos\csname @df@dim@\romannumeral#1\endcsname
\rotateframe{\csname @df@angle@\romannumeral#1\endcsname}{%
\ifthenelse{\boolean{dynamicframe\romannumeral#1}}{%
\@ff@fbox{\@ff@tmp@x}{\@ff@tmp@y}%
{\@dodfparbox{#1}}%
{\csname\ff@frametype\endcsname}%
}{%
\@ff@box{\@ff@tmp@x}{\@ff@tmp@y}{%
\@dodfparbox{#1}}%
}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dodynamicbbox}
% Now for the \gls{bbox}:
%    \begin{macrocode}
\newcommand*{\@dodynamicbbox}[1]{%
\edef\ff@col{}%
\@df@setoffset{#1}%
\expandafter\expandafter\expandafter
\@ff@getstaticpos\csname @df@dim@\romannumeral#1\endcsname
\@fr@meifdraft{%
\@ff@box{\@ff@tmp@x}{\@ff@tmp@y}{%
\expandafter\expandafter\expandafter
\parbox\csname @df@dim@\romannumeral#1\endcsname
{}}%
}{D:\number#1;\csname @df@id@\romannumeral#1\endcsname}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putdynamicbox}
% Put the \gls{dynamic} "#1" at its given position
%    \begin{macrocode}
\newcommand*{\@putdynamicbox}[1]{%
\@df@chckifthispg{#1}%
\if@notthiscol\else
\@killglue
\if@twoside
\ifodd\c@page
\expandafter\raise\csname @df@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @df@\romannumeral#1@posx\endcsname
\@dodynamicbox{#1}\hss}\ignorespaces
\else
\expandafter\raise\csname @df@\romannumeral#1@eveny\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @df@\romannumeral#1@evenx\endcsname
\@dodynamicbox{#1}\hss}\ignorespaces
\fi
\else
\expandafter\raise\csname @df@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @df@\romannumeral#1@posx\endcsname
\@dodynamicbox{#1}\hss}\ignorespaces
\fi
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putdynamicbbox}
% Bounding box:
%    \begin{macrocode}
\newcommand*{\@putdynamicbbox}[1]{%
\@df@chckifthispg{#1}%
\if@notthiscol\else
\@killglue
\if@twoside
\ifodd\c@page
\expandafter\raise\csname @df@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @df@\romannumeral#1@posx\endcsname
\@dodynamicbbox{#1}\hss}\ignorespaces
\else
\expandafter\raise\csname @df@\romannumeral#1@eveny\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @df@\romannumeral#1@evenx\endcsname
\@dodynamicbbox{#1}\hss}\ignorespaces
\fi
\else
\expandafter\raise\csname @df@\romannumeral#1@posy\endcsname
\hb@xt@\z@{%
\expandafter\kern \csname @df@\romannumeral#1@posx\endcsname
\@dodynamicbbox{#1}\hss}\ignorespaces
\fi
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@doheader}
% Do standard header in the standard place.
%    \begin{macrocode}
\newcommand*{\@@doheader}{%
\setlength\@ff@tmp@y{\textheight}%
\addtolength{\@ff@tmp@y}{\headsep}%
\def\ff@col{}%
\def\ff@txtcol{}%
\def\ff@backcol{{none}}%
\@ff@box{0pt}{\@ff@tmp@y}{\makebox[0pt][l]{\@dothehead}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@dofooter}
% Do standard footer in the standard place.
%    \begin{macrocode}
\newcommand*{\@@dofooter}{%
\setlength\@ff@tmp@y{-\footskip}%
\def\ff@col{}%
\def\ff@txtcol{}%
\def\ff@backcol{{none}}%
\@ff@box{0pt}{\@ff@tmp@y}{\makebox[0pt][l]{\@dothefoot}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tfr@mes}
% This is a modified version of the way the picture environment 
% works:
%    \begin{macrocode}
\newcommand{\@s@tfr@mes}[1]{{\@picht\textheight
\setbox\@picbox\hb@xt@ \textwidth 
\bgroup \hbox \bgroup #1\relax
\egroup
\hss \egroup 
\ht\@picbox\@picht \dp\@picbox 
\z@ \mbox{\box \@picbox}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doallflowframes}
% Puts all the \glspl{flow} defined on the current page
%    \begin{macrocode}
\newcommand*{\@ff@doallflowframes}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxflow}{\advance\@colN by 1\relax
\@putcolbox{\@colN}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doallflowframesbbox}
% Flow frame \glspl{bbox}:
%    \begin{macrocode}
\newcommand*{\@ff@doallflowframesbbox}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxflow}{\advance\@colN by 1\relax
\@putcolbbox{\@colN}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doallstatics}
% Puts all \glspl{static} defined on the current page
%    \begin{macrocode}
\newcommand*{\@ff@doallstatics}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxstatic}{\advance\@colN by 1\relax
\@putstaticbox{\@colN}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doallstaticsbbox}
% Static frame \glspl{bbox}:
%    \begin{macrocode}
\newcommand*{\@ff@doallstaticsbbox}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxstatic}{\advance\@colN by 1\relax
\@putstaticbbox{\@colN}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doalldynamics}
% Puts all the \glspl{dynamic} defined on the current page
%    \begin{macrocode}
\newcommand*{\@ff@doalldynamics}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxdynamic}{\advance\@colN by 1\relax
\@putdynamicbox{\@colN}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doalldynamicsbbox}
% Dynamic frame \glspl{bbox}:
%    \begin{macrocode}
\newcommand*{\@ff@doalldynamicsbbox}{%
\@colN=0\relax
\whiledo{\@colN<\c@maxdynamic}{\advance\@colN by 1\relax
\@putdynamicbbox{\@colN}}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@dotypeblock}
% Draw \gls{typeblock} frame if draft.
%    \begin{macrocode}
\newcommand*{\@ff@dotypeblock}{%
\makebox[0pt][l]{\@fr@meifdraft[\setffdrafttypeblockcolor]{%
\vbox to \textheight{\hbox to \textwidth{}}}{}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@do@allframes}
% Put all frames defined on the current page.
%    \begin{macrocode}
\newlength\ffevenoffset
\newcommand*{\@ff@do@allframes}{%
\ffevenoffset=0pt\relax
\if@twoside
  \ifodd\c@page
  \else
    \ffevenoffset=-\oddsidemargin\relax
    \advance\ffevenoffset by \evensidemargin\relax
    \kern\ffevenoffset\relax
  \fi
\fi
\setlength{\@ff@tmp@x}{\textwidth}%
\advance\@ff@tmp@x by -\ffevenoffset\relax
\makebox[\@ff@tmp@x][l]{%
\@s@tfr@mes{%
\@ff@doallstatics
\@@doheader
\@@dofooter
\@ff@doallflowframes
\@ff@doalldynamics
\ifshowtypeblock
  \@ff@dotypeblock
\fi
\ifshowframebbox
  \@ff@doallstaticsbbox
  \@ff@doallflowframesbbox
  \@ff@doalldynamicsbbox
\fi
\ifshowmargins
  \@ff@drawmargins
\fi
}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@outputdblcol}
% This was modified from the output routine for standard
% two column format. After "\@g@tnextcol", the register
% "\c@curpg" contains the page that the next \gls{flow}
% is on. If "\c@curpg" minus "\c@page" is greater
% than 1, then there is at least one page without a \gls{flow}.
% These pages will have to be shipped before \TeX\ can
% continue with the rest of the document.
%    \begin{macrocode}
\newcount\@nxtcol
\def\@outputdblcol{%
\@nxtcol=\c@thisframe
\c@curpg=\c@page
\@g@tnextcol{\@nxtcol}%
\if@ff@nwpg % next flow frame starts on new page
  \global\@firstcolumntrue
  \@setcolbox\c@thisframe
  \if@specialpage
    \global\@specialpagefalse
    \@nameuse{ps@\@specialstyle}\relax
  \fi
  \if@twoside
    \ifodd\count\z@
      \let\@thehead\@oddhead
      \let\@thefoot\@oddfoot
    \else
      \let\@thehead\@evenhead
      \let\@thefoot\@evenfoot
    \fi
  \else
    \let\@thehead\@oddhead
    \let\@thefoot\@oddfoot
  \fi
  \@begindvi
  \@dodynamicthehead\@dodynamicthefoot
  \vbadness=\@M
  \setbox\@outputbox\vbox{\hbox to \textwidth{\@ff@do@allframes}}%
  \@combinedblfloats
  \@outputpage
%shipout pages without flow frames
\advance\c@curpg by -\c@page\relax
  \whiledo{\c@curpg>0}{\advance\c@curpg by -1\relax
  \setbox\@outputbox\vbox{\hbox to \textwidth{\@ff@do@allframes}}%
\@outputpage} 
  \begingroup
    \@dblfloatplacement
    \@startdblcolumn
    \@whilesw \if@fcolmade \fi
       {\@outputpage \@startdblcolumn }\endgroup
  \@resetst@tics
  \@resetdyn@mics
\else % still on same page, save contents of box255
  \global\@firstcolumnfalse
  \@setcolbox\c@thisframe
\fi
\global\c@thisframe=\@nxtcol
\@setcol{\c@thisframe}\relax
\global\@colht\vsize
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dblfloatplacement}
% Modify "\@dblfloatplacement" replacing "\textheight"
% with "\vsize".
%    \begin{macrocode}
\def\@dblfloatplacement{%
  \global\@dbltopnum\c@dbltopnumber
  \global\@dbltoproom\dbltopfraction\@colht\@textmin
  \@colht\advance\@textmin -\@dbltoproom
  \@fpmin\dblfloatpagefraction\vsize
  \@fptop \@dblfptop \@fpsep \@dblfpsep \@fpbot \@dblfpbot}
%    \end{macrocode}
%\end{macro}
%
%\subsection{Static versions of floats}
% Floats can not go in saveboxes or minipages, so define
% static versions to go in static and \glspl{dynamic}.
% These just set "\@captype" so that the "\caption"
% command may be used.
%\begin{environment}{statictable}
%    \begin{macrocode}
\newenvironment{statictable}{\def\@captype{table}}{}
%    \end{macrocode}
%\end{environment}
%\begin{environment}{staticfigure}
%    \begin{macrocode}
\newenvironment{staticfigure}{\def\@captype{figure}}{}
%    \end{macrocode}
%\end{environment}
%
%\subsection{Standard Layouts}
%\subsubsection{Column Styles}
% Redefine "\twocolumn" and "\onecolumn" to set up \glspl{flow} from
% the dimensions of the \gls{typeblock}. Ignore the optional argument.
% The \gls{flow} height will be adjusted to make sure that it
% is an integer multiple of "\baselineskip", unless
% "\ffvajdustfalse" is used. 
%    \begin{macrocode}
\newif\ifffvadjust
\ffvadjusttrue
%    \end{macrocode}
%\begin{macro}{\onecolumn}
% "\onecolumn" will make a single \gls{flow} that takes
% up the entire area of the \gls{typeblock} (adjusted according
% to "\ifffvadjust".) Frames should only be created in 
% the preamble, otherwise the next \gls{flow} may not
% be detected by the output routine. The exception to this
% is when the output routine can't find any more \glspl{flow}
% to use, in which case it creates a single \gls{flow} using
% "\@onecolumn". Therefore, make "\onecolumn" use "\@onecolumn",
% and then set "\onecolumn" as a preamble command, so it
% can't be used in the document, but the output routine can
% use "\@onecolumn". Syntax: \cs{onecolumn}\oarg{pages}, 
% where \meta{pages} is the \gls{pglist} for which the new
% \gls{flow} is defined.
%    \begin{macrocode}
\renewcommand*{\onecolumn}{\@onecolumn}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@onecolumn}
%    \begin{macrocode}
\newcommand*{\@onecolumn}[1][all]{%
\@onecolumninarea[#1]{\textwidth}{\textheight}{0pt}{0pt}}
%    \end{macrocode}
%\end{macro}
% Need a length to store the height of
% the \gls{flow} so that it can be adjusted.
%    \begin{macrocode}
\newlength\columnheight
%    \end{macrocode}
%\begin{macro}{\onecolumninarea}
% "\onecolumn" is in fact a special case of "\onecolumninarea"
% which sets up one \gls{flow} in the specified area, given
% by bottom left corner (\meta{x}, \meta{y}),
% relative to the \gls{typeblock}, with width \meta{w} 
% and height \meta{h}.
% The only difference between "\onecolumninarea" and
% explicitly creating the \gls{flow} using "\newflowframe"
% is the "\onecolumninarea" will adjust the vertical height
% the ensure it is a multiple of "\baselineskip". There
% is also no starred version, so if you want a border, you
% will need to set it explicitly using "\setflowframe". 
% Syntax:\newline
% \cs{onecolumninarea}\oarg{pages}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\onecolumninarea}{\@onecolumninarea}
\@onlypreamble{\onecolumninarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@onecolumninarea}
%    \begin{macrocode}
\newcommand*{\@onecolumninarea}[5][all]{%
\setlength{\columnheight}{#3}%
\ifffvadjust\adjustheight{\columnheight}\fi%
\@n@wflowframe[#1]{#2}{\columnheight}{#4}{#5}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumn}
% Set up two \glspl{flow} parallel to each other
% with a distance of "\columnsep" between them, to
% fill the entire \gls{typeblock} (although the frames may
% end up marginally shorter than "\textheight" after
% they have been adjusted.) Again, these commands may only
% be used in the preamble. Note that unlike the standard
% "\twocolumn" command, this one has an optional argument
% that indicates which pages the two \glspl{flow} should
% appear on. Syntax: \cs{twocolumn}\oarg{pages}.
%    \begin{macrocode}
\renewcommand*{\twocolumn}{\@twocolumn}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@twocolumn}
%    \begin{macrocode}
\newcommand*{\@twocolumn}[1][all]{%
\@twocolumninarea[#1]{\textwidth}{\textheight}{0pt}{0pt}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumninarea}
% Again, "\twocolumn" is actually a special case of
% "\twocolumninarea".
% Syntax:\newline
% \cs{twocolumninarea}\oarg{pages}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\twocolumninarea}{\@twocolumninarea}
\@onlypreamble{\twocolumninarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@twocolumninarea}
%    \begin{macrocode}
\newcommand*{\@twocolumninarea}[5][all]{%
  \setlength{\columnheight}{#3}%
  \ifffvadjust\adjustheight{\columnheight}\fi%
  \setlength{\columnwidth}{#2}%
  \addtolength{\columnwidth}{-\columnsep}%
  \divide\columnwidth by 2\relax
  \setlength{\@ff@tmp@x}{#4}%
  \addtolength{\@ff@tmp@x}{\columnwidth}%
  \addtolength{\@ff@tmp@x}{\columnsep}%
  \iflefttorightcolumns
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{#4}{#5}%
    \setflowframe{\c@maxflow}{margin=left}%
  \else
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{\@ff@tmp@x}{#5}%
    \setflowframe{\c@maxflow}{margin=right}%
  \fi
  \iflefttorightcolumns
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{\@ff@tmp@x}{#5}%
    \setflowframe{\c@maxflow}{margin=right}%
  \else
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{#4}{#5}%
    \setflowframe{\c@maxflow}{margin=left}%
  \fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumn}
% Again for an aribtrary number of columns (\meta{n}). Syntax:
% \cs{Ncolumn}\oarg{pages}\marg{n}.
%    \begin{macrocode}
\newcommand*{\Ncolumn}[2][all]{%
\Ncolumninarea[#1]{#2}{\textwidth}{\textheight}{0pt}{0pt}}
\@onlypreamble{\Ncolumn}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumninarea}
% Check the number of \glspl{flow} requested, and do one
% of the special cases if available.
% Syntax:\newline
% \cs{Ncolumninarea}\oarg{pages}\marg{n}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\Ncolumninarea}[6][all]{%
\ifnum#2>2\relax
  \@Ncolumninarea[#1]{#2}{#3}{#4}{#5}{#6}%
\else
  \ifcase#2\relax
    \PackageError{flowfram}{% 
    You have requested 0 flowframes!}{%
    It does not make much sense to ask to create 0 flow frames}%
  \or
    \onecolumninarea[#1]{#3}{#4}{#5}{#6}%
  \or
    \twocolumninarea[#1]{#3}{#4}{#5}{#6}%
  \else
    \PackageError{flowfram}{%
    Can't create a negative number of flow frames!}{%
    You have asked for \number#2 \space flow frames
    which really doesn't make sense}%
  \fi
\fi
}

\@onlypreamble{\Ncolumninarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@Ncolumninarea}
% Set up \meta{n} columns in the area specified.
% There is a horizontal distance of "\columnsep"
% between them all.
%    \begin{macrocode}
\newcommand*{\@Ncolumninarea}[6][all]{%
  \@colN=#2\relax
  \advance\@colN by -1\relax
  \setlength{\columnwidth}{#3}%
  \addtolength{\columnwidth}{-\@colN\columnsep}%
  \divide\columnwidth by #2\relax
  \setlength{\@ff@tmp@x}{#5}%
  \iflefttorightcolumns
  \else
    \addtolength{\@ff@tmp@x}{#3}%
    \addtolength{\@ff@tmp@x}{-\columnwidth}%
  \fi
  \setlength{\columnheight}{#4}%
  \ifffvadjust\adjustheight{\columnheight}\fi%
  \@colN=0\relax
  \loop
    \advance\@colN by 1\relax
    \newflowframe[#1]{\columnwidth}{\columnheight}{\@ff@tmp@x}{#6}%
    \iflefttorightcolumns
      \addtolength{\@ff@tmp@x}{\columnwidth}%
      \addtolength{\@ff@tmp@x}{\columnsep}%
    \else
      \addtolength{\@ff@tmp@x}{-\columnwidth}%
      \addtolength{\@ff@tmp@x}{-\columnsep}%
    \fi
  \ifnum\@colN<#2
  \repeat
}
%    \end{macrocode}
%\end{macro}
%
% Set up something similar but have another frame (of type
% \meta{type}) at the top of  the other frames.
%\begin{macro}{\vcolumnsep}
% The vertical distance between the top frames and column flow
% frames when created using "\Ncolumntop" etc is given by:
%    \begin{macrocode}
\newlength{\vcolumnsep}
\setlength{\vcolumnsep}{\columnsep}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumntop}
% "\onecolumntop" makes one \gls{flow}, and one \meta{type} 
% frame in the area specified, where the \meta{type} frame is 
% \meta{H} high.
% The distance between the top frame and the column \gls{flow}
% will be approximately "\vcolumnsep". (The height of \gls{flow}
% may be adjusted to make it an integer multiple of 
% "\baselineskip".) 
%
% First the special case where the area is the \gls{typeblock}.
% Syntax:\newline
% \cs{onecolumntop}\oarg{pages}\marg{type}\marg{H}
%    \begin{macrocode}
\newcommand*{\onecolumntop}[3][all]{%
\onecolumntopinarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}}
\@onlypreamble{\onecolumntop}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnStop}
% Special case for \gls{static}.
% Syntax: \cs{onecolumnStop}\oarg{pages}\marg{H}
%    \begin{macrocode}
\newcommand*{\onecolumnStop}[2][all]{%
\onecolumntopinarea[#1]{static}{#2}{\textwidth}{\textheight}{0pt}{0pt}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnDtop}
% Special case for \gls{dynamic}.
% Syntax: \cs{onecolumnDtop}\oarg{pages}\marg{H}
%    \begin{macrocode}
\newcommand*{\onecolumnDtop}[2][all]{%
\onecolumntopinarea[#1]{dynamic}{#2}{\textwidth}{\textheight}{0pt}{0pt}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\newframe}
% Create a frame of given type.
% Syntax:\newline
% \cs{newframe}\oarg{pages}\marg{type}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\newframe}[6][all]{%
\ifthenelse{\equal{#2}{flow}}{%
\@n@wflowframe[#1]{#3}{#4}{#5}{#6}%
}{%
\ifthenelse{\equal{#2}{dynamic}}{%
\@n@wdynamicframe[#1]{#3}{#4}{#5}{#6}}{%
\ifthenelse{\equal{#2}{static}}{%
\@n@wstaticframe[#1]{#3}{#4}{#5}{#6}}{%
\PackageError{flowfram}{Unknown frame type '#2'}{%
Available frame types are: 'flow', 'static' and 'dynamic'}}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumntopinarea}
% Now for a specified area.
% Syntax:\newline
% \cs{onecolumntopinarea}\oarg{pages}\marg{type}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newlength\@ff@staticH

\newcommand*{\onecolumntopinarea}[7][all]{%
\setlength{\@ff@staticH}{#3}%
\setlength{\@ff@tmp@y}{#5}%
\addtolength{\@ff@tmp@y}{-\@ff@staticH}%
\setlength{\columnheight}{\@ff@tmp@y}%
\addtolength{\columnheight}{-\vcolumnsep}%
\ifffvadjust\adjustheight{\columnheight}\fi%
\addtolength{\@ff@tmp@y}{#7}%
\newframe[#1]{#2}{#4}{\@ff@staticH}{#6}{\@ff@tmp@y}%
\@n@wflowframe[#1]{#4}{\columnheight}{#6}{#7}%
}

\@onlypreamble{\onecolumntopinarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnStopinarea}
% Special case for \gls{static}.
% Syntax:\newline
% \cs{onecolumnStopinarea}\oarg{pages}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\onecolumnStopinarea}[6][all]{%
\onecolumntopinarea[#1]{static}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnDtopinarea}
% Special case for \gls{dynamic}.
% Syntax:\newline
% \cs{onecolumnDtopinarea}\oarg{pages}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\onecolumnDtopinarea}[6][all]{%
\onecolumntopinarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumntop}
% Now for two \glspl{flow}, with a single \meta{type} frame
% above both of them.
% Syntax:\newline
% \cs{twocolumntop}\oarg{pages}\marg{type}\marg{H}
%
% First the special case where the area is the entire
% \gls{typeblock}:
%    \begin{macrocode}
\newcommand*{\twocolumntop}[3][all]{%
\twocolumntopinarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}}
\@onlypreamble{\twocolumntop}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnStop}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\twocolumnStop}[2][all]{%
\@twocolumntopinarea[#1]{static}{#2}{\textwidth}{\textheight}{0pt}{0pt}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDtop}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\twocolumnDtop}[2][all]{%
\twocolumntop[#1]{dynamic}{#2}}
%    \end{macrocode}
%\end{macro}
%
% Now for a general area.
%\begin{macro}{\twocolumntopinarea}
% Syntax:\newline
% \cs{twocolumntopinarea}\oarg{pages}\marg{type}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\twocolumntopinarea}{\@twocolumntopinarea}
\newcommand*{\@twocolumntopinarea}[7][all]{%
  \setlength{\@ff@staticH}{#3}%
%    \end{macrocode}
% work out where to put the static frame
%    \begin{macrocode}
  \setlength{\@ff@tmp@y}{#5}%
  \addtolength{\@ff@tmp@y}{-\@ff@staticH}%
  \setlength{\columnheight}{\@ff@tmp@y}%
  \addtolength{\@ff@tmp@y}{#7}%
  \newframe[#1]{#2}{#4}{\@ff@staticH}{#6}{\@ff@tmp@y}%
%    \end{macrocode}
% work out height of the flow frames
%    \begin{macrocode}
  \addtolength{\columnheight}{-\vcolumnsep}%
  \ifffvadjust\adjustheight{\columnheight}\fi
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \setlength{\columnwidth}{#4}%
  \addtolength{\columnwidth}{-\columnsep}%
  \divide\columnwidth by 2\relax
%    \end{macrocode}
% work out the offset of the right column
%    \begin{macrocode}
  \setlength{\@ff@tmp@x}{\columnwidth}%
  \addtolength{\@ff@tmp@x}{\columnsep}%
  \addtolength{\@ff@tmp@x}{#6}%
  \iflefttorightcolumns
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{#6}{#7}%
    \setflowframe{\c@maxflow}{margin=left}%
  \else
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{\@ff@tmp@x}{#7}%
    \setflowframe{\c@maxflow}{margin=right}%
  \fi
  \iflefttorightcolumns
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{\@ff@tmp@x}{#7}%
    \setflowframe{\c@maxflow}{margin=right}%
  \else
    \@n@wflowframe[#1]{\columnwidth}{\columnheight}{#6}{#7}%
    \setflowframe{\c@maxflow}{margin=left}%
  \fi
}
\@onlypreamble{\twocolumntopinarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnStopinarea}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\twocolumnStopinarea}[6][all]{%
\twocolumntopinarea[#1]{static}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDtopinarea}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\twocolumnDtopinarea}[6][all]{%
\twocolumntopinarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumntop}
% Similarly for an arbitrary number of \glspl{flow}.
% Special case where the area is the \gls{typeblock}.
%
% Syntax:\newline
% \cs{Ncolumntop}\oarg{pages}\marg{type}\marg{n}\marg{H}
%    \begin{macrocode}
\newcommand*{\Ncolumntop}[4][all]{%
\Ncolumntopinarea[#1]{#2}{#3}{#4}{\textwidth}{\textheight}{0pt}{0pt}}
\@onlypreamble{\Ncolumntop}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnStop}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\NcolumnStop}[3][all]{%
\Ncolumntop[#1]{static}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDtop}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\NcolumnDtop}[3][all]{%
\Ncolumntop[#1]{dynamic}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumntopinarea}
% Again test to make sure the user requested a sensible
% number.
%    \begin{macrocode}
\newcommand*{\Ncolumntopinarea}[8][all]{%
\ifnum#3>2\relax
  \@Ncolumntopinarea[#1]{#2}{#3}{#4}{#5}{#6}{#7}{#8}%
\else
  \ifcase#3\relax
    \PackageError{flowfram}{% 
    You have requested 0 flowframes!}{%
    It does not make much sense to ask to create 0 flow frames}
  \or
    \onecolumntopinarea[#1]{#2}{#4}{#5}{#6}{#7}{#8}%
  \or
    \twocolumntopinarea[#1]{#2}{#4}{#5}{#6}{#7}{#8}%
  \else
    \PackageError{flowfram}{%
    Can't create a negative number of flow frames!}{%
    You have asked for \number#3 \space flow frames
    which really doesn't make sense}%
  \fi
\fi
}
\@onlypreamble{\Ncolumntopinarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@Ncolumntopinarea}
% Fit the frames into specified area.
% Syntax:\newline
% \cs{Ncolumntopinarea}\oarg{pages}\marg{type}\marg{n}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\@Ncolumntopinarea}[8][all]{%
  \setlength{\@ff@staticH}{#4}%
%    \end{macrocode}
% work out where to put the static frame
%    \begin{macrocode}
  \setlength{\@ff@tmp@y}{#6}%
  \addtolength{\@ff@tmp@y}{-\@ff@staticH}%
  \setlength{\columnheight}{\@ff@tmp@y}%
  \addtolength{\@ff@tmp@y}{#8}%
  \newframe[#1]{#2}{#5}{\@ff@staticH}{#7}{\@ff@tmp@y}%
%    \end{macrocode}
% work out height of the flow frames
%    \begin{macrocode}
  \addtolength{\columnheight}{-\vcolumnsep}%
%    \end{macrocode}
% adjust the flow frame height so that it is a multiple of 
% \cs{baselineskip}
%    \begin{macrocode}
  \ifffvadjust\adjustheight{\columnheight}\fi%
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \@colN=#3\relax
  \advance\@colN by -1\relax
  \setlength{\columnwidth}{#5}%
  \addtolength{\columnwidth}{-\@colN\columnsep}%
  \divide\columnwidth by #3\relax
%    \end{macrocode}
% Set the $x$ position of the first frame
%    \begin{macrocode}
  \setlength{\@ff@tmp@x}{#7}%
  \iflefttorightcolumns
  \else
    \addtolength{\@ff@tmp@x}{#5}%
    \addtolength{\@ff@tmp@x}{-\columnwidth}%
  \fi
  \@colN=0\relax
  \loop
    \advance\@colN by 1\relax
    \newflowframe[#1]{\columnwidth}{\columnheight}{\@ff@tmp@x}{#8}%
%    \end{macrocode}
% work out the offset for the next column
%    \begin{macrocode}
    \iflefttorightcolumns
      \addtolength{\@ff@tmp@x}{\columnwidth}%
      \addtolength{\@ff@tmp@x}{\columnsep}%
    \else
      \addtolength{\@ff@tmp@x}{-\columnwidth}%
      \addtolength{\@ff@tmp@x}{-\columnsep}%
    \fi
  \ifnum\@colN<#3
  \repeat
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnStopinarea}
% Specific case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\NcolumnStopinarea}[7][all]{%
\Ncolumntopinarea[#1]{static}{#2}{#3}{#4}{#5}{#6}{#7}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDtopinarea}
% Specific case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\NcolumnDtopinarea}[7][all]{%
\Ncolumntopinarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}{#7}}
%    \end{macrocode}
%\end{macro}
% Now the same kind of thing but with the \meta{type} frame at the
% bottom. Firstly, a single \gls{flow} with a \meta{type}
% frame below it. 
%
%\begin{macro}{\onecolumnbottom}
% Syntax:\newline
% \cs{onecolumnbottom}\oarg{pages}\marg{type}\marg{H}
%    \begin{macrocode}
\newcommand*{\onecolumnbottom}[3][all]{%
\onecolumnbottominarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}}
%    \end{macrocode}
%\end{macro}
% This command may only be used in the preamble.
%    \begin{macrocode}
\@onlypreamble{\onecolumnbottom}
%    \end{macrocode}
%\begin{macro}{\onecolumnSbottom}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\onecolumnSbottom}[2][all]{%
\onecolumnbottom[#1]{static}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnDbottom}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\onecolumnDbottom}[2][all]{%
\onecolumnbottom[#1]{dynamic}{#2}}
%    \end{macrocode}
%\end{macro}
%
% General case of the above, but fit in specified area.
%\begin{macro}{\onecolumnbottominarea}
% Syntax:\newline
% \cs{onecolumnbottominarea}\oarg{pages}\marg{type}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y},\newline
% where \meta{H} is the \meta{type} frame's height.
% The area is defined by bottom
% left co-ordinates (\meta{x}, \meta{y}) width \meta{w}, and 
% height \meta{h}.
%    \begin{macrocode}
\newcommand*{\onecolumnbottominarea}[7][all]{%
  \setlength{\@ff@staticH}{#3}%
  \setlength{\columnheight}{#5}%
  \addtolength{\columnheight}{-\@ff@staticH}%
  \addtolength{\columnheight}{-\vcolumnsep}%
  \ifffvadjust\adjustheight{\columnheight}\fi%
  \setlength{\@ff@tmp@y}{#5}%
  \addtolength{\@ff@tmp@y}{-\columnheight}%
  \addtolength{\@ff@tmp@y}{#7}%
  \newframe[#1]{#2}{#4}{\@ff@staticH}{#6}{#7}%
  \newflowframe[#1]{#4}{\columnheight}{#6}{\@ff@tmp@y}%
}
%    \end{macrocode}
%\end{macro}
% Again, this command may only be used in the preamble.
%    \begin{macrocode}
\@onlypreamble{\onecolumnbottominarea}
%    \end{macrocode}
%\begin{macro}{\onecolumnSbottominarea}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\onecolumnSbottominarea}[6][all]{%
\onecolumnbottominarea[#1]{static}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnDbottominarea}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\onecolumnDbottominarea}[6][all]{%
\onecolumnbottominarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnbottom}
% Now for two \glspl{flow} side by side with a static
% frame underneath both of them. Firstly, the specific
% case where the area is the entire \gls{typeblock}.
% Syntax:\newline
% \cs{twocolumnbottom}\oarg{pages}\marg{type}\marg{H}.
%    \begin{macrocode}
\newcommand*{\twocolumnbottom}[3][all]{%
\twocolumnSbottominarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}}
\@onlypreamble{\twocolumnbottom}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnSbottom}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\twocolumnSbottom}[2][all]{%
\twocolumnbottom[#1]{static}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDbottom}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\twocolumnDbottom}[2][all]{%
\twocolumnbottom[#1]{dynamic}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnbottominarea}
% Now for a general area.
% Syntax:\newline
% \cs{twocolumnbottominarea}\oarg{pages}\marg{type}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\newcommand*{\twocolumnbottominarea}[7][all]{%
  \setlength{\@ff@staticW}{#4}%
  \setlength{\@ff@staticH}{#3}%
%    \end{macrocode}
% work out height of the flow frames
%    \begin{macrocode}
  \setlength{\columnheight}{#5}%
  \addtolength{\columnheight}{-\@ff@staticH}%
  \addtolength{\columnheight}{-\vcolumnsep}%
  \ifffvadjust\adjustheight{\columnheight}\fi%
  \newframe[#1]{#2}{\@ff@staticW}{\@ff@staticH}{#6}{#7}%
%    \end{macrocode}
% work out the $y$ position of the flow frames
%    \begin{macrocode}
  \setlength{\@ff@tmp@y}{#5}%
  \addtolength{\@ff@tmp@y}{-\columnheight}%
  \addtolength{\@ff@tmp@y}{#7}%
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \setlength{\columnwidth}{\@ff@staticW}%
  \addtolength{\columnwidth}{-\columnsep}%
  \divide\columnwidth by 2\relax
%    \end{macrocode}
% work out the $x$ offset of the right column
%    \begin{macrocode}
  \setlength{\@ff@tmp@x}{\columnwidth}%
  \addtolength{\@ff@tmp@x}{\columnsep}%
  \addtolength{\@ff@tmp@x}{#6}%
%    \end{macrocode}
% Define the frames
%    \begin{macrocode}
  \iflefttorightcolumns
    \newflowframe[#1]{\columnwidth}{\columnheight}{#6}{\@ff@tmp@y}%
    \setflowframe{\c@maxflow}{margin=left}%
  \else
    \newflowframe[#1]{\columnwidth}{\columnheight}%
      {\@ff@tmp@x}{\@ff@tmp@y}%
    \setflowframe{\c@maxflow}{margin=right}%
  \fi
  \iflefttorightcolumns
    \newflowframe[#1]{\columnwidth}{\columnheight}%
      {\@ff@tmp@x}{\@ff@tmp@y}%
    \setflowframe{\c@maxflow}{margin=right}%
  \else
    \newflowframe[#1]{\columnwidth}{\columnheight}{#6}{\@ff@tmp@y}%
    \setflowframe{\c@maxflow}{margin=left}%
  \fi
}
\@onlypreamble{\twocolumnbottominarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnSbottominarea}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\twocolumnSbottominarea}[6][all]{%
\twocolumnbottominarea[#1]{static}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDbottominarea}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\twocolumnDbottominarea}[6][all]{%
\twocolumnbottominarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}}
%    \end{macrocode}
%\end{macro}
% Now for an arbitrary number of parallel \glspl{flow}
% with a \gls{static} beneath all of them.
%
%\begin{macro}{\Ncolumnbottom}
% First make them fill the entire \gls{typeblock}.
% Syntax:\newline
% \cs{Ncolumnbottom}\oarg{pages}\marg{type}\marg{H}.
%    \begin{macrocode}
\newcommand*{\Ncolumnbottom}[4][all]{%
\Ncolumnbottominarea[#1]{#2}{#3}{#4}{\textwidth}{\textheight}{0pt}{0pt}}
\@onlypreamble{\Ncolumnbottom}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnSbottom}
% Special case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\NcolumnSbottom}[3][all]{%
\Ncolumnbottom[#1]{static}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDbottom}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\NcolumnDbottom}[3][all]{%
\Ncolumnbottom[#1]{dynamic}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumnbottominarea}
% Again check the user has requested a sensible number.
%    \begin{macrocode}
\newcommand*{\Ncolumnbottominarea}[8][all]{%
\ifnum#3>2\relax
  \@Ncolumnbottominarea[#1]{#2}{#3}{#4}{#5}{#6}{#7}{#8}%
\else
  \ifcase#3\relax
    \PackageError{flowfram}{% 
    You have requested 0 flowframes!}{%
    It does not make much sense to ask to create 0 flow frames}
  \or
    \onecolumnbottominarea[#1]{#2}{#4}{#5}{#6}{#7}{#8}%
  \or
    \twocolumnbottominarea[#1]{#2}{#4}{#5}{#6}{#7}{#8}%
  \else
    \PackageError{flowfram}{%
    Can't create a negative number of flow frames!}{%
    You have asked for \number#3 \space flow frames
    which really doesn't make sense}%
  \fi
\fi
}
\@onlypreamble{\Ncolumnbottominarea}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@NcolumnSbottominarea}
% An arbitrary number of columns with a \gls{static}
% underneath them all, filling the specified area.
%    \begin{macrocode}
\newcommand*{\@NcolumnSbottominarea}[8][all]{%
  \setlength{\@ff@staticH}{#4}%
%    \end{macrocode}
% work out height of the flow frames
%    \begin{macrocode}
  \setlength{\columnheight}{#6}%
  \addtolength{\columnheight}{-\@ff@staticH}%
  \addtolength{\columnheight}{-\vcolumnsep}%
%    \end{macrocode}
% adjust the flow frame height so that it is a multiple of 
% \cs{baselineskip}
%    \begin{macrocode}
  \ifffvadjust\adjustheight{\columnheight}\fi
  \newframe[#1]{#2}{#5}{\@ff@staticH}{#7}{#8}%
%    \end{macrocode}
% work out the $y$ offset of the flow frames
%    \begin{macrocode}
  \setlength{\@ff@tmp@y}{#6}%
  \addtolength{\@ff@tmp@y}{-\columnheight}%
  \addtolength{\@ff@tmp@y}{#8}%
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \@colN=#3\relax
  \advance\@colN by -1\relax
  \setlength{\columnwidth}{#5}%
  \addtolength{\columnwidth}{-\@colN\columnsep}%
  \divide\columnwidth by #3\relax
%    \end{macrocode}
% Set the $x$ offset of the first frame.
%    \begin{macrocode}
  \setlength{\@ff@tmp@x}{#7}%
  \iflefttorightcolumns
  \else
    \addtolength{\@ff@tmp@x}{#5}%
    \addtolength{\@ff@tmp@x}{-\columnwidth}%
  \fi
  \@colN=0\relax
  \loop
    \advance\@colN by 1\relax
    \newflowframe[#1]{\columnwidth}{\columnheight}%
       {\@ff@tmp@x}{\@ff@tmp@y}%
%    \end{macrocode}
% work out the offset for the next column
%    \begin{macrocode}
    \iflefttorightcolumns
      \addtolength{\@ff@tmp@x}{\columnwidth}%
      \addtolength{\@ff@tmp@x}{\columnsep}%
    \else
      \addtolength{\@ff@tmp@x}{-\columnwidth}%
      \addtolength{\@ff@tmp@x}{-\columnsep}%
    \fi
  \ifnum\@colN<#3
  \repeat
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnSbottominarea}
% Specific case for \gls{static}.
%    \begin{macrocode}
\newcommand*{\NcolumnSbottominarea}[1][all]{%
\Ncolumnbottominarea[#1]{static}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDbottominarea}
% Specific case for \gls{dynamic}.
%    \begin{macrocode}
\newcommand*{\NcolumnDbottominarea}[1][all]{%
\Ncolumnbottominarea[#1]{dynamic}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\adjustheight}
% Given a height "#1" (a length), adjust it so that it is a multiple of "\baselineskip".
%    \begin{macrocode}
\newcount\@ff@adjh
\newcommand*{\adjustheight}[1]{%
%    \end{macrocode}
% convert to an integer
%    \begin{macrocode}
\@ff@adjh=#1\relax
\divide\@ff@adjh by \baselineskip\relax
#1=\baselineskip\relax
\multiply#1 by \@ff@adjh\relax
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\adjustcolsep}
% Adjust the value of "\columnsep" so that the margins will fit between columns.
%    \begin{macrocode}
\newcommand*{\adjustcolsep}{%
\multiply\columnsep by 2\relax
\addtolength{\columnsep}{\marginparwidth}}
%    \end{macrocode}
%\end{macro}
%
%\subsubsection{Backdrop Effects}
% Set up some commands to make \glspl{static} for different styles 
% of backdrop.
%\begin{macro}{\vtwotone}
% Syntax:\newline
% \cs{vtwotone}\oarg{pages}\oarg{xoffset}\marg{W1}\marg{C1}\marg{L1}\marg{W2}\marg{C2}\marg{L2}
%\newline where the first frame
% has width \meta{W1} with background colour \meta{C1} and label \meta{L1}. 
% The second frame has width \meta{W2} with background colour \meta{C2}
% and label \meta{L2}. Unlike earlier commands, the $x$-offset is 
% relative to the left page edge \emph{not} the \gls{typeblock}. 
% This is because they are designed for backdrops, which
% tend to span the entire page.
% Note that the colour specs must be
% completely enclosed in braces. e.g.\ "{[gray]{0.5}}" \emph{not} "[gray]{0.5}".
%
% Need a length to store the width of the \gls{static}.
%    \begin{macrocode}
\newlength\@ff@staticW
%    \end{macrocode}
% Vertical two tone effect where the height of the static
% frames is equal to the paper height.
%    \begin{macrocode}
\newcommand*{\vtwotone}[1][all]{%
\def\ff@pages{#1}\@vtwotone}

\newcommand*{\@vtwotone}[1][0pt]{\@@vtwotonebottom{#1}{\paperheight}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\vtwotonebottom}
% Vertical two tone effect along the bottom of the page, of
% height \meta{H}.
% Syntax:\newline
% \cs{vtwotonebottom}\oarg{pages}\oarg{xoffset}\marg{H}\marg{W1}\marg{C1}\marg{L1}\marg{W2}\marg{C2}\marg{L2}
% where the first frame starts at \meta{xoffset}.
%    \begin{macrocode}
\newcommand*{\@@vtwotonebottom}[8]{%
\computeleftedgeodd{\@ff@tmp@x}%
\if@twoside
  \computeleftedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computebottomedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@x}{#1}%
\addtolength{\@ff@tmp@x@even}{#1}%
\@nextvband{\ff@pages}{#2}{#3}{#4}{#5}%
\@nextvband{\ff@pages}{#2}{#6}{#7}{#8}%
}

\@onlypreamble{\vtwotone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\vtwotonebottom}
% Border strip along the bottom of the page
%    \begin{macrocode}
\newcommand*{\vtwotonebottom}[1][all]{%
\def\ff@pages{#1}\@vtwotonebottom}

\@onlypreamble{\vtwotonebottom}

\newcommand*{\@vtwotonebottom}[2][0pt]{\@@vtwotonebottom{#1}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\vtwotonetop}
% Border strip along the top of the page
%    \begin{macrocode}
\newcommand*{\vtwotonetop}[1][all]{%
\def\ff@pages{#1}\@vtwotonetop}

\newcommand*{\@vtwotonetop}[2][0pt]{\@@vtwotonetop{#1}{#2}}

\newcommand*{\@@vtwotonetop}[8]{%
\computeleftedgeodd{\@ff@tmp@x}%
\if@twoside
  \computeleftedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computetopedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@y}{-#2}%
\addtolength{\@ff@tmp@x}{#1}%
\addtolength{\@ff@tmp@x@even}{#1}%
\@nextvband{\ff@pages}{#2}{#3}{#4}{#5}%
\@nextvband{\ff@pages}{#2}{#6}{#7}{#8}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@nextvband}
% Make next \gls{static}. Syntax:\newline
% \cs{@nextvband}\marg{pages}\marg{height}\marg{width}\marg{colour specs}\marg{label}\newline
% $x$ and $y$ offsets are given by "\@ff@tmp@x" and "\@ff@tmp@y". 
% On exit, "\@ff@tmp@x" is set to the right border.
%    \begin{macrocode}
\newcommand*{\@nextvband}[5]{%
\setlength{\@ff@staticW}{#3}%
\ifthenelse{\equal{#5}{}}{%
\newstaticframe[#1]{\@ff@staticW}{#2}{\@ff@tmp@x}{\@ff@tmp@y}}%
{\newstaticframe[#1]{\@ff@staticW}{#2}{\@ff@tmp@x}{\@ff@tmp@y}[#5]}%
\expandafter\global\expandafter\setlength
 \csname @sf@\romannumeral\c@maxstatic @evenx\endcsname{%
   \@ff@tmp@x@even}%
\@setframecol#4\end{\c@maxstatic}{backcol}{sf}%
\addtolength{\@ff@tmp@x}{\@ff@staticW}%
\addtolength{\@ff@tmp@x@even}{\@ff@staticW}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\vNtone}
% Similarly for N colours. Syntax:\newline
% \cs{vNtone}\oarg{pages}\oarg{xoffset}\marg{n}\marg{W1}\marg{C1}\marg{L1}\ldots\marg{Wn}\marg{Cn}\marg{Ln}\newline
% where the first frame has width \meta{W1} with background 
% colour \meta{C1} and label \meta{L1} all the way up to
% the \meta{n}th frame which has width \meta{Wn}, background
% colour \meta{Cn} and \gls{idl} \meta{Ln}.
%
% Keep track of which strip we are doing.
%    \begin{macrocode}
\newcount\@thisstrip
%    \end{macrocode}
% This command needs two optional arguments, so store
% first optional argument, and look for the next.
%    \begin{macrocode}
\newcommand*{\vNtone}[1][all]{%
\def\ff@pages{#1}\@vNtone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vNtone}
% Got the first argument, now get the next.
%    \begin{macrocode}
\newcommand*{\@vNtone}[2][0pt]{%
\@@vNtone{#1}{#2}{\paperheight}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@vNtone}
% Vertical \meta{n} tone aligned along the
% bottom of the page with height "#3".
%    \begin{macrocode}
\newcommand*{\@@vNtone}[3]{%
\computeleftedgeodd{\@ff@tmp@x}%
\if@twoside
  \computeleftedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computebottomedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@x}{#1}%
\addtolength{\@ff@tmp@x@even}{#1}%
\@thisstrip=#2\relax
\setlength{\@ff@staticH}{#3}%
\@nextvNband%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@nextvNband}
% Recursively do the next strip.
%    \begin{macrocode}
\newcommand*{\@nextvNband}{%
\ifnum\@thisstrip>0\relax
 \let\flf@next\@@nextvNband
\else
 \let\flf@next\relax
\fi
\advance\@thisstrip by -1\relax
\flf@next}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@nextvNband}
% Do current strip, and go on to next one.
%    \begin{macrocode}
\newcommand*{\@@nextvNband}[3]{%
\@nextvband{\ff@pages}{\@ff@staticH}{#1}{#2}{#3}\@nextvNband}

\@onlypreamble{\vNtone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\vNtonebottom}
% Border strip along the bottom of the page. Same as above
% but user specifies the height.
%    \begin{macrocode}
\newcommand*{\vNtonebottom}[1][all]{%
\def\ff@pages{#1}\@vNtonebottom}
\@onlypreamble{\vNtonebottom}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vNtonebottom}
%    \begin{macrocode}
\newcommand*{\@vNtonebottom}[3][0pt]{%
\@@vNtone{#1}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\vNtonetop}
% Border strip along the top of the page. Again two
% optional arguments are required. Get first optional
% argument.
%    \begin{macrocode}
\newcommand*{\vNtonetop}[1][all]{%
\def\ff@pages{#1}\@vNtonetop}
\@onlypreamble{\vNtonetop}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vNtonetop}
% Get next optional argument.
%    \begin{macrocode}
\newcommand*{\@vNtonetop}[3][0pt]{%
\@@vNtonetop{#1}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@vNtonetop}
% Now get on with it.  Again, it has to be done 
% recursively.
%    \begin{macrocode}
\newcommand*{\@@vNtonetop}[3]{%
\computeleftedgeodd{\@ff@tmp@x}%
\if@twoside
  \computeleftedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computetopedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@y}{-#3}%
\addtolength{\@ff@tmp@x}{#1}%
\addtolength{\@ff@tmp@x@even}{#1}%
\@thisstrip=#2\relax
\setlength{\@ff@staticH}{#3}%
\@nextvNband%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\htwotone}
% Now do horizontal strips. Syntax:\newline
% \cs{htwotone}\oarg{pages}\oarg{y offset}\marg{H1}\marg{C1}\marg{L1}\marg{H2}\marg{C2}\marg{L2}
%    \begin{macrocode}
\newcommand*{\htwotone}[1][all]{%
\def\ff@pages{#1}\@htwotone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@htwotone}
%    \begin{macrocode}
\newcommand*{\@htwotone}[1][0pt]{\@@htwotoneleft{#1}{\paperwidth}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@htwotoneleft}
% This is all done in much the same way as the vertical
% strips.
%    \begin{macrocode}
\newcommand*{\@@htwotoneleft}[8]{%
\computeleftedgeodd{\@ff@tmp@x}%
\if@twoside
  \computeleftedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computebottomedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@y}{#1}%
\@nexthband{\ff@pages}{#2}{#3}{#4}{#5}%
\@nexthband{\ff@pages}{#2}{#6}{#7}{#8}%
}

\@onlypreamble{\htwotone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\htwotoneleft}
% Two tone horizontal strips along left border
% Syntax: \cs{htwotoneleft}\oarg{pages}\oarg{y offset}\marg{width}\marg{H1}\marg{C1}\marg{L1}\marg{H2}\marg{C2}\marg{L2}
%    \begin{macrocode}
\newcommand*{\htwotoneleft}[1][all]{%
\def\ff@pages{#1}\@htwotoneleft}
\@onlypreamble{\htwotoneleft}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@htwotoneleft}
%    \begin{macrocode}
\newcommand*{\@htwotoneleft}[2][0pt]{\@@htwotoneleft{#1}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\htwotoneright}
% Two tone horizontal strips along right border
%    \begin{macrocode}
\newcommand*{\htwotoneright}[1][all]{%
\def\ff@pages{#1}\@htwotoneright}
\@onlypreamble{\htwotoneright}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@htwotoneright}
%    \begin{macrocode}
\newcommand*{\@htwotoneright}[2][0pt]{\@@htwotoneright{#1}{#2}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@htwotoneright}
%    \begin{macrocode}
\newcommand*{\@@htwotoneright}[8]{%
\computerightedgeodd{\@ff@tmp@x}%
\if@twoside
  \computerightedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computebottomedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@y}{#1}%
\addtolength{\@ff@tmp@x}{-#2}%
\addtolength{\@ff@tmp@x@even}{-#2}%
\@nexthband{\ff@pages}{#2}{#3}{#4}{#5}%
\@nexthband{\ff@pages}{#2}{#6}{#7}{#8}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\hNtone}
% Now for \meta{N} coloured horizontal strips
%    \begin{macrocode}
\newcommand*{\hNtone}[1][all]{%
\def\ff@pages{#1}\@hNtone}
\@onlypreamble{\hNtone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@hNtone}
%    \begin{macrocode}
\newcommand*{\@hNtone}[2][0pt]{%
\@@hNtone{#1}{#2}{\paperwidth}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@hNtone}
%    \begin{macrocode}
\newcommand*{\@@hNtone}[3]{%
\computeleftedgeodd{\@ff@tmp@x}%
\if@twoside
  \computeleftedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computebottomedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@y}{#1}%
\@thisstrip=#2\relax
\setlength{\@ff@staticW}{#3}%
\@nexthNband%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\hNtoneleft}
% Now for the N tone strips along the left border
%    \begin{macrocode}
\newcommand*{\hNtoneleft}[1][all]{%
\def\ff@pages{#1}\@hNtoneleft}
\@onlypreamble{\hNtoneleft}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@hNtoneleft}
%    \begin{macrocode}
\newcommand*{\@hNtoneleft}[3][0pt]{%
\@@hNtone{#1}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\hNtoneright}
% Border strip along the right border
%    \begin{macrocode}
\newcommand*{\hNtoneright}[1][all]{%
\def\ff@pages{#1}\@hNtoneright}
\@onlypreamble{\hNtoneright}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@hNtoneright}
%    \begin{macrocode}
\newcommand*{\@hNtoneright}[3][0pt]{%
\@@hNtoneright{#1}{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@hNtoneright}
%    \begin{macrocode}
\newcommand*{\@@hNtoneright}[3]{%
\computerightedgeodd{\@ff@tmp@x}%
\if@twoside
  \computerightedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computebottomedge{\@ff@tmp@y}%
\addtolength{\@ff@tmp@y}{#1}%
\addtolength{\@ff@tmp@x}{-#3}%
\addtolength{\@ff@tmp@x@even}{-#3}%
\@thisstrip=#2\relax
\setlength{\@ff@staticW}{#3}%
\@nexthNband%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@nexthband}
% Make next \gls{static}. Syntax:\newline
% \cs{@nexthband}\marg{pages}\marg{width}\marg{height}\marg{colour specs}\marg{label}\newline
% $x$ and $y$ offsets are given by "\@ff@tmp@x" and "\@ff@tmp@y". 
% On exit, "\@ff@tmp@y" is set to the top border.
%    \begin{macrocode}
\newcommand*{\@nexthband}[5]{%
\setlength{\@ff@staticH}{#3}%
\ifthenelse{\equal{#5}{}}{%
\newstaticframe[#1]{#2}{\@ff@staticH}{\@ff@tmp@x}{\@ff@tmp@y}}%
{\newstaticframe[#1]{#2}{\@ff@staticH}{\@ff@tmp@x}{\@ff@tmp@y}[#5]}%
\expandafter\global\expandafter
\setlength\csname @sf@\romannumeral\c@maxstatic @evenx\endcsname{%
\@ff@tmp@x@even}%
\@setframecol#4\end{\c@maxstatic}{backcol}{sf}%
\addtolength{\@ff@tmp@y}{\@ff@staticH}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@nexthNband}
% Get next horizontal strip recursively.
%    \begin{macrocode}
\newcommand*{\@nexthNband}{%
\ifnum\@thisstrip>0\relax
 \let\flf@next\@@nexthNband%
\else
 \let\flf@next\relax%
\fi
\advance\@thisstrip by -1\relax
\flf@next}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@nexthNband}
%    \begin{macrocode}
\newcommand*{\@@nexthNband}[3]{%
\@nexthband{\ff@pages}{\@ff@staticW}{#1}{#2}{#3}\@nexthNband}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\makebackgroundframe}
% Make one big \gls{static} that covers the entire page.
% This command should come before all other commands that create 
% \glspl{static}, otherwise it will obscure all the ones defined
% before it. Syntax:\newline
% \cs{makebackgroundframe}\oarg{pages}\oarg{label}.
%    \begin{macrocode}
\newcommand*{\makebackgroundframe}[1][all]{%
\ifnum\c@maxstatic>0\relax
  \PackageWarning{flowfram}{Background frame is not
  first static frame to be defined. All previously defined
  static frames may be obscured.}%
\fi
\computeleftedgeodd{\@ff@tmp@x}%
\if@twoside
  \computeleftedgeeven{\@ff@tmp@x@even}%
\else
  \setlength{\@ff@tmp@x@even}{\@ff@tmp@x}%
\fi
\computebottomedge{\@ff@tmp@y}%
\newstaticframe[#1]{\paperwidth}{\paperheight}{\@ff@tmp@x}%
{\@ff@tmp@y}%
\expandafter\global\expandafter
\setlength\csname @sf@\romannumeral\c@maxstatic @evenx\endcsname
{\@ff@tmp@x@even}}
%    \end{macrocode}
%\end{macro}
%
%\subsubsection{Lines Between Frames}
%\DescribeMacro{\insertvrule}
% Insert a \gls{static} between two frames with a vertical
% rule that goes from the maximum height of the highest
% to the minimum height of the lowest, equidistant from
% both frames. Syntax:\newline
% \cs{insertvrule}\oarg{y top}\oarg{y bottom}\marg{frame1 type}\marg{IDN1}\marg{frame2 type}\meta{IDN2}.
% The starred version uses \glspl{idl} instead of \glspl{idn}.
% The optional arguments indicate to continue above the highest
% point by \meta{y top} or continue below the lowest point
% by \meta{y bottom}.
%
%\begin{macro}{\ffcolumnseprule}
% This has changed in v1.09. Define "\ffcolumnseprule" and use
% instead of "\columnseprule"
%    \begin{macrocode}
\newlength\ffcolumnseprule
\setlength{\ffcolumnseprule}{2pt}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffruledeclarations}
%\changes{1.11}{2008/06/27}{new}
% This can be redefined to use declarations that affect how the
% rule appears. For example, it can be used to set the colour of
% the rule.
%    \begin{macrocode}
\newcommand*{\ffruledeclarations}{}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\insertvrule}
% Determine whether or not the starred version is being
% used.
%    \begin{macrocode}
\newcommand*{\insertvrule}{\@ifstar\@sinsertvrule\@insertvrule}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@insertvrule}
% Two optional arguments required.
%    \begin{macrocode}
\newcommand*{\@insertvrule}[1][0pt]{%
\@ifnextchar[{\@@insertvrule[#1]}{\@@insertvrule[#1][0pt]}}
%    \end{macrocode}
%\end{macro}
% Need some lengths:
%    \begin{macrocode}
\newlength\@ff@left@x
\newlength\@ff@left@y
\newlength\@ff@left@evenx
\newlength\@ff@left@eveny
\newlength\@ff@left@width
\newlength\@ff@left@height
%    \end{macrocode}
%\begin{macro}{\@@insertvrule}
% Arguments all accounted for. Convert the frame type
% into a number to make life easier
%    \begin{macrocode}
\def\@@insertvrule[#1][#2]#3#4#5#6{%
\ifthenelse{\equal{#3}{flow}}{%
\def\@ff@type@i{1}}{\ifthenelse{\equal{#3}{static}}{%
\def\@ff@type@i{2}}{\ifthenelse{\equal{#3}{dynamic}}{%
\def\@ff@type@i{3}}{\PackageError{flowfram}{Unknown frame
type '#3'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\ifthenelse{\equal{#5}{flow}}{%
\def\@ff@type@ii{1}}{\ifthenelse{\equal{#5}{static}}{%
\def\@ff@type@ii{2}}{\ifthenelse{\equal{#5}{dynamic}}{%
\def\@ff@type@ii{3}}{\PackageError{flowfram}{Unknown frame
type '#5'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\@@insert@vrule{#1}{#2}{\@ff@type@i}{#4}{\@ff@type@ii}{#6}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@insert@vrule}
% Insert a new \gls{static} between the two specified frames.
% Check to make sure which one is on the left and which one
% is on the right.
% Syntax:\newline
%\cs{@@insert@vrule}\marg{y top}\marg{y bottom}\marg{type ID}\marg{IDN}\marg{type ID}\marg{IDN}.
%    \begin{macrocode}
\newcommand*{\@@insert@vrule}[6]{%
\@ff@getdim{#3}{#4}%
\setlength{\@ff@left@x}{\ffareax}%
\setlength{\@ff@left@y}{\ffareay}%
\setlength{\@ff@left@width}{\ffareawidth}%
\setlength{\@ff@left@height}{\ffareaheight}%
\@ff@getdim{#5}{#6}%
\ifnum\@ff@left@x>\ffareax\relax
  \@ff@swaplen{\@ff@left@x}{\ffareax}%
  \@ff@swaplen{\@ff@left@y}{\ffareax}%
  \@ff@swaplen{\@ff@left@evenx}{\ffareaevenx}%
  \@ff@swaplen{\@ff@left@eveny}{\ffareaevenx}%
  \@ff@swaplen{\@ff@left@width}{\ffareawidth}%
  \@ff@swaplen{\@ff@left@height}{\ffareaheight}%
\fi
\setlength{\@ff@tmp@x}{\@ff@left@x}
\addtolength{\@ff@tmp@x}{\@ff@left@width}%
\setlength{\@ff@staticW}{\ffareax}%
\addtolength{\@ff@staticW}{-\@ff@tmp@x}%
\setlength{\@ff@staticH}{\@ff@left@y}%
\addtolength{\@ff@staticH}{\@ff@left@height}%
\setlength{\@ff@tmp@y}{\ffareay}%
\addtolength{\@ff@tmp@y}{\ffareaheight}%
\ifnum\@ff@tmp@y>\@ff@staticH
  \setlength{\@ff@staticH}{\@ff@tmp@y}%
\fi
\ifnum\@ff@left@y<\ffareay\relax
  \setlength{\@ff@tmp@y}{\@ff@left@y}%
\else
  \setlength{\@ff@tmp@y}{\ffareay}%
\fi
\addtolength{\@ff@staticH}{-\@ff@tmp@y}%
\newstaticframe{\@ff@staticW}{\@ff@staticH}%
{\@ff@tmp@x}{\@ff@tmp@y}%
\addtolength{\@ff@staticH}{#1}%
\addtolength{\@ff@staticH}{#2}%
\setstaticcontents{\c@maxstatic}{%
\ffruledeclarations
\ffvrule{#2}{\ffcolumnseprule}{\@ff@staticH}}%
\ifcase#3\relax
\or \edef\@ff@pages{\csname @ff@pages@\romannumeral#4\endcsname}%
\or \edef\@ff@pages{\csname @sf@pages@\romannumeral#4\endcsname}%
\or \edef\@ff@pages{\csname @df@pages@\romannumeral#4\endcsname}%
\fi
\setstaticframe{\c@maxstatic}{pages=\@ff@pages}%
%    \end{macrocode}
% check the difference between odd and even page co-ordinates
% and shift new frame in same direction. (Assumes the two
% original frames stay in the same relative position.)
%    \begin{macrocode}
\addtolength{\@ff@tmp@x}{\@ff@left@evenx}%
\addtolength{\@ff@tmp@x}{-\@ff@left@x}%
\addtolength{\@ff@tmp@y}{\@ff@left@eveny}%
\addtolength{\@ff@tmp@y}{-\@ff@left@y}%
\setstaticframe{\c@maxstatic}{evenx=\@ff@tmp@x,eveny=\@ff@tmp@y}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffvrule}
%\changes{1.11}{2008/06/27}{new}
%\cs{ffvrule}\marg{offset}\marg{width}\marg{height}\par
% Draws the rule for \cs{insertvrule}
%    \begin{macrocode}
\newcommand*{\ffvrule}[3]{%
\hfill \rule[-#1]{#2}{#3}\hfill\mbox{}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sinsertvrule}
% Starred version. Two optional arguments required.
%    \begin{macrocode}
\newcommand*{\@sinsertvrule}[1][0pt]{%
\@ifnextchar[{\@@sinsertvrule[#1]}{\@@sinsertvrule[#1][0pt]}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@sinsertvrule}
% Find out the frame types and their \gls{idn}.
%    \begin{macrocode}
\def\@@sinsertvrule[#1][#2]#3#4#5#6{%
\ifthenelse{\equal{#3}{flow}}{%
\def\@ff@type@i{1}\@flowframeid{#4}\@ff@tmpN=\ff@id}{%
\ifthenelse{\equal{#3}{static}}{%
\def\@ff@type@i{2}\@staticframeid{#4}\@ff@tmpN=\ff@id}{%
\ifthenelse{\equal{#3}{dynamic}}{%
\def\@ff@type@i{3}\@dynamicframeid{#4}\@ff@tmpN=\ff@id}{%
\PackageError{flowfram}{Unknown frame
type '#3'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\ifthenelse{\equal{#5}{flow}}{%
\def\@ff@type@ii{1}\@flowframeid{#6}}{%
\ifthenelse{\equal{#5}{static}}{%
\def\@ff@type@ii{2}\@staticframeid{#6}}{%
\ifthenelse{\equal{#5}{dynamic}}{%
\def\@ff@type@ii{3}\@dynamicframeid{#6}}{%
\PackageError{flowfram}{Unknown frame
type '#5'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\@@insert@vrule{#1}{#2}{\@ff@type@i}{\@ff@tmpN}%
{\@ff@type@ii}{\ff@id}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\inserthrule}
% Now for a horizontal rule. Syntax similar to "\insertvrule".
% Determine whether or not the starred version is being
% used.
%    \begin{macrocode}
\newcommand*{\inserthrule}{\@ifstar\@sinserthrule\@inserthrule}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@inserthrule}
% Two optional arguments required.
%    \begin{macrocode}
\newcommand*{\@inserthrule}[1][0pt]{%
\@ifnextchar[{\@@inserthrule[#1]}{\@@inserthrule[#1][0pt]}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@inserthrule}
% Arguments all accounted for. Convert the frame type
% into a number to make life easier
%    \begin{macrocode}
\def\@@inserthrule[#1][#2]#3#4#5#6{%
\ifthenelse{\equal{#3}{flow}}{%
\def\@ff@type@i{1}}{\ifthenelse{\equal{#3}{static}}{%
\def\@ff@type@i{2}}{\ifthenelse{\equal{#3}{dynamic}}{%
\def\@ff@type@i{3}}{\PackageError{flowfram}{Unknown frame
type '#3'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\ifthenelse{\equal{#5}{flow}}{%
\def\@ff@type@ii{1}}{\ifthenelse{\equal{#5}{static}}{%
\def\@ff@type@ii{2}}{\ifthenelse{\equal{#5}{dynamic}}{%
\def\@ff@type@ii{3}}{\PackageError{flowfram}{Unknown frame
type '#5'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\@@insert@hrule{#1}{#2}{\@ff@type@i}{#4}{\@ff@type@ii}{#6}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@insert@hrule}
% Insert a new \gls{static} between the two specified frames.
% Check to make sure which one is on the top and which one
% is on the bottom.
% Syntax:\newline
%\cs{@@insert@hrule}\marg{x left}\marg{x right}\marg{type ID}\marg{IDN}\marg{type ID}\marg{IDN}.
%    \begin{macrocode}
\newcommand*{\@@insert@hrule}[6]{%
\@ff@getdim{#3}{#4}%
\setlength{\@ff@left@x}{\ffareax}%
\setlength{\@ff@left@y}{\ffareay}%
\setlength{\@ff@left@width}{\ffareawidth}%
\setlength{\@ff@left@height}{\ffareaheight}%
\@ff@getdim{#5}{#6}%
\ifnum\@ff@left@y>\ffareay\relax
  \@ff@swaplen{\@ff@left@x}{\ffareax}%
  \@ff@swaplen{\@ff@left@y}{\ffareay}%
  \@ff@swaplen{\@ff@left@width}{\ffareawidth}%
  \@ff@swaplen{\@ff@left@height}{\ffareaheight}%
\fi
\setlength{\@ff@tmp@y}{\@ff@left@y}%
\addtolength{\@ff@tmp@y}{\@ff@left@height}%
\setlength{\@ff@staticH}{\ffareay}%
\addtolength{\@ff@staticH}{-\@ff@tmp@y}%
\setlength{\@ff@staticW}{\@ff@left@x}%
\addtolength{\@ff@staticW}{\@ff@left@width}%
\setlength{\@ff@tmp@x}{\ffareax}%
\addtolength{\@ff@tmp@x}{\ffareawidth}%
\ifnum\@ff@tmp@x>\@ff@staticW\relax
  \setlength{\@ff@staticW}{\@ff@tmp@x}%
\fi
\ifnum\@ff@left@x<\ffareax\relax
  \setlength{\@ff@tmp@x}{\@ff@left@x}%
\else
  \setlength{\@ff@tmp@x}{\ffareax}%
\fi
\addtolength{\@ff@staticW}{-\@ff@tmp@x}%
\newstaticframe{\@ff@staticW}{\@ff@staticH}%
{\@ff@tmp@x}{\@ff@tmp@y}%
\addtolength{\@ff@staticW}{#1}%
\addtolength{\@ff@staticW}{#2}%
\setstaticcontents{\c@maxstatic}{%
\ffruledeclarations
\ffhrule{#1}{\@ff@staticW}{\ffcolumnseprule}}%
\ifcase#3\relax
\or \edef\@ff@pages{\csname @ff@pages@\romannumeral#4\endcsname}%
\or \edef\@ff@pages{\csname @sf@pages@\romannumeral#4\endcsname}%
\or \edef\@ff@pages{\csname @df@pages@\romannumeral#4\endcsname}%
\fi
\setstaticframe{\c@maxstatic}{pages=\@ff@pages}%
\addtolength{\@ff@tmp@x}{\@ff@left@evenx}%
\addtolength{\@ff@tmp@x}{-\@ff@left@x}%
\addtolength{\@ff@tmp@y}{\@ff@left@eveny}%
\addtolength{\@ff@tmp@y}{-\@ff@left@y}%
\setstaticframe{\c@maxstatic}{evenx=\@ff@tmp@x,eveny=\@ff@tmp@y}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffhrule}
%\changes{1.11}{2008/06/27}{new}
%\cs{ffhrule}\marg{offset}\marg{width}\marg{height}\par
% Draws the rule for \cs{inserthrule}
%    \begin{macrocode}
\newcommand*{\ffhrule}[3]{%
\hspace*{-#1}\rule{#2}{#3}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sinserthrule}
% Starred version. Two optional arguments required.
%    \begin{macrocode}
\newcommand*{\@sinserthrule}[1][0pt]{%
\@ifnextchar[{\@@sinserthrule[#1]}{\@@sinserthrule[#1][0pt]}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@sinserthrule}
% Find out the frame types and their \gls{idn}.
%    \begin{macrocode}
\def\@@sinserthrule[#1][#2]#3#4#5#6{%
\ifthenelse{\equal{#3}{flow}}{%
\def\@ff@type@i{1}\@flowframeid{#4}\@ff@tmpN=\ff@id}{%
\ifthenelse{\equal{#3}{static}}{%
\def\@ff@type@i{2}\@staticframeid{#4}\@ff@tmpN=\ff@id}{%
\ifthenelse{\equal{#3}{dynamic}}{%
\def\@ff@type@i{3}\@dynamicframeid{#4}\@ff@tmpN=\ff@id}{%
\PackageError{flowfram}{Unknown frame
type '#3'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\ifthenelse{\equal{#5}{flow}}{%
\def\@ff@type@ii{1}\@flowframeid{#6}}{%
\ifthenelse{\equal{#5}{static}}{%
\def\@ff@type@ii{2}\@staticframeid{#6}}{%
\ifthenelse{\equal{#5}{dynamic}}{%
\def\@ff@type@ii{3}\@dynamicframeid{#6}}{%
\PackageError{flowfram}{Unknown frame
type '#5'}{Available frame types are: 'flow', 'static'
or 'dynamic'}}}}%
\@@insert@hrule{#1}{#2}{\@ff@type@i}{\@ff@tmpN}%
{\@ff@type@ii}{\ff@id}%
}
%    \end{macrocode}
%\end{macro}
%
% \subsection{Putting Chapter Headings in Dynamic Frames}
%\begin{macro}{\dfchaphead}
% Provide facility to make chapter headings appear
% in specified \gls{dynamic}. 
% I originally called this macro "\putchapterheadingsindynamicframe"
% which was descriptive, but overly long, so I changed it
% to the rather more cryptic name "\dfchaphead".
% If the starred form is used, the frame is identified by \gls{idl},
% the unstarred form identifies the frame \gls{idn}.
%    \begin{macrocode}
\newcommand*{\dfchaphead}{%
\@ifstar\@sdynamicchap\@dynamicchap}
%    \end{macrocode}
%\end{macro}
% Define style for the chapter heading. These commands
% are should only be used when "\dfchaphead" has been used.
%\begin{macro}{\DFchapterstyle}
%    \begin{macrocode}
\newcommand{\DFchapterstyle}[1]{#1}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\DFschapterstyle}
%    \begin{macrocode}
\newcommand{\DFschapterstyle}[1]{#1}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dynamicchap}
% Unstarred version.
%    \begin{macrocode}
\newcommand{\@dynamicchap}[1]{%
\@ifundefined{chapter}{\PackageError{flowfram}{Chapters aren't 
defined}{The document
class you are using does not define chapters}}{%
\let\@ff@OLDmakechapterhead\@makechapterhead
\let\@ff@OLDmakeschapterhead\@makeschapterhead
\renewcommand{\DFchapterstyle}[1]{\@ff@OLDmakechapterhead{##1}}%
\renewcommand{\DFschapterstyle}[1]{\@ff@OLDmakeschapterhead{##1}}%
%
\xdef\@makechapterhead##1{%
\noexpand\@setdynamiccontents{\number#1}{%
\noexpand\DFchapterstyle{##1}}}%
\xdef\@makeschapterhead##1{%
\noexpand\@setdynamiccontents{\number#1}{%
\noexpand\DFschapterstyle{##1}}}%
}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sdynamicchap}
% Starred form.
%    \begin{macrocode}
\newcommand{\@sdynamicchap}[1]{%
\@dynamicframeid{#1}\@dynamicchap{\ff@id}}
%    \end{macrocode}
%\end{macro}
% There is no facility for placing other sectional types
% in \glspl{dynamic}.  This is because, either (1) the sectioning
% command does not start a new page, in which case there
% is no way of telling where exactly the new section will start,
% and having a section title in some other location on the
% page is ambiguous, and would really confuse the reader, or
% (2) in the case of "\part" in report or book class files, the
% title appears on a page of its own, so where is the point in
% putting it in a \gls{dynamic}?
%
%\subsection{Thumbtabs}
% Define counter to keep track of total number of
% thumbtabs.
%    \begin{macrocode}
\newcounter{maxthumbtabs}
%    \end{macrocode}
%\begin{macro}{\defaultthumbtabtype}
% Check to see if chapters are defined, if they are make
% thumbtabs correspond to chapters, otherwise make
% thumbtabs correspond to sections.
%    \begin{macrocode}
\@ifundefined{chapter}{%
\newcommand*{\defaultthumbtabtype}{section}}{
\newcommand*{\defaultthumbtabtype}{chapter}
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@type}
% Section type to assign to thumbtabs.
%    \begin{macrocode}
\newcommand*{\@ttb@type}{\defaultthumbtabtype}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\makethumbtabs}
% Make the thumbtabs. Read in information from ".ttb"
% file, and open it for output.
% Syntax:\newline
% \cs{makethumbtabs}\oarg{y offset}\marg{height}\oarg{sec type}.
%
% First check to see if there is a second optional argument.
%    \begin{macrocode}
\newcommand*{\makethumbtabs}[2][0pt]{%
\@ifnextchar[{\@makethumbtabs[#1]{#2}}{%
\@makethumbtabs[#1]{#2}[\defaultthumbtabtype]}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makethumbtabs}
% Now all arguments are known, first redefine the 
% appropriate sectioning command, then input the ttb file,
% and create the thumbtabs.
%    \begin{macrocode}
\def\@makethumbtabs[#1]#2[#3]{%
\@ifundefined{#3}{\PackageError{flowfram}{%
Unknown section type '#3'}{}}{%
\renewcommand{\@ttb@type}{#3}%
\ifthenelse{\equal{#3}{chapter}}{\@makethumbchapter}{%
\ifthenelse{\equal{#3}{part}}{\@makethumbpart}{%
\@makethumbsection{#3}}}}
\@starttoc{ttb}%
\@dothumbtabs{#1}{#2}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makethumbchapter}
% If thumbtabs correspond to chapters, redefine "\@chapter"
% so that each unstarred chapter writes an entry to the
% ".ttb" file.
%    \begin{macrocode}
\newcommand{\@makethumbchapter}{
\let\@ttb@old@chapter\@chapter
\def\@chapter[##1]##2{%
\@ttb@old@chapter[##1]{##2}%
\addtocontents{ttb}{\protect\thumbtab
  {\thepage}{\thechapter}{##1}{chapter.\thechapter}}%
\@afterheading
}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makethumbpart}
% For parts in books or reports, the thumbtab needs to be
% saved after the part counter has been incremented, but
% before the page break so that the page number and part
% numbers are correct. If "\@endpart" is not defined, then
% the document class probably does not start a new page after
% "\part". (This can't be guaranteed for non standard class 
% files, but there's nothing that can be done about that.)
% If this happens, just redefine "\@part", and hope for the
% best.
%    \begin{macrocode}
\newcommand{\@makethumbpart}{
\let\@ttb@old@part\@part
\@ifundefined{@endpart}{%
\def\@part[##1]##2{\@ttb@old@part[##1]{##2}%
\addtocontents{ttb}{\protect\thumbtab
  {\thepage}{\thepart}{##1}{part.\thepage}}%
\@afterheading}}{%
\let\@ttb@old@endpart\@endpart
\def\@part[##1]##2{%
\def\@parttitle{##1}%
\@ttb@old@part[##1]{##2}%
}%
\def\@endpart{%
\addtocontents{ttb}{%
\protect\thumbtab{\thepage}%
{\thepart}{\@parttitle}{part.\thepage}}%
\@ttb@old@endpart
}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makethumbsection}
% Thumbtabs defined for one of the remaining standard 
% sectioning commands. Since these commands use
% "\@startsection", it is necessary to redefine
% "\@sect" to add the thumbtab information to the .ttb file.
%    \begin{macrocode}
\newcommand*{\@makethumbsection}[1]{%
\let\@ttb@old@sect=\@sect
\def\@sect##1##2##3##4##5##6[##7]##8{%
\@ttb@old@sect{##1}{##2}{##3}{##4}{##5}{##6}[##7]{##8}%
\ifthenelse{\equal{##1}{#1}}{%
\addtocontents{ttb}{%
\protect\thumbtab{\thepage}{\csname the#1\endcsname}%
{##7}{#1.\csname the#1\endcsname}}%
\@afterheading}{}%
}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtab}
% The thumbtab file, ".ttb", will have a series of "\thumbtab"
% commands, when this file is read in, just store the 
% information for now.
%    \begin{macrocode}
\newcommand{\thumbtab}[4]{%
\stepcounter{maxthumbtabs}%
\expandafter
\gdef\csname thumbtab@pages@\romannumeral\c@maxthumbtabs\endcsname
{#1}%
\expandafter
\gdef\csname thumbtab@num@\romannumeral\c@maxthumbtabs\endcsname
{#2}%
\expandafter
\gdef\csname thumbtab@title@\romannumeral\c@maxthumbtabs\endcsname
{#3}%
\expandafter
\gdef\csname thumbtab@link@\romannumeral\c@maxthumbtabs\endcsname
{#4}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dothumbtabs}
% Once the thumbtab information has been read in and stored
% in the thumbtab macros, create the thumbtabs using this
% information.  First need to work out the \glspl{pgrange} between
% each thumbtab. If the following thumbtab starts on the
% same page as the previous one, leave the page varable
% as a single number (this may happen if the thumbtabs
% correspond to sections rather than chapters). If the
% following thumbtab starts on a different page to the
% one before it, the preceding thumbtab page variable so
% be a range from its own initial page up to the page before
% the next thumbtab starts. The final thumbtab has an open
% ended range. This final thumbtab will continue to be displayed
% until cancelled by "\disablethumbtabs".
%
% Syntax: \cs{@dothumbtabs}\marg{y offset}\marg{height}.
%    \begin{macrocode}
\newcommand*{\@dothumbtabs}[2]{%
\@colN=0\relax
\whiledo{\@colN<\c@maxthumbtabs}{%
  \advance\@colN by 1\relax
  \edef\ff@pages{%
    \csname thumbtab@pages@\romannumeral\@colN\endcsname}%
  \ifnum\@colN=\c@maxthumbtabs
    \expandafter
      \xdef\csname thumbtab@pages@\romannumeral\@colN\endcsname{%
        \ff@pages,>\ff@pages}%
  \else
    \advance\@colN by 1\relax
    \edef\ff@endpage{%
      \csname thumbtab@pages@\romannumeral\@colN\endcsname}%
    \advance\@colN by -1\relax
    \@ff@tmpN=\ff@endpage\relax
    \advance\@ff@tmpN by -1\relax
    \ifnum\@ff@tmpN>\ff@pages
      \expandafter
        \xdef\csname thumbtab@pages@\romannumeral\@colN\endcsname{%
          \ff@pages-\number\@ff@tmpN}%
    \fi
  \fi
}%
\@@dothumbtabs{#1}{#2}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabwidth}
% Default thumbtab width.
%    \begin{macrocode}
\newlength{\thumbtabwidth}
\setlength{\thumbtabwidth}{1cm}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabindexformat}
% Thumbtab format. If hyperlinks have been defined,
% use a hyperlink in the thumbtab index.
% Syntax: \cs{thumbtabindexformat}\marg{link}\marg{text}\marg{height}
%    \begin{macrocode}
\@ifundefined{hyperlink}{%
\newcommand{\thumbtabindexformat}[3]{%
\thumbtabformat{#2}{#3}}}{%
\newcommand{\thumbtabindexformat}[3]{%
\hyperlink{#1}{\thumbtabformat{#2}{#3}}}
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabformat}
% Individual thumbtab format. If rotating has
% been disabled, stack the letters vertically (this 
% doesn't look very good).
% Syntax: \cs{thumbtabformat}\marg{text}\marg{height}
%    \begin{macrocode}
\newcommand{\thumbtabformat}[2]{%
\if@ttb@rotate
\rotatebox{-90}{\parbox[c][\thumbtabwidth]{#2}{%
\centering#1}}%
\else
\parbox[c][#2]{\thumbtabwidth}{%
\centering\@ttb@stack{#1}}%
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@flf@subsp}
% Substitute spaces for \cs{space}. Stores resulting text in
% \cs{@flf@subsptext} which should be set to empty before use.
%\changes{1.10}{2007/08/21}{new}
%    \begin{macrocode}
\def\@flf@subsp#1 #2{%
\expandafter\flf@ta\expandafter{\@flf@subsptext}%
\flf@tb{#1}%
\edef\@flf@subsptext{\the\flf@ta\the\flf@tb}%
\def\@flf@tmp{#2}%
\ifx\@flf@tmp\@nnil
  \let\@flf@donextsubsp=\@gobble
\else
  \expandafter\flf@ta\expandafter{\@flf@subsptext}%
  \edef\@flf@subsptext{\the\flf@ta\noexpand\space}%
  \let\@flf@donextsubsp=\@flf@subsp
\fi
\@flf@donextsubsp{#2}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@stack}
% Stack letters vertically. 
% Any spaces first need to be substituted
% with \cs{space}, otherwise they will be ignored.
%\changes{1.10}{2007/08/21}{spaces now replaced with \cs{space}}
%    \begin{macrocode}
\newcommand{\@ttb@stack}[1]{%
\def\@flf@subsptext{}%
\expandafter\@flf@subsp#1 \@nil\relax
\begin{tabular}{l}%
\expandafter\@@ttb@stack\@flf@subsptext\@nil\relax
\end{tabular}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@ttb@stack}
%\changes{1.10}{2007/08/21}{now uses \cs{mbox}}
%    \begin{macrocode}
\def\@@ttb@stack#1#2{%
\def\@flf@tmp{#1}%
\ifx\@flf@tmp\@nnil
  \let\flf@next\relax
\else
  #1\\%
  \def\@flf@tmp{#2}%
  \ifx\@nnil#2\relax
    \let\flf@next\@gobble
  \else
    \let\flf@next\@@ttb@stack
  \fi
\fi
\flf@next{#2}}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@greyscale}
% Count register to compute the grey scale.
%    \begin{macrocode}
\newcount\@greyscale
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@dothumbtabs}
% Once the \gls{pgrange} have been sorted, create the
% \glspl{dynamic} associated with each thumbtab.
% Thumbtabs will initially have a grey background, but
% this can be changed by the user. Each thumbtab is given
% an \gls{idl} "thumbtab"\meta{n} where \meta{n} is the index of
% the thumbtab (starting from 1 for the topmost thumbtab.)
% Each frame in the thumbtab index is given an \gls{idl} 
% "thumbtabindex"\meta{n}, where \meta{n} is as before.
%    \begin{macrocode}
\newcommand{\@@dothumbtabs}[2]{%
\setlength{\@ff@tmp@y}{\textheight}%
\addtolength{\@ff@tmp@y}{-#2}%
\addtolength{\@ff@tmp@y}{-#1}%
\computerightedgeodd{\@ff@tmp@x}%
\addtolength{\@ff@tmp@x}{-\thumbtabwidth}%
\computeleftedgeeven{\@ff@tmp@x@even}%
\@ff@tmpN=0\relax
\whiledo{\@ff@tmpN<\c@maxthumbtabs}{%
  \advance\@ff@tmpN by 1\relax
  \@greyscale=\@ff@tmpN\relax
  \multiply\@greyscale by 60\relax
  \divide\@greyscale by \c@maxthumbtabs
  \advance\@greyscale by 25\relax
  \edef\@ff@greyscale{0.\number\@greyscale}%
%    \end{macrocode}
% Thumbtab
%    \begin{macrocode}
  \newdynamicframe[none]{\thumbtabwidth}{#2}%
    {\@ff@tmp@x}{\@ff@tmp@y}[thumbtab\number\@ff@tmpN]%
  \expandafter\global\expandafter
    \setlength\csname @df@\romannumeral\c@maxdynamic @evenx\endcsname
    {\@ff@tmp@x@even}%
%    \end{macrocode}
% set the contents of the dynamic frame
%    \begin{macrocode}
  \ifthenelse{\boolean{@ttb@title}\and\boolean{@ttb@num}}{%
    \expandafter
    \xdef\csname @dynamicframe@\romannumeral\c@maxdynamic\endcsname{%
    \noexpand\thumbtabformat{%
    \csname thumbtab@num@\romannumeral\@ff@tmpN\endcsname\
    \csname thumbtab@title@\romannumeral\@ff@tmpN\endcsname
    }{#2}}%
  }{%
    \if@ttb@title
      \expandafter
      \xdef\csname @dynamicframe@\romannumeral\c@maxdynamic\endcsname{%
        \noexpand\thumbtabformat{%
        \csname thumbtab@title@\romannumeral\@ff@tmpN\endcsname
        }{#2}}%
    \fi
    \if@ttb@num
      \expandafter
      \xdef\csname @dynamicframe@\romannumeral\c@maxdynamic\endcsname{%
        \noexpand\thumbtabformat{%
        \csname thumbtab@num@\romannumeral\@ff@tmpN\endcsname
        }{#2}}%
    \fi
  }%
  \expandafter
    \xdef\csname @df@backcol@\romannumeral\c@maxdynamic\endcsname
    {[gray]{\@ff@greyscale}}
%    \end{macrocode}
% Thumbtab index
%    \begin{macrocode}
  \newdynamicframe[none]{\thumbtabwidth}{#2}%
    {\@ff@tmp@x}{\@ff@tmp@y}[thumbtabindex\number\@ff@tmpN]%
  \expandafter\global\expandafter
  \setlength\csname @df@\romannumeral\c@maxdynamic @evenx\endcsname
  {\@ff@tmp@x@even}%
  \expandafter
%    \end{macrocode}
% set the contents of the dynamic frame
%    \begin{macrocode}
  \ifthenelse{\boolean{@ttb@title}\and\boolean{@ttb@num}}{%
    \expandafter
    \xdef\csname @dynamicframe@\romannumeral\c@maxdynamic\endcsname{%
      \noexpand\thumbtabindexformat{%
      \csname thumbtab@link@\romannumeral\@ff@tmpN\endcsname}{%
      \csname thumbtab@num@\romannumeral\@ff@tmpN\endcsname\
      \csname thumbtab@title@\romannumeral\@ff@tmpN\endcsname
      }{#2}}%
  }{%
    \if@ttb@title
      \expandafter
      \xdef\csname @dynamicframe@\romannumeral\c@maxdynamic\endcsname{%
        \noexpand\thumbtabindexformat{%
        \csname thumbtab@link@\romannumeral\@ff@tmpN\endcsname}{%
        \csname thumbtab@title@\romannumeral\@ff@tmpN\endcsname
        }{#2}}%
    \fi
    \if@ttb@num
    \expandafter
      \xdef\csname @dynamicframe@\romannumeral\c@maxdynamic\endcsname{%
        \noexpand\thumbtabindexformat{%
        \csname thumbtab@link@\romannumeral\@ff@tmpN\endcsname}{%
        \csname thumbtab@num@\romannumeral\@ff@tmpN\endcsname
        }{#2}}%
    \fi
  }%
  \expandafter
    \xdef\csname @df@backcol@\romannumeral\c@maxdynamic\endcsname
    {[gray]{\@ff@greyscale}}
  \addtolength{\@ff@tmp@y}{-#2}%
}%
}%
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\enablethumbtabs}
% Enable thumbtabs. Once the \gls{idn} is obtained for the
% first thumbtab, the rest can be found by incrementing the
% number by 2 (the frames in between correspond to the 
% thumbtab index.)
%    \begin{macrocode}
\newcommand*{\enablethumbtabs}{%
\ifnum\c@maxthumbtabs>0
\@ff@tmpN=0\relax
\@dynamicframeid{thumbtab1}%
\whiledo{\@ff@tmpN<\c@maxthumbtabs}{%
\advance\@ff@tmpN by 1\relax
%    \end{macrocode}
% thumbtab
%    \begin{macrocode}
\edef\@ff@pages{\csname thumbtab@pages@\romannumeral\@ff@tmpN\endcsname}%
\@@setdynamicframe{\ff@id}{pages=\@ff@pages}%
\advance\ff@id by 2\relax
}%
\else\PackageWarning{flowfram}{No thumb tabs defined}\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\disablethumbtabs}
% Disable all thumbtabs.
%    \begin{macrocode}
\newcommand*{\disablethumbtabs}{%
\ifnum\c@maxthumbtabs>0
\@ff@tmpN=0\relax
\@dynamicframeid{thumbtab1}%
\whiledo{\@ff@tmpN<\c@maxthumbtabs}{%
\advance\@ff@tmpN by 1\relax
%    \end{macrocode}
%thumbtab
%    \begin{macrocode}
\expandafter\xdef\csname @df@pages@\romannumeral\ff@id\endcsname
{none}%
\advance\ff@id by 1\relax
%    \end{macrocode}
%thumbtab index
%    \begin{macrocode}
\expandafter\xdef\csname @df@pages@\romannumeral\ff@id\endcsname
{none}%
\advance\ff@id by 1\relax
}\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabindex}
% Show thumbtab index on current page.
% The "\@ff@doafter" bit circumvents the problem of duplicate page 
% numbers, as the table of contents
% is quite frequently on page i while the first chapter starts on page 1.
%    \begin{macrocode}
\newcommand*{\thumbtabindex}{%
\ifnum\c@maxthumbtabs>0\relax
\@ff@tmpN=0\relax
\@dynamicframeid{thumbtabindex1}%
\whiledo{\@ff@tmpN<\c@maxthumbtabs}{%
\advance\@ff@tmpN by 1\relax
\expandafter
\xdef\csname @df@pages@\romannumeral\ff@id\endcsname{\c@page}%
\edef\@ff@doafter{%
\noexpand\afterpage{%
\noexpand\setdynamicframe{\number\ff@id}{pages=none}}}
\@ff@doafter
\advance\ff@id by 2\relax
}\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setthumbtab}
% Modify the settings for all the thumbtabs (including thumbtab 
% index).  Since the thumbtabs are \glspl{dynamic}
% you could just use "\setdynamicframe", however, the thumbtabs 
% will not be generated on the first run, as there will be no 
% information in the ttb file, so "\setdynamicframe" would 
% generate an error.  "\setthumbtab" will only give
% a warning message if it can not find the thumbtab. 
% The argument "#1" is the index of the thumbtab (starting 
% from 1), the second argument "#2" is the
% frame settings.
%    \begin{macrocode}
\newcommand{\setthumbtab}[2]{%
\ifthenelse{\equal{#1}{all}}{%
\@ff@tmpN=0\relax
\whiledo{\@ff@tmpN<\c@maxthumbtabs}{%
\advance\@ff@tmpN by 1\relax
\@setthumbtab{\@ff@tmpN}{#2}}}{%
\@for\@ttb@id:=#1\do{\@setthumbtab{\@ttb@id}{#2}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setthumbtab}
% Set individual thumbtab and its index tab.
%    \begin{macrocode}
\newcommand{\@setthumbtab}[2]{%
% check if this thumbtab exists
\ifthenelse{\(\c@maxthumbtabs<#1\) \or \(#1<1\)}{%
\PackageWarning{flowfram}{Can't find thumbtab number '#1', 
ttb file may not be up-to-date}}{%
\@dynamicframeid{thumbtab\number#1}%
\@@setdynamicframe{\ff@id}{#2}%
\@dynamicframeid{thumbtabindex\number#1}%
\@@setdynamicframe{\ff@id}{#2}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setthumbtabindex}
% Only change settings for the thumbtab index. This can
% take a comma-separated number list.
%    \begin{macrocode}
\newcommand{\setthumbtabindex}[2]{%
\ifthenelse{\equal{#1}{all}}{%
\@ff@tmpN=0\relax
\whiledo{\@ff@tmpN<\c@maxthumbtabs}{%
\advance\@ff@tmpN by 1\relax
\@setthumbtabindex{\@ff@tmpN}{#2}}}{%
\@for\@ttb@id:=#1\do{\@setthumbtabindex{\@ttb@id}{#2}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setthumbtabindex}
% Change setting for individual thumbtab index entry.
%    \begin{macrocode}
\newcommand{\@setthumbtabindex}[2]{%
% check if this thumbtab exists
\ifthenelse{\(\c@maxthumbtabs<#1\) \or \(#1<1\)}{%
\PackageWarning{flowfram}{Can't find thumbtab number `\number#1', 
ttb file may not be up-to-date}}{%
\@dynamicframeid{thumbtabindex\number#1}%
\@@setdynamicframe{\ff@id}{#2}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\tocandhumbtabindex}
% Do both the table of contents and the thumbtab index
%    \begin{macrocode}
\newcommand*{\tocandthumbtabindex}{%
\aligntoctrue
\tableofcontents
\thumbtabindex
\aligntocfalse
}
%    \end{macrocode}
%\end{macro}
%
% \subsection{Minitocs}
%\begin{macro}{\@ttb@minitoctype}
% Sectioning type for the minitoc, by default it is the
% same as the thumbtabs
%    \begin{macrocode}
\newcommand*{\@ttb@minitoctype}{\@ttb@type}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@starttoc}
% In order to align the table of contents with the thumbtabs,
% or to use minitocs, the toc information must be stored,
% rather than simply input.
% Therefore, modify "\@starttoc" so that it can store the contents
% of the file. "\if@storetoc" is used to determine whether
% to store the contents, or act as normal.
%    \begin{macrocode}
\let\@ttb@old@starttoc\@starttoc
\newif\if@storetoc
\@storetocfalse
\renewcommand*{\@starttoc}[1]{%
\if@storetoc
  \@ttb@storetoc{#1}%
\else
  \@ttb@old@starttoc{#1}%
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@storetoc}
% store the contents of the file with the given extension
%    \begin{macrocode}
\newcommand*{\@ttb@storetoc}[1]{%
\begingroup
\makeatletter
\@storefileconts{\jobname.#1}%
\if@filesw
 \expandafter\newwrite\csname tf@#1\endcsname
 \immediate\openout\csname tf@#1\endcsname\jobname.#1\relax
\fi
\@nobreakfalse
\endgroup}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@storefileconts}
% store the contents of named file, if it exists.
%\changes{1.10}{2007/08/21}{uses \cs{PackageInfo} instead of
% \cs{typeout}}
%    \begin{macrocode}
\newcommand*{\@storefileconts}[1]{\IfFileExists{#1}{%
\@@storefileconts\@filef@und}{%
\PackageInfo{flowfram}{No file #1.}}}
%    \end{macrocode}
%\end{macro}
% store the number of units corresponding to the 
% thumbtab type, and minitoc units. These will usually
% have the same value, but this is not always
% guaranteed.
%\begin{macro}{\c@maxtocunits}
% Total number of toc units
%    \begin{macrocode}
\newcount\c@maxtocunits
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\c@maxminitoc}
% Total number of minitoc units
%    \begin{macrocode}
\newcount\c@maxminitoc
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@storefileconts}
% Read each line in from the file, and add to the contents
% list.
%    \begin{macrocode}
\newcommand{\@@storefileconts}[1]{%
\@ifundefined{\@ttb@minitoctype}{\@ttb@minitoclevel=6\relax}{%
\expandafter\@ttb@minitoclevel\expandafter
  =\csname @ttb@\@ttb@minitoctype @level\endcsname}%
\newread\@ttb@toc
\openin\@ttb@toc=#1\relax
\c@maxtocunits=0\relax
\c@maxminitoc=0\relax
\whiledo{\not\boolean{eof}\@ttb@toc}{%
\read\@ttb@toc to\tocline
\@addtotoclist{\tocline}{\c@maxtocunits}%
}%
\closein\@ttb@toc}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@addtotoclist}
% Before each line is added to the contents list, it is
% first checked to see whether the line starts with
% "\contentsline".  If it does, then check to see if the
% sectioning type corresponds to the thumbtab level. If
% it does, then start a new list. There will be "\c@maxtocunits"
% lists, each one corresponding to each thumbtab group.
% In addition, each contents line needs to be added to 
% the minitoclists, but only if the sectioning type level
% is greater than "\@ttb@minitoctype". The number of minitoc
% lists is given by "\c@maxminitoc".
%    \begin{macrocode}
\newif\if@contsline
\newcount\@ttb@level
\newcount\@ttb@minitoclevel

\newcommand{\@addtotoclist}[2]{%
\expandafter\@checkcontentsline#1\end
\if@contsline
\expandafter\@gettype#1\end
\ifthenelse{\equal{\@ttb@contstype}{\@ttb@type}}{%
\global\advance#2 by 1\relax
}{%
}%
\fi
\@ifundefined{@toc@\romannumeral#2}{%
\flf@ta=\expandafter{#1}%
\expandafter\xdef\csname @toc@\romannumeral#2\endcsname{\the\flf@ta}}{%
\flf@ta=\expandafter{#1}%
\flf@tb=\expandafter\expandafter\expandafter{\csname @toc@\romannumeral#2\endcsname}%
\expandafter\xdef\csname @toc@\romannumeral#2\endcsname{\the\flf@tb\the\flf@ta}}%
%    \end{macrocode}
% now do minitoc stuff. If the sectioning type is unknown,
% assume it comes last
%    \begin{macrocode}
\if@minitoc
  \if@contsline
    \@ifundefined{\@ttb@contstype}{\@ttb@level=6}{%
      \@ttb@level=\csname @ttb@\@ttb@contstype @level\endcsname}%
    \relax
    \ifnum\@ttb@level=\@ttb@minitoclevel
      \global\advance\c@maxminitoc by 1\relax
      \expandafter
         \gdef\csname @minitoc@\romannumeral\c@maxminitoc\endcsname{}%
    \else
      \ifnum\@ttb@level>\@ttb@minitoclevel
        \flf@ta=\expandafter{#1}\relax
        \flf@tb=\expandafter\expandafter\expandafter
         {\csname @minitoc@\romannumeral\c@maxminitoc\endcsname}\relax
        \expandafter
          \xdef\csname @minitoc@\romannumeral\c@maxminitoc\endcsname{%
           \the\flf@tb\the\flf@ta}
      \fi
    \fi
  \fi
\fi
}
%    \end{macrocode}
%\end{macro}
% Is there already a way of determining the sectioning
% level from its name?
%    \begin{macrocode}
\def\@ttb@part@level{-1}
\def\@ttb@chapter@level{0}
\def\@ttb@section@level{1}
\def\@ttb@subsection@level{2}
\def\@ttb@subsubsection@level{3}
\def\@ttb@paragraph@level{4}
\def\@ttb@subparagraph@level{5}
%    \end{macrocode}
%\begin{macro}{\@checkcontentsline}
% Check to see if line starts with "\contentsline"
%    \begin{macrocode}
\long\def\@checkcontentsline#1#2\end{%
\ifx#1\contentsline
  \@contslinetrue
\else
  \@contslinefalse
\fi}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@gettype}
% Given that the line starts with "\contentsline", extract
% the first argument of "\contentsline" to get the sectioning
% type.
%    \begin{macrocode}
\def\@gettype\contentsline#1#2\end{%
\def\@ttb@contstype{#1}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\tableofcontents}
% Modify "\tableofcontents". It first stores the contents
% of the toc file, and then, either simply prints it on the
% page (so it appears no different to the standard
% "\tableofcontents"), or it prints it out so that each
% thumbtab unit has the same height as the thumbtabs.
% Note: this assumes that the actual table of contents
% starts at the same height as the thumbtabs. The thumbtab
% vertical position may need to be adjusted to compensate
% for space taken up by the contents title.
%    \begin{macrocode}
\newif\ifaligntoc
\aligntocfalse

\let\@ttb@old@tableofcontents\tableofcontents
\renewcommand{\tableofcontents}{%
\@storetoctrue
\@ttb@old@tableofcontents
\ifaligntoc
  \@printalignedtoc
\else
  \@printtoc
\fi
\@storetocfalse
\global\c@minitoc=0\relax}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\beforeminitocskip}
% Vertical space to add before minitoc.
%    \begin{macrocode}
\newlength\beforeminitocskip
\setlength{\beforeminitocskip}{0pt}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\afterminitocskip}
% Vertical space to add after minitoc.
%    \begin{macrocode}
\newlength\afterminitocskip
\setlength{\afterminitocskip}{\baselineskip}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dominitoc}
% Do the minitoc for unit "#1". Check first that
% minitocs have been enabled.
%    \begin{macrocode}
\newcommand*{\dominitoc}[1]{%
\if@minitoc \@dominitoc{#1}\fi}
\newcommand*{\@dominitoc}[1]{\@@dominitoc{#1}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\minitocstyle}
% Style in which to display the minitoc.
%    \begin{macrocode}
\newcommand{\minitocstyle}[1]{\normalfont\normalsize\normalcolor
#1}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@dominitoc}
% Now do the actual minitoc for unit "#1".
%    \begin{macrocode}
\newcommand*{\@@dominitoc}[1]{%
{\minitocstyle{%
\vskip\beforeminitocskip
\csname @minitoc@\romannumeral#1\endcsname}}
\vskip\afterminitocskip}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\appenddfminitoc}
% Modify "\dominitoc" so that the minitoc is appended
% to specified \gls{dynamic}. Starred version uses
% \gls{dynamic} \gls{idl}, unstarred version uses \gls{dynamic}
% \gls{idn}. I originally called this macro "\appendminitoctodynamicframe"
% but decided it was too long, for I've opted instead
% for a slightly more cryptic name.
%    \begin{macrocode}
\newcommand*{\appenddfminitoc}{%
\renewcommand{\beforeminitocskip}{\baselineskip}%
\@ifstar\@sappendminitocdf\@appendminitocdf}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sappendminitocdf}
% Starred version
%    \begin{macrocode}
\newcommand*{\@sappendminitocdf}[1]{%
\renewcommand{\@dominitoc}[1]{%
\@sappenddynamic{#1}{\@@dominitoc{##1}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@appendminitocdf}
% Unstarred version
%    \begin{macrocode}
\newcommand*{\@appendminitocdf}[1]{%
\renewcommand{\@dominitoc}[1]{%
\@appenddynamic{#1}{\@@dominitoc{##1}}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@printtoc}
% Do the table of contents, which has been stored
% in "\c@maxtocunits" macros. (or possibly 
% "\c@maxtocunits + 1", if information was added
% before the first group---which corresponds to
% "\@colN=0".)
%    \begin{macrocode}
\newcommand*{\@printtoc}{%
\@colN=0\relax
\csname @toc@\romannumeral\@colN\endcsname
\whiledo{\@colN<\c@maxtocunits}{%
\advance\@colN by 1\relax
\csname @toc@\romannumeral\@colN\endcsname}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@printalignedtoc}
% Print the table of contents so that each unit is
% has vertical height the same as the height of the
% thumbtabs. Note that you may have to adjust the
% vertical offset of the thumbtabs (in "\makethumbtabs")
% in order to make them correctly aligned.
%    \begin{macrocode}
\newcommand{\@printalignedtoc}{%
\@ff@tmpN=0\relax
\@ifundefined{@toc@\romannumeral\@ff@tmpN}{%
}{%
\csname @toc@\romannumeral\@ff@tmpN\endcsname
\par\noindent\hrulefill
}%
\whiledo{\@ff@tmpN<\c@maxtocunits}{%
\advance\@ff@tmpN by 1\relax
\ifnum\@ff@tmpN>\c@maxthumbtabs
\csname @toc@\romannumeral\@ff@tmpN\endcsname
\else
\@dynamicframeid{thumbtabindex\number\@ff@tmpN}%
\expandafter\expandafter\expandafter
\@ff@getstaticpos\csname @df@dim@\romannumeral\ff@id\endcsname
\vbox to \@ff@tmp@y{%
\noindent\parbox{\linewidth}{%
\csname @toc@\romannumeral\@ff@tmpN\endcsname}%
\vfill
\par\noindent\hrulefill
}%
\fi}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\enableminitoc}
% Make mini tocs appear at the start of given sectional unit.
%    \begin{macrocode}
\newcounter{minitoc}
\newif\if@minitoc
\@minitocfalse

\newcommand*{\enableminitoc}[1][\@ttb@type]{%
\@minitoctrue
\setcounter{minitoc}{0}%
\@ifundefined{#1}{%
\PackageError{flowfram}{Sectioning type `#1' not defined}{}}{%
\renewcommand{\@ttb@minitoctype}{#1}%
\ifthenelse{\equal{#1}{chapter}}{\@makeminitocchapter}{%
\ifthenelse{\equal{#1}{part}}{\@makeminitocpart}{%
\@makeminitocsection{#1}}}}%
}
%    \end{macrocode}
%\end{macro}
% This command should only appear in the preamble. (This
% ensures that it is used before "\tableofcontents".
%    \begin{macrocode}
\@onlypreamble{\enableminitoc}
%    \end{macrocode}
%\begin{macro}{\@makeminitocchapter}
% If minitocs are associated with chapters, redefine
% "\@chapter" so that the minitoc appears after the 
% chapter heading.
%    \begin{macrocode}
\newcommand{\@makeminitocchapter}{
\let\@mtoc@old@chapter\@chapter
\def\@chapter[##1]##2{%
\@mtoc@old@chapter[##1]{##2}%
\stepcounter{minitoc}%
\dominitoc{\c@minitoc}%
\@afterheading
}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makeminitocpart}
% Again, for parts. As before, need to redefine
% "\@endpart" if it exists, otherwise redefine
% "\@part".
%    \begin{macrocode}
\newcommand{\@makeminitocpart}{
\@ifundefined{@endpart}{%
\let\@mtoc@old@part\@part
\def\@part[##1]##2{%
\@mtoc@old@part[##1]{##2}%
\stepcounter{minitoc}%
\dominitoc{\c@minitoc}%
\@afterheading
}}{%
\let\@mtoc@old@endpart\@endpart
\def\@endpart{%
\stepcounter{minitoc}%
\dominitoc{\c@minitoc}%
\@mtoc@old@endpart
}}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makeminitocsection}
% Now for the remaining sectional units.
%    \begin{macrocode}
\newcommand{\@makeminitocsection}[1]{%
\let\@mtoc@old@sect=\@sect
\def\@sect##1##2##3##4##5##6[##7]##8{%
\@mtoc@old@sect{##1}{##2}{##3}{##4}{##5}{##6}[##7]{##8}%
\ifthenelse{\equal{##1}{#1}}{%
\stepcounter{minitoc}%
\dominitoc{\c@minitoc}\@afterheading}{}%
}}
%    \end{macrocode}
%\end{macro}
%\iffalse
%    \begin{macrocode}
%</flowfram.sty>
%    \end{macrocode}
%\fi
%\Finale
\endinput
