%\iffalse
% flowfram.dtx generated using makedtx version 1.2 (c) Nicola Talbot
% Command line args:
%   -author "Nicola Talbot"
%   -codetitle "Main Package Code"
%   -doc "flowfram-codedoc.tex"
%   -src "(flowfram.sty)\Z=>\1"
%   -src "(flowframtkutils.sty)\Z=>\1"
%   -src "(flowfram-[0-9]+-[0-9]+-[0-9]+.sty)\Z=>\1"
%   flowfram
% Created on 2026/6/19 16:46
%\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) 2026 Nicola Talbot, all rights reserved.
% \fi
% \iffalse
%<*driver>
\iffalse
flowfram-codedoc.tex is a stub file used by makedtx to create
flowfram.dtx
\fi

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{tcolorbox}
\RequirePackage{hologo}

\usepackage{doc}
\usepackage[nomain]{glossaries-extra}

\CheckSum{37358}

\RecordChanges
\PageIndex

\SetupDoc{reportchangedates}
\setcounter{IndexColumns}{2}

\newglossary*{terms}{Terms}

\MakeShortVerb"
\DeleteShortVerb|

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

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

\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=terms}

\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=terms}

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

\newabbreviation[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}

\newabbreviation[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}

\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=terms}

\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=terms}

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

\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=terms}

\definecolor{defbackground}{rgb}{1,1,0.75}

\newtcolorbox{definition}{halign=flush left,
 colframe=black,colback=defbackground,
 fontupper=\ttfamily,
 before upper={\frenchspacing\obeylines},
 after={\par\noindent\ignorespacesafterend}
}

\NewDocElement{Option}{option}
\NewDocElement{Counter}{counter}

\providecommand{\sty}[1]{\textsf{#1}}
\providecommand{\cls}[1]{\textsf{#1}}
\providecommand{\env}[1]{\textsf{#1}}
\providecommand{\opt}[1]{\textsf{#1}}
\providecommand{\file}[1]{\nolinkurl{#1}}

\providecommand\marg[1]{%
  \texorpdfstring{\allowbreak{\ttfamily\char`\{}\meta{#1}{\ttfamily\char`\}}}
  {\{#1\}}}
\providecommand\oarg[1]{%
  \texorpdfstring{\allowbreak{\ttfamily[}\meta{#1}{\ttfamily]}}
  {[#1]}}

\newcommand*{\LuaLaTeX}{\hologo{LuaLaTeX}}
\newcommand*{\pdfLaTeX}{\hologo{pdfLaTeX}}

\begin{document}
\DocInput{flowfram.dtx}
\end{document}
%</driver>
%\fi
%
%\title{Documented Source Code for flowfram.sty v2.3}
%\author{Nicola L. C. Talbot}
%\date{2026-06-19}
%\maketitle
%
%This is the documented source code for the flowfram package.
%For a user manual, see \url{flowfram-manual.pdf} (or do \texttt{texdoc
%flowfram-manual}).
%
%\tableofcontents
%
%\printunsrtglossary[type=terms]
%
%\StopEventually{\clearpage\PrintChanges\PrintIndex}
%
%
%\section{Main Package 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}
%    \end{macrocode}
% Rollback release:
%    \begin{macrocode}
\DeclareRelease{v1.17}{2014-09-30}{flowfram-2014-09-30.sty}
\DeclareRelease{v1.18}{2025-08-23}{flowfram-2025-08-23.sty}
\DeclareCurrentRelease{v2.3}{2026-06-19}
%    \end{macrocode}
%Declare package:
%    \begin{macrocode}
\ProvidesPackage{flowfram}[2026/06/19 v2.3 (NLCT)]
%    \end{macrocode}
%Version 2.0 now loaded rerunfilecheck package:
%    \begin{macrocode}
\RequirePackage{rerunfilecheck}
%    \end{macrocode}
% No longer loading xfor, ifthen or xkeyval.
%\changes{2.0}{2025-11-24}{no longer loading xfor, ifthen, xkeyval}
%    \begin{macrocode}
\RequirePackage{graphics}
\RequirePackage{afterpage}
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{now loading xfor and etoolbox}
%    \begin{macrocode}
\RequirePackage{etoolbox}
%    \end{macrocode}
%
% Version 2.0: switching to \LaTeX3 commands but some old code
% still remains.
%    \begin{macrocode}
\ExplSyntaxOn
%    \end{macrocode}
%
% The colour of the \gls{bbox} borders when the draft 
% option is specified is given by the commands:
%\begin{macro}{\setffdraftcolor}
%    \begin{macrocode}
\newcommand{\setffdraftcolor}{\color[gray]{0.8}}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setffdrafttypeblockcolor}
%    \begin{macrocode}
\newcommand{\setffdrafttypeblockcolor}{\color[gray]{0.9}}
%    \end{macrocode}
%\end{macro}
%\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.
%    \begin{macrocode}
\newlength\fflabelsep
\setlength\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}
% Allow user the option to show particular types of bounding
% boxes.
%    \begin{macrocode}
\newif\ifshowtypeblock
\newif\ifshowmargins
\newif\ifshowframebbox
%    \end{macrocode}
%\begin{macro}{\@ffdraft}
%\changes{2.0}{2025-11-24}{renamed}
% Set all draft settings.
%Version 2.0 renamed \cs{@ffdraft}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_draft:
 {
  \showtypeblocktrue
  \showmarginstrue
  \showframebboxtrue
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ffnodraft}
%\changes{2.0}{2025-11-24}{renamed}
% Unset all draft settings.
%Version 2.0 renamed \cs{@ffnodraft}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_final:
 {
  \showtypeblockfalse
  \showmarginsfalse
  \showframebboxfalse
 }
%    \end{macrocode}
% Set the default to \opt{final}:
%    \begin{macrocode}
\__flowfram_set_final:
%    \end{macrocode}
%\end{macro}
%
%Just in case something has redefined \cs{frame} (for example,
%\cls{beamer}, although it would be a unusual to use \sty{flowfram}
%with that).
%    \begin{macrocode}
\cs_new_protected:Nn \flowfram_frame:n
 {
   \leavevmode
   \hbox
    {
     \hskip -\@wholewidth
     \vbox
      {
        \vskip -\@wholewidth
        \hrule \@height \@wholewidth
        \hbox
         {
           \vrule \@width \@wholewidth
           #1
           \vrule \@width \@wholewidth 
         }
        \hrule \@height \@wholewidth
        \vskip -\@wholewidth
      }
     \hskip -\@wholewidth 
    }
 }
%    \end{macrocode}
%
%\begin{macro}{\flf@message}
% Messaging system (to help debugging):
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{flf@message}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_message:n
 {
  \flf@doifverbose
   {
     \msg_note:nn { flowfram } { #1 }
   }
 }
\cs_new:Nn \__flowfram_message:nn
 {
  \flf@doifverbose
   {
     \msg_note:nnn { flowfram } { #1 } { #2 }
   }
 }
\cs_new:Nn \__flowfram_message:nnn
 {
  \flf@doifverbose
   {
     \msg_note:nnnn { flowfram } { #1 } { #2 } { #3 }
   }
 }
\cs_generate_variant:Nn \__flowfram_message:nnn { nen , nee }
\cs_new:Nn \__flowfram_message:nnnn
 {
  \flf@doifverbose
   {
     \msg_note:nnnnn { flowfram } { #1 } { #2 } { #3 } { #4 }
   }
 }
\cs_generate_variant:Nn \__flowfram_message:nnnn { neee }
\cs_new:Nn \__flowfram_message:nnnnn
 {
  \flf@doifverbose
   {
     \msg_note:nnnnnn { flowfram } { #1 } { #2 } { #3 } { #4 } { #5 }
   }
 }
\cs_generate_variant:Nn \__flowfram_message:nnnnn
  { nnnen , nnneV , nnnev }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_error:nnn
 {
   \msg_error:nnnn { flowfram } { #1 } { #2 } { #3 }
 }
\cs_generate_variant:Nn \__flowfram_error:nnn
 { eee }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_error:nnnn
 {
   \msg_error:nnnnn { flowfram } { #1 } { #2 } { #3 } { #4 }
 }
\cs_generate_variant:Nn \__flowfram_error:nnnn
 { eeee }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_error:nnnnn
 {
   \msg_error:nnnnnn { flowfram } { #1 } { #2 } { #3 } { #4 } { #5 }
 }
\cs_generate_variant:Nn \__flowfram_error:nnnnn 
 { eeeee }
%    \end{macrocode}
%
%\begin{macro}{\flf@doifverbose}
%\changes{1.14}{2012-11-10}{new}
% Initialise:
%    \begin{macrocode}
\newcommand{\flf@doifverbose}[1]{}
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\char_set_catcode_space:n { `\ }

\msg_new:nnnn {flowfram} {label-defined}
 {Label `#1' already defined for frame type `#2'}
 {You can't assign this label, as it is already defined
  for #2 frame IDN #3}

\msg_new:nnnn {flowfram} {label-undefined}
 {Label `#1' is not defined for any #2 frame}
 {Check that you have spelt the label correctly and that
  the label corresponds to a #2 frame}

\msg_new:nnnn {flowfram} {invalid-width}
 {Invalid width #1 for #2 frame (using #3 instead)}
 {A #2 frame width must be greater than 0pt}

\msg_new:nnnn {flowfram} {invalid-height}
 {Invalid height #1 for #2 frame (using #3 instead)}
 {A #2 frame height must be greater than 0pt}

\msg_new:nnnn {flowfram} {idn-undefined}
 {No #1 frame with IDN #2}
 {Identification numbers start from 1 to the number of defined #1 frames}

\msg_new:nnnn {flowfram} {invalid-id}
 {Invalid IDN #1}
 {Identification numbers start from 1}

\msg_new:nnnn {flowfram} {attribute-type-change}
 {Frame attribute #1 of type '#2' now being defined as '#3'}
 {Frame attribute #1 has already been defined as type '#2' but
 now this attribute is being defined as type '#3'}

\msg_new:nnnn {flowfram} {invalid-frame-type}
 {Unknown frame type `#1'}
 {Frame types can be one of: flow, static or dynamic}

\msg_new:nnnn {flowfram} {invalid-frame-typeid}
 {Unknown frame type ID `#1'}
 {Frame type IDs can be one of: 1 (flow), 2 (static) or 3 (dynamic)}

\msg_new:nnn {flowfram} {frame-unsupported-options}
 {Frame type `#1' does not support option(s): #2}

\msg_new:nnnn {flowfram} {frame-unknown-tag}
 {Frame type `#1' does not have #4 attribute #2 defined (IDN #3)}
 {Check that you have correctly spelt the attribute `#2' and have
correctly identified the type of frame and its numeric identifier.
The other possibility is that there is a bug in the code that's
incorrectly identified the underlying data type (#4).}

\msg_new:nnn {flowfram} {non-void-box}
 {Box #1 is not void.  Dumping. This page: #2.
  Page list: "#3".  Exclusion list: "#4". 
  (Maybe the page list was changed after this frame was
  selected or maybe you should use package option pages=absolute)}

\msg_new:nnn {flowfram} {invalid-bool}
 {Invalid boolean setting `#1' for attribute `#2' applied to #3 frame IDN #4}

\msg_new:nnnn {flowfram} {invalid-pagelist}
 {Invalid page list `#1'}
 {A page list may be one of the keywords `all', `none', `even' or
 `odd', or may be an ordered comma-separated list of individual
  numbers (e.g. `2'), a closed range (e.g. `12-18'), or an
  open-ended range (e.g. `<3' or `>5'). Overlapping ranges are not
  permitted and items must be listed in increasing numerical order
  (e.g. `<4,9-12,15,>20')}

\msg_new:nnnn {flowfram} {cant-set-column}
 {Can't set current column to frame `#1' (so such frame)}
 {There is no frame defined with the IDN `#1'}

\msg_new:nnn {flowfram} {unequal-cols}
 {Moving to flow frame of unequal width, use of 
  \token_to_str:N \framebreak \c_space_tl advised, 
  or text might not appear correctly (difference = #1,
  tolerance = #2)}

\msg_new:nnn {flowfram} {no-page1-col}
 {Can't find a flow frame on page 1.
  Attempting to find the first page with a flow frame}

\msg_new:nnn {flowfram} {no-cols}
 {No flow frames, adding #1}

\msg_new:nnn {flowfram} {no-more-cols-on-page}
 {Run out of flows frames on page #1, adding new one}

\msg_new:nnn {flowfram} {misplaced-col-cmd}
 {Found #1 in document environment with 
 column-changes=switch option set but no frame
 has been identified to use with #1}

\msg_new:nnnn {flowfram} {doc-env-only}
 {Command #1 only permitted in document environment}
 {You can't use #1 in the preamble}

\msg_new:nnn {flowfram} {background-not-first}
 {Background frame is not first static frame to be 
  defined. All previously defined static frames may be 
  obscured.}

\msg_new:nnn {flowfram} {ignoring-multiple-makethumbtabs}
 {Ignoring repeated instance of \makethumbtabs}

\msg_new:nnn {flowfram} {no-thumbtabs-missing-makethumbtabs}
 {No thumb tabs defined: missing \makethumbtabs}

\msg_new:nnn {flowfram} {no-thumbtabs-rerun}
 {No thumb tabs defined. Rerun may be required}

\msg_new:nnn {flowfram} {cant-find-thumbtab}
 {Can't find thumbtab number `#1', ttb file may not be
 up-to-date}

\msg_new:nnnn {flowfram} {cant-find-thumbtab-index}
 {Can't find thumbtab index number `#1'}
 {Something's gone wrong. The thumbtab `#1' exists but 
  thumbtab index `#1' doesn't}

\msg_new:nnnn {flowfram} {invalid-thumbtab-index}
 {Invalid thumbtab index `#1'}
 {Thumbtab indexing starts at 1}

\msg_new:nnn {flowfram} {section-unit-not-defined}
 {Sectioning type `#1' not defined}

\msg_new:nnn {flowfram} {unknown-heading-cmd}
 {Unknown heading command `#1'}

\msg_new:nnn {flowfram} {unknown-shape}
 {Unknown shape #1}

\msg_new:nnn {flowfram} {forbidden-cmd-in-shape}
 {You can't use #1 within a paragraph shaped with #2}

\msg_new:nnnn {flowfram} {cant-continue}
 {Can't continue to new frame: either not in static or dynamic frame or attempting to append content}
 {\token_to_str:N \continueonframe \c_space_tl may only
  be used inside `staticcontents' or `dynamiccontents'
  environments (or their starred versions) or in the commands 
  \token_to_str:N \setstaticcontents \c_space_tl or
  \token_to_str:N \setdynamiccontents}

\msg_new:nnnn {flowfram} {invalid-num-frames}
 {You have requested #2 #1 frames!}
 {The number of frames must be greater than 0}

\msg_new:nnnn {flowfram} {no-chapters}
 {Chapters aren't defined}
 {The document class you are using does not support chapters}

\msg_new:nnnn {flowfram} {option-too-late}
 {Option #1 occurring too late (has no effect after #2)}
 {If you want to set this option, you need to do so earlier}

\msg_new:nnn {flowfram} {relloc-label-already-defined}
 {Relative location label `#1' multiply defined}

\msg_new:nnn {flowfram} {relloc-label-not-defined}
 {Relative location label `#1' undefined}

\msg_new:nnn {flowfram} {data-changed-rerun}
 {Label or frame data has changed. Rerun required}

\msg_new:nnn {flowfram} {info-set-excludelist}
 {Setting exclusion list for #1 frame IDN #2 to `#3'}

\msg_new:nnn {flowfram} {info-switching-col}
 {Switching to flow frame #1 on page #2}

\msg_new:nnn {flowfram} {info-setting-col}
 {Setting contents of box for flow frame #1}

\msg_new:nnn {flowfram} {info-doing-col}
 {Doing flow frame #1 (page #2)}

\msg_new:nnn {flowfram} {info-col-not-required}
 {Flow frame #1 is not required on page #2}

\msg_new:nnn {flowfram} {info-col-list}
 {List of defined flow frames: #1}

\msg_new:nnn {flowfram} {info-static-frame-hidden}
 {Static frame IDN #1 is hidden (#2=true)}

\msg_new:nnn {flowfram} {info-dynamic-frame-hidden}
 {Dynamic frame IDN #1 is hidden (#2=true)}

\msg_new:nnn {flowfram} {info-no-file}
  {No file #1.}

\msg_new:nnn {flowfram} {info-no-rotation}
  {Frame rotation has been disable. 
   Attempt to rotate frame has been ignored.}

\msg_new:nnn {flowfram} {info-found-thumbtab}
 {Found thumbtab data { #1 } { #2 } { #3 } { #4 }}

\msg_new:nnn {flowfram} {info-thumbtab}
 {Thumbtab #1 dynamic frame #2 (IDN #3)}

\msg_new:nnn {flowfram} {info-thumbtab-index}
 {Thumbtab index #1 dynamic frame #2 (IDN #3)}

\msg_new:nnn {flowfram} {info-setting-frame-attribute}
 {Setting #1 attribute for #2 frame #3 to #4}

\msg_new:nnn {flowfram} {show-frame-attributes}
 {Frame type #1 IDN #2 has the following attributes:\\#3}

\msg_new:nnn {flowfram} {show-all-frames-none}
 {There are no frames of type #1}

\msg_new:nnn {flowfram} {show-all-frames}
 {Showing all #1 frames. 
  Each frame will be shown separately.
  Total number of #1 frames: \\#2}

\char_set_catcode_ignore:n { `\ }
%    \end{macrocode}
%
%Separate option to rotate thumbtab text from option to inhibit all
%frame rotation.
%    \begin{macrocode}
\bool_new:N \l__flowfram_allow_frame_rotation_bool
\bool_set_true:N \l__flowfram_allow_frame_rotation_bool
%    \end{macrocode}
%
%\begin{macro}{\if@ttb@rotate}
% Settings to adjust rotation support in the thumbtabs.
%\changes{1.14}{2012-11-10}{changed to boolean key}
% Version 2.0 replaced \cs{if@ttb@rotate},
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%No rotation (the frame will need to be wide enough to accommodate
%the text or have rotation applied):
%    \begin{macrocode}
\cs_new:Nn \__flowfram_thumbtab_fmt:nn
 {
   \__flowfram_thumbtab_fmt_sideways:nn { #1 } { #2 }
 }
%    \end{macrocode}
%Rotate for right / odd pages.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_thumbtab_fmt_sideways_oneside_right:nn 
 {
    \rotatebox { -90 }
     {
       \parbox [ c ] [ \thumbtabwidth ] { #2 }
        {
          \centering #1
        }
     }
 }
%    \end{macrocode}
%Rotate for left / even pages.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_thumbtab_fmt_sideways_oneside_left:nn 
 {
    \rotatebox { 90 }
     {
       \parbox [ c ] [ \thumbtabwidth ] { #2 }
        {
          \centering #1
        }
     }
 }
%    \end{macrocode}
%Rotate according to one or two-sided documents.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_thumbtab_fmt_sideways:nn 
 {
   \if@twoside
     \int_if_odd:nTF { \c@page }
      {
        \__flowfram_thumbtab_fmt_sideways_oneside_right:nn
          { #1 } { #2 }
      }
      {
        \__flowfram_thumbtab_fmt_sideways_oneside_left:nn
          { #1 } { #2 }
      }
   \else
     \__flowfram_thumbtab_fmt_sideways_oneside_right:nn
   \fi
 }
%    \end{macrocode}
% Stack the letters vertically (this 
% doesn't look very good).
%    \begin{macrocode}
\cs_new:Nn \__flowfram_thumbtab_fmt_stack:nn
 {
   \parbox [ c ] [ #2 ] { \thumbtabwidth }
    {
      \centering 
      \flowfram_thumbtab_stack:n { #1 }
    }
 }
%    \end{macrocode}
%
% Should the thumbtabs include number, title, both or
% neither?
%\begin{macro}{\if@ttb@num}
% Version 2.0 removed \cs{if@ttb@num}.
%\changes{2.0}{2025-11-24}{removed}
%    \begin{macrocode}
\bool_new:N \l__flowfram_ttb_show_number_bool
\bool_set_false:N \l__flowfram_ttb_show_number_bool
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\if@ttb@title}
%    \begin{macrocode}
\bool_new:N \l__flowfram_ttb_show_title_bool
\bool_set_true:N \l__flowfram_ttb_show_title_bool
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@pages@countreg}
%\changes{1.14}{2012-11-10}{new}
% The default is relative (for backwards compatibility).
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed \cs{@ff@pages@countreg}.
%    \begin{macrocode}
\tl_new:N \g__flowfram_pagecounter_tl
\tl_gset:Nn \g__flowfram_pagecounter_tl { \c@page }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\theFramePageCounter}
%\changes{2.0}{2025-11-24}{new}
%For use when the page/absolutepage counter needs to be written as
%its actual value (not formatted) but must be deferred.
%    \begin{macrocode}
\newcommand \theFramePageCounter
 {
   \int_eval:n { \g__flowfram_pagecounter_tl }
 }
%    \end{macrocode}
%\end{macro}
%\begin{counter}{absolutepage}
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcounter{absolutepage}
%    \end{macrocode}
%\end{counter}
%
%\begin{macro}{\flowfram@thepagenumber}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \flowfram@thepagenumber { \int_use:N \c@page }
%    \end{macrocode}
%\end{macro}
%Constants.
%    \begin{macrocode}
\tl_const:Nn \c_flowfram_all_tl { all }
\tl_const:Nn \c_flowfram_odd_tl { odd }
\tl_const:Nn \c_flowfram_even_tl { even }
\tl_const:Nn \c_flowfram_none_tl { none }
\tl_const:Nn \c_flowfram_color_none_tl {  { none } }
\tl_const:Nn \c_flowfram_color_black_tl {  { black } }
\tl_const:Nn \c_flowfram_inner_tl { inner }
\tl_const:Nn \c_flowfram_outer_tl { outer }
\tl_const:Nn \c_flowfram_left_tl { left }
\tl_const:Nn \c_flowfram_right_tl { right }
\tl_const:Nn \c_flowfram_compute_tl { compute}
%    \end{macrocode}
%\changes{2.1}{2026-02-23}{added frame type label constants}
%    \begin{macrocode}
\tl_const:Nn \c_flowfram_flow_tl { flow }
\tl_const:Nn \c_flowfram_dynamic_tl { dynamic }
\tl_const:Nn \c_flowfram_static_tl { static }
%    \end{macrocode}
%Integer constants:
%    \begin{macrocode}
\int_const:Nn \c_flowfram_max_page_int { 100000 }
\int_const:Nn \c_flowfram_shape_type_parshape_int { 1 }
\int_const:Nn \c_flowfram_shape_type_shapepar_int { 2 }
\int_const:Nn \c_flowfram_shape_type_none_int { 0 }
\int_const:Nn \c_flowfram_frame_type_flow_int { 1 }
\int_const:Nn \c_flowfram_frame_type_static_int { 2 }
\int_const:Nn \c_flowfram_frame_type_dynamic_int { 3 }
%    \end{macrocode}
%
%\begin{macro}{\flowframecol}
%Default frame border colour.
%    \begin{macrocode}
\newcommand \flowframecol { }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframetextcol}
%Default text colour.
%    \begin{macrocode}
\newcommand \flowframetextcol { }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@fr@meifdraft}
% Draw \gls{bbox}.
%Version 2.0 renamed \cs{@fr@meifdraft}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_if_draft:nnn
 {
  \tl_set_eq:NN
     \l__flowfram_backcolor_tl
     \c_flowfram_color_none_tl
  #1
  \flowfram_frame:n { #2 }
  \tl_if_empty:nF { #3 }
   {
     \makebox [ 0pt ] [ l ]
      {
        \hskip \fflabelsep
        \fflabelfont { #3 }
      }
   }
}
\cs_new:Nn \__flowfram_do_if_draft:nn
 {
   \__flowfram_do_if_draft:nnn
    { \setffdraftcolor } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_draft_annote:nnn
 {
   [ #1 : #2 ; #3 ]
 }
\cs_new:Nn \flowfram_draft_annote:nn
 {
   [ #1 : #2 ]
 }
%    \end{macrocode}
% Colour setting commands, do nothing by default:
%\begin{macro}{\@s@tffcol}
%Set frame border colour.
%Version 2.0 renamed \cs{@s@tffcol}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_border_color: { }
\tl_new:N \l__flowfram_bordercolor_tl
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tfftextcol}
%\changes{2.0}{2025-11-24}{renamed}
%Set text colour.
%Version 2.0 renamed \cs{@s@tfftextcol}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_text_color: { }
\tl_new:N \l__flowfram_textcolor_tl
%    \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.
% Version 2.0 renamed \cs{@ffbackground}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_background_box:n { #1 }
\tl_new:N \l__flowfram_backcolor_tl
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@enablecolor}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{removed}
% Enable colour commands.
% Version 2.0 renamed \cs{@ff@enablecolor}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_enable_color:
 {
  \tl_set_eq:NN \flowframecol \c_flowfram_color_black_tl
  \tl_set_eq:NN \flowframetextcol \c_flowfram_color_black_tl
  \cs_set:Nn \__flowfram_set_border_color:
   {
     \exp_args:Ne \__flowfram_color:n 
       { \l__flowfram_bordercolor_tl }
   }
  \cs_set:Nn \__flowfram_set_text_color:
   {
     \exp_args:Ne \__flowfram_color:n 
       { \l__flowfram_textcolor_tl }
   }
  \cs_set:Nn \__flowfram_background_box:n
   {
     \exp_args:Ne 
     \__flowfram_background_box:nn
       { \l__flowfram_backcolor_tl } { ##1 } 
   }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \__flowfram_if_no_color:n
   { T, F, TF }
 {
   \tl_if_empty:nTF { #1 }
     { \prg_return_true: }
    {
      \tl_if_eq:NnTF \c_flowfram_color_none_tl { #1 }
        { \prg_return_true: }
        { \prg_return_false: }
    }
 }
\cs_new:Nn \__flowfram_color:n
 {
   \__flowfram_if_no_color:nF 
    { #1 }
    { \color #1 }
 }
\cs_new:Nn \__flowfram_background_box:nn
 {
   \__flowfram_if_no_color:nTF { #1 }
     { #2 }
     {
       \group_begin:
         \dim_zero:N \fboxsep
         \colorbox #1 { #2 }
       \group_end:
     }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@disablecolor}
%\changes{1.14}{2012-11-10}{new}
% Disable colour commands.
% Version 2.0 renamed \cs{@ff@disablecolor}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_disable_color:
 {
  \tl_clear:N \flowframetextcol
  \tl_clear:N \flowframecol
  \cs_set:Nn \__flowfram_set_border_color: { }
  \cs_set:Nn \__flowfram_set_text_color: { }
  \cs_set_eq:NN \__flowfram_background_box:n \use:n
 }
%    \end{macrocode}
%\end{macro}
%
%\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}
%
%To minimize the number of output routine kernel commands that need
%to be redefined in order to place all frames in their chosen
%locations (including header and footer frames), version 2.0 now
%switches on two column mode. This can cause some standard commands
%to switch back and forth between one column and two column mode
%(for example, \cs{tableofcontents} with the book or report class).
%Since \cs{onecolumn} and \cs{twocolumn} are changed by
%\sty{flowfram} to create one or two column layouts, this can be
%problematic. So v2.0 now has the "column-changes" option, which
%governs what to do if \cs{onecolumn} or \cs{twocolumn} are
%encountered in the document. The default is to do just clear the
%page but don't switch the layout (if the
%optional argument of \cs{twocolumn} is present then that is simply
%added to the current frame).
%    \begin{macrocode}
\bool_new:N \g__flowfram_ignore_column_changes_bool
\bool_gset_true:N \g__flowfram_ignore_column_changes_bool
%    \end{macrocode}
%Determine whether or not to clear page (not applicable if switcher
%columns identified).
%    \begin{macrocode}
\bool_new:N \g__flowfram_clearpage_column_changes_bool
\bool_gset_false:N \g__flowfram_clearpage_column_changes_bool
%    \end{macrocode}
%
%Only make thumbtabs for unnumbered units if the following boolean
%is set.
%    \begin{macrocode}
\bool_new:N \g__flowfram_save_nonum_thumbtabs_bool
%    \end{macrocode}
%\begin{macro}{\ifaligntoc}
%This is now moved into options. Instead of using
%\cs{tocandthumbtabindex}, use the toc-thumbtab option.
%    \begin{macrocode}
\newif\ifaligntoc
\aligntocfalse
\bool_new:N \l__flowfram_thumbtabs_in_toc_bool
\bool_set_false:N \l__flowfram_thumbtabs_in_toc_bool
\bool_new:N \l__flowfram_thumbtabs_span_toc_bool
\bool_set_false:N \l__flowfram_thumbtabs_span_toc_bool
%    \end{macrocode}
%\end{macro}
%Indicates whether or not the sectioning commands have a second
%optional argument.
%    \begin{macrocode}
\bool_new:N \l__flowfram_section_header_opt_bool
\IfClassLoadedTF { memoir }
 {
   \bool_set_true:N \l__flowfram_section_header_opt_bool
 }
 {
   \bool_set_false:N \l__flowfram_section_header_opt_bool
 }
\bool_new:N \l__flowfram_section_header_opt_thumbtab_bool 
\bool_set_true:N \l__flowfram_section_header_opt_thumbtab_bool 
%    \end{macrocode}
%Indicates whether or not the section unit first optional argument
%may be a key=value list (for example with KOMA's
%headings=optiontoheadandtoc setting).
%    \begin{macrocode}
\bool_new:N \l__flowfram_section_keyval_opt_bool
\bool_set_false:N \l__flowfram_section_keyval_opt_bool
%    \end{macrocode}
%Provide keys if the above is true:
%    \begin{macrocode}
\tl_new:N \l__flowfram_section_opti_tl
\tl_new:N \l__flowfram_section_optii_tl
\tl_new:N \l__flowfram_section_toc_tl
\tl_new:N \l__flowfram_section_head_tl
\keys_define:nn { flowfram / section }
 {
    head .tl_set:N = \l__flowfram_section_head_tl ,
    tocentry .tl_set:N = \l__flowfram_section_toc_tl ,
    toc .tl_set:N = \l__flowfram_section_toc_tl ,
 }
%    \end{macrocode}
%If \sty{hyperref} package is loaded, automatically enable
%hyperlinks for thumtab index.
%\begin{macro}{\thumbtabhyperlinkformat}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\NewDocumentCommand \thumbtabhyperlinkformat { m m m }
 {
    \thumbtabformat { #2 } { #3 }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\AddToHook
  { package / hyperref / after }
  {
    \RenewDocumentCommand \thumbtabhyperlinkformat { m m m }
     {
        \hyperlink { #1 } { \thumbtabformat { #2 } { #3 } }
     }
  }
%    \end{macrocode}
%
%By default, only the thumbtab indexes have hyperlinks (if
%supported).
%\begin{macro}{\thumbtabindexformat}
% Thumbtab format. If hyperlinks are defined,
% use a hyperlink in the thumbtab index.
% Syntax: \cs{thumbtabindexformat}\marg{link}\marg{text}\marg{height}
%    \begin{macrocode}
\newcommand \thumbtabindexformat [ 3 ]
 {
   \thumbtabhyperlinkformat { #1 } { #2 } { #3 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabregularformat}
%\changes{2.0}{2025-11-24}{new}
%Format for non-index thumbtabs.
%    \begin{macrocode}
\newcommand \thumbtabregularformat [ 3 ]
 {
   \thumbtabformat { #2 } { #3 }
 }
%    \end{macrocode}
%\end{macro}
%
%Should thumbtabs be created outside the main matter?
%    \begin{macrocode}
\bool_new:N \g__flowfram_frontmatter_bool
\bool_gset_false:N \g__flowfram_frontmatter_bool
\bool_new:N \g__flowfram_backmatter_bool
\bool_gset_false:N \g__flowfram_backmatter_bool
\cs_if_exist:cTF { if@mainmatter }
 {
   \prg_new_conditional:Nnn \flowfram_if_mainmatter:
      { T, F, TF }
    {
      \legacy_if:nTF { @mainmatter }
        { \prg_return_true: }
        { \prg_return_false: }
    }
   \cs_if_exist:NT \frontmatter
    {
      \appto \frontmatter
       {
         \bool_gset_true:N \g__flowfram_frontmatter_bool
         \bool_gset_false:N \g__flowfram_backmatter_bool
       }
    }
   \cs_if_exist:NT \backmatter
    {
      \appto \backmatter
       {
         \bool_gset_false:N \g__flowfram_frontmatter_bool
         \bool_gset_true:N \g__flowfram_backmatter_bool
         \__flowfram_write_backmatter_ttb:
         \__flowfram_backmatter_setsecnumdepth:
       }
    }
   \cs_if_exist:NT \mainmatter
    {
      \appto \mainmatter
       {
         \bool_gset_false:N \g__flowfram_frontmatter_bool
         \bool_gset_false:N \g__flowfram_backmatter_bool
       }
    }
 }
 {
   \prg_new_conditional:Nnn \flowfram_if_mainmatter:
      { T, F, TF }
    {
       \prg_return_true:
    }
 }
\cs_new:Nn \__flowfram_ttb_notmainmatter_num:n
 {
   \bool_if:NF \g__flowfram_frontmatter_bool
     {
       \__flowfram_ttb_num:n { #1 }
     }
 }
%    \end{macrocode}
% change the secnumdepth counter in the backmatter if applicable
%    \begin{macrocode}
\cs_new:Nn \__flowfram_backmatter_setsecnumdepth:
 {
   \setcounter { secnumdepth } { -1 }
 }
%    \end{macrocode}
%Case changing command used by dynamic header.
%    \begin{macrocode}
\cs_new:Nn \flowfram_header_case:n { #1 }
\cs_new:Nn \flowfram_subheader_case:n { #1 }
%    \end{macrocode}
%Font used by dynamic header.
%    \begin{macrocode}
\cs_new:Nn \flowfram_header_font:n { \emph { #1 } }
\cs_new:Nn \flowfram_subheader_font:n { \flowfram_header_font:n { #1 } }
\cs_new:Nn \__flowfram_adjust_page_styles:n
 {
   #1
 }
%    \end{macrocode}
%Header separator:
%    \begin{macrocode}
\ExplSyntaxOff
\ifdef\chapter
 {
  \newcommand{\flowframheaderchapprefix}{\@chapapp \ }
  \newcommand{\flowframheadersep}{.\ }
 }
 {
  \newcommand{\flowframheaderchapprefix}{}
  \newcommand{\flowframheadersep}{\quad}
 }
\ExplSyntaxOn
%    \end{macrocode}
%Table of contents header.
%    \begin{macrocode}
\renewcommand \tableofcontents
 {
   \__flowfram_tableofcontents:
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_if_exist:NTF \chapter
 {
  \cs_new:Nn \__flowfram_adjusted_toc:
   {
     \chapter * { \contentsname }   
     \chaptermark { \contentsname }
     \@starttoc { toc }
   }
 }
 {
  \cs_new:Nn \__flowfram_adjusted_toc:
   {
     \section * { \contentsname }
     \sectionmark { \contentsname } 
     \@starttoc { toc }
   }
 }
\cs_new:Nn \flowfram_toc:
 {
   \__flowfram_adjusted_toc:
 }
%    \end{macrocode}
%
%By default, ffempty style clears the header and footer.
%    \begin{macrocode}
\tl_new:N \l__flowfram_ffempty_style_tl
\tl_set:Nn \l__flowfram_ffempty_style_tl { \__flowfram_ps_empty: }
%    \end{macrocode}
% and hides the dynamic frames:
%    \begin{macrocode}
\bool_new:N \l__flowfram_ps_ffempty_hides_bool
\bool_set_true:N \l__flowfram_ps_ffempty_hides_bool
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_only_pre_makedfheaderfooter:nn { #2 }
%    \end{macrocode}
%
%Save original definition of \cs{tableofcontents}:
%    \begin{macrocode}
\cs_set_eq:NN \__flowfram_org_tableofcontents: \tableofcontents
%    \end{macrocode}
%
%The new \LaTeX\ hook management system and sophisticated classes
%now make the old \sty{flowfram} pre-chapter hooks somewhat redundant.
%These are retained for backward-compatibility but provide a way of
%omitting them.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_addto_prechap:
{
  \__flowfram_addto_prechap:
}
\cs_new:Nn \__flowfram_addto_prechap:
{
%    \end{macrocode}
%First check if \cs{chapter} exists:
%    \begin{macrocode}
  \cs_if_exist:NT \chapter
   {
%    \end{macrocode}
%\begin{macro}{\chapterfirstpagestyle}
% User may want a non standard style for the first page of 
% each chapter, so modify chapter commands to take this into 
% account.
%    \begin{macrocode}
    \newcommand*{\chapterfirstpagestyle}{plain}%
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
    \AddToHook { cmd / chapter / before }
     {
       \ffprechapterhook
       \thispagestyle { \chapterfirstpagestyle }
     }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffprechapterhook}
%\changes{1.14}{2012-11-10}{new}
% Hook at start of chapter (before page break issued)
%This is redundant now that hook are available but retained for
%backward-compatibility.
%    \begin{macrocode}
    \newcommand*{\ffprechapterhook}{}
%    \end{macrocode}
%\end{macro}
%
% End of test if \cs{chapter} defined:
%    \begin{macrocode}
 }
%    \end{macrocode}
%
%    \begin{macrocode}
}
%    \end{macrocode}
%
% Now declare the options. 
% NB v2.0 has switched from xkeyval to l3keys.
%    \begin{macrocode}
\keys_define:nn { flowfram }
{
%    \end{macrocode}
% Should the table of contents be adjusted.
%    \begin{macrocode}
  adjust-toc .choice: ,
%    \end{macrocode}
% adjust the table of contents including the header (default):
%    \begin{macrocode}
  adjust-toc / header  .code:n =
   {
     \cs_set:Nn \flowfram_toc:
      {
        \__flowfram_adjusted_toc:
      }
     \renewcommand \tableofcontents
      {
        \__flowfram_tableofcontents:
      }
   } ,
%    \end{macrocode}
% adjust the table of contents but retain original header:
%    \begin{macrocode}
  adjust-toc / notheader  .code:n =
   {
     \cs_set:Nn \flowfram_toc:
      {
         \__flowfram_org_tableofcontents:
      }
     \renewcommand \tableofcontents
      {
        \__flowfram_tableofcontents:
      }
   } ,
%    \end{macrocode}
% don't adjust the table of contents (no support for thumbtab index
% or minitocs):
%    \begin{macrocode}
  adjust-toc / off  .code:n =
   {
     \let \tableofcontents \__flowfram_org_tableofcontents:
   } ,
%    \end{macrocode}
% If the header and footer are converted into dynamic frames,
% indicate how to adjust the page styles.
%    \begin{macrocode}
  dynamic-page-style .choice: ,
  dynamic-page-style .usage:n = { preamble } ,
  dynamic-page-style / adjust .code:n = 
   {
     \__flowfram_only_pre_makedfheaderfooter:nn
       { dynamic-page-style = adjust }
      {
        \cs_set_eq:NN \__flowfram_adjust_page_styles:n \use:n
      }
   } ,
  dynamic-page-style / noadjust .code:n = 
   {
     \__flowfram_only_pre_makedfheaderfooter:nn
       { dynamic-page-style = noadjust }
      {
        \cs_set_eq:NN \__flowfram_adjust_page_styles:n \use_none:n
      }
   } ,
  dynamic-header-case .choice: ,
  dynamic-header-case / uc .code:n = 
   {
     \cs_set:Nn \flowfram_header_case:n
      {
        \MakeUppercase { ##1 }
      }
   } ,
  dynamic-header-case / no-change .code:n = 
   {
     \cs_set:Nn \flowfram_header_case:n { ##1 }
   } ,
  dynamic-subheader-case .choice: ,
  dynamic-subheader-case / uc .code:n = 
   {
     \cs_set:Nn \flowfram_subheader_case:n
      {
        \MakeUppercase { ##1 }
      }
   } ,
  dynamic-subheader-case / no-change .code:n = 
   {
     \cs_set:Nn \flowfram_subheader_case:n { ##1 }
   } ,
  dynamic-page-style-header-font .code:n = 
   {
     \tl_if_empty:nTF { #1 }
      {
        \cs_set:Nn \flowfram_header_font:n { ##1 }
      }
      {
        \cs_set:Nn \flowfram_header_font:n { #1 { ##1 } }
      }
   } ,
  dynamic-page-style-subheader-font .code:n = 
   {
     \tl_if_empty:nTF { #1 }
      {
        \cs_set:Nn \flowfram_subheader_font:n { ##1 }
      }
      {
        \cs_set:Nn \flowfram_subheader_font:n { #1 { ##1 } }
      }
   } ,
%    \end{macrocode}
%How should ffempty page style behave?
%    \begin{macrocode}
  dynamic-empty-page-style .choice: ,
  dynamic-empty-page-style / empty .code:n =
    {
      \tl_set:Nn \l__flowfram_ffempty_style_tl { \__flowfram_ps_empty: }
      \bool_set_false:N \l__flowfram_ps_ffempty_hides_bool
    } ,
  dynamic-empty-page-style / plain .code:n =
    {
      \tl_set:Nn \l__flowfram_ffempty_style_tl { \__flowfram_ps_plain: }
      \bool_set_false:N \l__flowfram_ps_ffempty_hides_bool
    } ,
  dynamic-empty-page-style / headings .code:n =
    {
      \tl_set:Nn \l__flowfram_ffempty_style_tl { \__flowfram_ps_headings: }
      \bool_set_false:N \l__flowfram_ps_ffempty_hides_bool
    } ,
  dynamic-empty-page-style / myheadings .code:n =
    {
      \tl_set:Nn \l__flowfram_ffempty_style_tl { \__flowfram_ps_myheadings: }
      \bool_set_false:N \l__flowfram_ps_ffempty_hides_bool
    } ,
  dynamic-empty-page-style / ignore .code:n =
    {
      \tl_clear:N \l__flowfram_ffempty_style_tl
      \bool_set_false:N \l__flowfram_ps_ffempty_hides_bool
    } ,
  dynamic-empty-page-style / hide .code:n =
    {
      \bool_set_true:N \l__flowfram_ps_ffempty_hides_bool
    } ,
  dynamic-empty-page-style / show .code:n =
    {
      \bool_set_false:N \l__flowfram_ps_ffempty_hides_bool
    } ,
%    \end{macrocode}
%If backmatter is supported, adjust the secnumdepth counter:
%    \begin{macrocode}
  backmatter-sections .choice: ,
  backmatter-sections / no-number .code:n =
   {
    \cs_set:Nn \__flowfram_backmatter_setsecnumdepth:
     {
       \setcounter { secnumdepth } { -1 }
     }
   } ,
  backmatter-sections / no-change .code:n =
   {
    \cs_set:Nn \__flowfram_backmatter_setsecnumdepth:
     {
     }
   } ,
%    \end{macrocode}
% Indicate if unstarred units outside of the main matter should have
% thumbtabs.
%    \begin{macrocode}
   matter-thumbtabs .choice: ,
   matter-thumbtabs / main-only .code:n =
    {
      \cs_set:Nn \__flowfram_ttb_notmainmatter_num:n
       {
       }
    },
   matter-thumbtabs / all .code:n =
    {
      \cs_set:Nn \__flowfram_ttb_notmainmatter_num:n
       {
         \__flowfram_ttb_num:n { ##1 }
       }
    },
   matter-thumbtabs / not-front .code:n =
    {
      \cs_set:Nn \__flowfram_ttb_notmainmatter_num:n
       {
         \bool_if:NF \g__flowfram_frontmatter_bool
           {
             \__flowfram_ttb_num:n { ##1 }
           }
       }
    },
   matter-thumbtabs / not-back .code:n =
    {
      \cs_set:Nn \__flowfram_ttb_notmainmatter_num:n
       {
         \bool_if:NF \g__flowfram_backmatter_bool
           {
             \__flowfram_ttb_num:n { ##1 }
           }
       }
    },
%    \end{macrocode}
% Indicate which thumbtabs should have hyperlinks (if supported).
%    \begin{macrocode}
   thumbtab-links .choice: ,
   thumbtab-links / toc-only .code:n =
    {
      \renewcommand \thumbtabindexformat [ 3 ]
       {
         \thumbtabhyperlinkformat { ##1 } { ##2 } { ##3 }
       }
      \renewcommand \thumbtabregularformat [ 3 ]
       {
         \thumbtabformat { ##2 } { ##3 }
       }
    } ,
   thumbtab-links / all .code:n =
    {
      \renewcommand \thumbtabindexformat [ 3 ]
       {
         \thumbtabhyperlinkformat { ##1 } { ##2 } { ##3 }
       }
      \renewcommand \thumbtabregularformat [ 3 ]
       {
         \thumbtabhyperlinkformat { ##1 } { ##2 } { ##3 }
       }
    } ,
   thumbtab-links / none .code:n =
    {
      \renewcommand \thumbtabindexformat [ 3 ]
       {
         \thumbtabformat { ##2 } { ##3 }
       }
      \renewcommand \thumbtabregularformat [ 3 ]
       {
         \thumbtabformat { ##2 } { ##3 }
       }
    } ,
%    \end{macrocode}
% Indicate whether or not unstarred units should have thumbtabs.
%    \begin{macrocode}
   unstarred-thumbtabs .bool_gset:N =
    \g__flowfram_save_nonum_thumbtabs_bool ,
%    \end{macrocode}
% Indicate whether or not thumbtab indexes should appear in the
% table of contents and, if so, whether or not to align them.
%    \begin{macrocode}
   toc-thumbtabs .choice: ,
   toc-thumbtabs / aligned .code:n =
    {
      \aligntoctrue
      \bool_set_true:N \l__flowfram_thumbtabs_in_toc_bool
      \bool_set_false:N \l__flowfram_thumbtabs_span_toc_bool
    } ,
   toc-thumbtabs / unaligned .code:n =
    {
      \aligntocfalse
      \bool_set_true:N \l__flowfram_thumbtabs_in_toc_bool
      \bool_set_false:N \l__flowfram_thumbtabs_span_toc_bool
    } ,
   toc-thumbtabs / false .code:n =
    {
      \bool_set_false:N \l__flowfram_thumbtabs_in_toc_bool
    } ,
   toc-thumbtabs / true .code:n =
    {
      \aligntocfalse
      \bool_set_true:N \l__flowfram_thumbtabs_in_toc_bool
      \bool_set_true:N \l__flowfram_thumbtabs_span_toc_bool
    } ,
   toc-thumbtabs .default:n = { true } ,
   sections-extra-option .choice: ,
   sections-extra-option / as-original .code:n =
    {
      \bool_set_true:N \l__flowfram_section_header_opt_bool 
      \bool_set_false:N \l__flowfram_section_header_opt_thumbtab_bool 
    } ,
   sections-extra-option / thumbtab-only .code:n =
    {
      \bool_set_false:N \l__flowfram_section_header_opt_bool 
      \bool_set_true:N \l__flowfram_section_header_opt_thumbtab_bool 
    } ,
   sections-extra-option / original-and-thumbtab .code:n =
    {
      \bool_set_true:N \l__flowfram_section_header_opt_bool 
      \bool_set_true:N \l__flowfram_section_header_opt_thumbtab_bool 
    } ,
   sections-option-keyval .bool_set:N = \l__flowfram_section_keyval_opt_bool ,
   column-changes .choice: ,
   column-changes / ignore .code:n = 
    {
      \bool_gset_true:N \g__flowfram_ignore_column_changes_bool
      \bool_gset_false:N \g__flowfram_clearpage_column_changes_bool
    } ,
   column-changes / clearpage .code:n = 
    {
%    \end{macrocode}
%Clear the page but otherwise ignore the column change command.
%    \begin{macrocode}
      \bool_gset_true:N \g__flowfram_clearpage_column_changes_bool
      \bool_gset_true:N \g__flowfram_ignore_column_changes_bool
    } ,
   column-changes / switch .code:n = 
    {
%    \end{macrocode}
%Switch to designated frames, if set up.
%    \begin{macrocode}
      \bool_gset_true:N \g__flowfram_clearpage_column_changes_bool
      \bool_gset_false:N \g__flowfram_ignore_column_changes_bool
    } ,
   draft .code:n = { \__flowfram_set_draft: } ,
   final .code:n = { \__flowfram_set_final: } ,
   verbose .choice: ,
   verbose / true .code:n = 
    {
      \let \flf@doifverbose \@firstofone
    } ,
   verbose / false .code:n = 
    {
      \let \flf@doifverbose \@gobble
    } ,
   verbose .default:n = { true } ,
   thumbtab-text .choice: ,
   thumbtab-text / normal .code:n =
    {
      \cs_set_eq:NN \__flowfram_thumbtab_fmt:nn \use_i:nn
    } ,
   thumbtab-text / stack .code:n =
    {
      \cs_set_eq:NN
         \__flowfram_thumbtab_fmt:nn 
         \__flowfram_thumbtab_fmt_stack:nn
    } ,
   thumbtab-text / rotate-right .code:n =
    {
      \cs_set_eq:NN
         \__flowfram_thumbtab_fmt:nn 
         \__flowfram_thumbtab_fmt_sideways_oneside_right:nn 
    } ,
   thumbtab-text / rotate-left .code:n =
    {
      \cs_set_eq:NN
         \__flowfram_thumbtab_fmt:nn 
         \__flowfram_thumbtab_fmt_sideways_oneside_left:nn 
    } ,
   thumbtab-text / rotate .code:n =
    {
      \cs_set_eq:NN
         \__flowfram_thumbtab_fmt:nn 
         \__flowfram_thumbtab_fmt_sideways:nn 
    } ,
%    \end{macrocode}
% Provide a way of inhibiting frame rotation.
%    \begin{macrocode}
   prohibit-frame-rotation .bool_set_inverse:N =
       \l__flowfram_allow_frame_rotation_bool ,
%    \end{macrocode}
% Provide old option for backward compatibility.
%    \begin{macrocode}
   rotate .choice: ,
   rotate / true .code:n =
    {
      \bool_set_true:N \l__flowfram_allow_frame_rotation_bool
      \cs_set_eq:NN
         \__flowfram_thumbtab_fmt:nn 
         \__flowfram_thumbtab_fmt_sideways_oneside_right:nn 
    } ,
   rotate / false .code:n =
    {
      \bool_set_false:N \l__flowfram_allow_frame_rotation_bool
      \cs_set_eq:NN
         \__flowfram_thumbtab_fmt:nn 
         \__flowfram_thumbtab_fmt_stack:nn
    } ,
   rotate .default:n = { true } ,
   norotate .code:n =
    {
      \bool_set_false:N \l__flowfram_allow_frame_rotation_bool
      \cs_set_eq:NN
         \__flowfram_thumbtab_fmt:nn 
         \__flowfram_thumbtab_fmt_stack:nn
    } ,
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{new}
% The \opt{thumbtabs} option replaces the \opt{ttbtitle},
% \opt{ttbnotitle}, \opt{ttbnum} and \opt{ttbnonum}
% options.
%    \begin{macrocode}
   thumbtabs .choice: ,
   thumbtabs / title .code:n =
    {
       \bool_set_false:N \l__flowfram_ttb_show_number_bool
       \bool_set_true:N \l__flowfram_ttb_show_title_bool
    } ,
   thumbtabs / number .code:n =
    {
       \bool_set_true:N \l__flowfram_ttb_show_number_bool
       \bool_set_false:N \l__flowfram_ttb_show_title_bool
    } ,
   thumbtabs / both .code:n =
    {
       \bool_set_true:N \l__flowfram_ttb_show_number_bool
       \bool_set_true:N \l__flowfram_ttb_show_title_bool
    } ,
   thumbtabs / none .code:n =
    {
       \bool_set_false:N \l__flowfram_ttb_show_number_bool
       \bool_set_false:N \l__flowfram_ttb_show_title_bool
    } ,
   thumbtabs .default:n = { title } ,
   thumbtabs .usage:n = { preamble } ,
%    \end{macrocode}
% Provide old options for backward compatibility:
%    \begin{macrocode}
   ttbtitle .code:n =
     {
       \bool_set_true:N \l__flowfram_ttb_show_title_bool
     } ,
   ttbtitle .usage:n = { preamble } ,
   ttbnotitle .code:n =
     {
       \bool_set_false:N \l__flowfram_ttb_show_title_bool
     } ,
   ttbnotitle .usage:n = { preamble } ,
   ttbnum .code:n =
     {
       \bool_set_true:N \l__flowfram_ttb_show_number_bool
     } ,
   ttbnum .usage:n = { preamble } ,
   ttbnonum .code:n =
     {
       \bool_set_false:N \l__flowfram_ttb_show_number_bool
     } ,
   ttbnonum .usage:n = { preamble } ,
%    \end{macrocode}
% Determine whether the pages key when defining frames refers to the
% page number as given by \cs{c@page} or the absolute
% page number as given by \cs{c@absolutepage}.
%    \begin{macrocode}
   pages .choice: ,
   pages / relative .code:n = 
    {
      \tl_gset:Nn \g__flowfram_pagecounter_tl { \c@page }
    } ,
   pages / absolute .code:n =
    {
      \tl_gset:Nn \g__flowfram_pagecounter_tl { \c@absolutepage }
    } ,
   pages .usage:n = { preamble } ,
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{changed color to boolean option}
% If color=true option specified, set up the default colours
% for the borders and text for all frame types. Note that
% the colour name has to be grouped within the definition
% of \cs{flowframecol} and \cs{flowframetextcol}. This
% was done so that you could do, for example, 
% \verb"\renewcommand{\flowframecol}{[rgb]{1,1,0}}" so that
% you can specify the colour model as well.
% The commands \cs{@s@tffcol} and \cs{@s@tfftextcol}
% switch to the border and text colour, respectively. They
% both assume that \cs{ff@col} has been set to the 
% relevant colour before use.
%    \begin{macrocode}
   color .choice: ,
   color / true .code:n =
    {
      \__flowfram_enable_color:
    } ,
   color / false .code:n =
    {
%    \end{macrocode}
% Option set to false, ensure that the colour changing
% commands do nothing:
%    \begin{macrocode}
      \__flowfram_disable_color:
    } ,
   color .default:n = { true } ,
   color .usage:n = { preamble } ,
%    \end{macrocode}
% Provide \opt{nocolor} option for backward compatibility:
%    \begin{macrocode}
   nocolor .code:n = 
    {
      \__flowfram_disable_color:
    } ,
   nocolor .usage:n = { preamble } ,
%    \end{macrocode}
% Define options that set the direction.
%    \begin{macrocode}
   LR .code:n = { \lefttorightcolumnstrue } ,
   LR .usage:n = { preamble } ,
   RL .code:n = { \lefttorightcolumnsfalse } ,
   RL .usage:n = { preamble } ,
   adjust-pre-chapter .choice: ,
   adjust-pre-chapter / true .code:n =
    {
      \cs_set:Nn \__flowfram_do_addto_prechap:
      {
        \__flowfram_addto_prechap:
      }
    } ,
   adjust-pre-chapter / false .code:n =
    {
      \cs_set:Nn \__flowfram_do_addto_prechap: { }
    } ,
   adjust-pre-chapter .default:n = { true }, 
   adjust-pre-chapter .usage:n = { load }, 
}
%    \end{macrocode}
%
%For options that can be set after the package has loaded:
%    \begin{macrocode}
\NewDocumentCommand \flowframsetup { m }
 {
   \keys_set:nn { flowfram } { #1 }
 }
%    \end{macrocode}
%
%Set the defaults. Version 2.0 color now initialised to on.
%(NB original version of flowfram was
%released in 2005 when there was less support for colour and
%rotation.)
%    \begin{macrocode}
\flowframsetup{color}
%    \end{macrocode}
%
%Apply any options set via flowframtkutils::
%    \begin{macrocode}
\IfPackageLoadedT { flowframtkutils }
 {
   \clist_if_empty:NF  \g__flowframtk_options_clist
    {
      \keys_set:nV { flowfram } \g__flowframtk_options_clist
    }
 }
%    \end{macrocode}
%Switch off L3 syntax:
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%Now load color package to support grey.
%    \begin{macrocode}
\RequirePackage{color}
%    \end{macrocode}
% Now the defaults have all been set, the package options
% specified by the user can be processed.
%    \begin{macrocode}
\ProcessKeyOptions[flowfram]
%    \end{macrocode}
%
%    \begin{macrocode}
\ExplSyntaxOn
%    \end{macrocode}
%Prior to v2.0, \cs{textwidth} and \cs{textheight} were used to
%keep track of the typeblock. This causes a problem when the output
%routine commands set \cs{vsize} to \cs{textheight}. Now there are
%two new lengths to keep track of the typeblock, which are
%initialised to \cs{textwidth} and \cs{textheight}. The frames may
%be the exact height of the typeblock or may overlap, but this
%provides a base for commands that need to know the default area.
%    \begin{macrocode}
\newlength \typeblockwidth
\newlength \typeblockheight
\newlength \typeblockoffsety
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn \flowfram_update_typeblock:
 {
   \global \setlength \typeblockwidth \textwidth
   \global \setlength \typeblockheight \textheight
   \dim_gset:Nn \typeblockoffsety
    {
      \topmargin
       + \headheight
       + \headsep
       + \voffset
    }
 }
\flowfram_update_typeblock:
%    \end{macrocode}
%Ideally geometry needs to be set first.
%    \begin{macrocode}
\AddToHook
  { package / geometry / after }
  {
    \flowfram_update_typeblock:
  }
%    \end{macrocode}
%Add pre-chapter hook if required:
%    \begin{macrocode}
\__flowfram_do_addto_prechap:
%    \end{macrocode}
%
%\begin{counter}{maxflow}
% 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}
%    \end{macrocode}
%\end{counter}
%
%\begin{counter}{thisframe}
% Next define a counter to keep track of the \gls{idn} of the current
% \gls{flow}.
%\changes{2.0}{2025-11-24}{replaced \cs{thepage} with
%\cs{theabsolutepage}}
%    \begin{macrocode}
\newcounter{thisframe}
\AddToHook
  { package / hyperref / after }
  {
    \def \theHthisframe { \theabsolutepage . \arabic {thisframe} }
  }
%    \end{macrocode}
%\end{counter}
%
%\begin{macro}{\labelflowidn}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Define a command to label the current \gls{flow} so that its
% \gls{idn} can be referenced:
%    \begin{macrocode}
\NewDocumentCommand \labelflowidn { m }
 {
   \group_begin:
    \def \@currentlabel { \thethisframe }
    \label { #1 }
   \group_end:
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{counter}{displayedframe}
% 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}
\AddToHook
  { package / hyperref / after }
  {
    \def \theHdisplayedframe { \thepage . \arabic{displayedframe} }
  }
%    \end{macrocode}
%\end{counter}
%
%\begin{macro}{\labelflow}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Define a command to label the current \gls{flow} so that its
% displayed index can be referenced:
%    \begin{macrocode}
\NewDocumentCommand \labelflow { m }
{
  \group_begin:
    \def \@currentlabel { \thedisplayedframe }
    \label { #1 }
  \group_end:
}
%    \end{macrocode}
%\end{macro}
%\begin{counter}{maxstatic}
% Define a counter to store the total number of \glspl{static}:
%    \begin{macrocode}
\newcounter{maxstatic}
%    \end{macrocode}
%\end{counter}
%\begin{counter}{maxdynamic}
% Define a counter to store the total number of \glspl{dynamic}:
%    \begin{macrocode}
\newcounter{maxdynamic}
%    \end{macrocode}
%\end{counter}
%
% Define some temporary variables. These have been changed to L3
% integer variables in v2.0.
%    \begin{macrocode}
\int_new:N \l__flowfram_current_frame_int
\int_new:N \l__flowfram_current_abspage_int
\int_new:N \l__flowfram_current_static_int
\int_new:N \l__flowfram_current_dynamic_int
\int_new:N \l__flowfram_col_int
\int_new:N \l__flowfram_tmpa_int
\int_new:N \l__flowfram_tmpb_int
\int_new:N \l__flowfram_id_int
\int_new:N \l__flowfram_id_ii_int
\int_new:N \l__flowfram_type_int
\int_new:N \l__flowfram_type_ii_int
\int_new:N \l__flowfram_range_start_int
\int_new:N \l__flowfram_range_end_int
\int_new:N \l__flowfram_shape_int
\dim_new:N \l__flowfram_tmpa_dim
\dim_new:N \l__flowfram_tmpb_dim
\clist_new:N \l__flowfram_tmp_clist
%    \end{macrocode}
%Dimensions used for both static and dynamic frames:
%    \begin{macrocode}
\dim_new:N \l__flowfram_sfdf_height_dim
\dim_new:N \l__flowfram_sfdf_width_dim
\tl_new:N \l__flowfram_tmpa_tl
\bool_new:N \l__flowfram_found_bool
\tl_new:N \g__flowfram_next_tl
%    \end{macrocode}
%
%    \begin{macrocode}
\dim_new:N \l__flowfram_x_dim
\dim_new:N \l__flowfram_evenx_dim
\dim_new:N \l__flowfram_y_dim
\dim_new:N \l__flowfram_eveny_dim
\dim_new:N \l__flowfram_width_dim
\dim_new:N \l__flowfram_height_dim
\dim_new:N \l__flowfram_offset_dim
%    \end{macrocode}
%
%    \begin{macrocode}
\tl_new:N \l__flowfram_remainder_tl
\tl_new:N \l__flowfram_pages_tl
\tl_new:N \l__flowfram_next_pages_tl
\tl_new:N \l__flowfram_exclude_pages_tl
\clist_new:N \l__flowfram_pages_clist
\clist_new:N \l__flowfram_even_pages_clist
\clist_new:N \l__flowfram_odd_pages_clist
\clist_new:N \l__flowfram_exclude_pages_clist
\tl_new:N \l__flowfram_label_tl
\tl_new:N \l__flowfram_frametype_tl
\tl_new:N \l__flowfram_style_tl
\tl_new:N \l__flowfram_parindent_tl
\tl_new:N \l__flowfram_shape_tl
\tl_new:N \l__flowfram_valign_tl
\tl_new:N \l__flowfram_minipage_tl
\tl_new:N \l__flowfram_contents_tl
%    \end{macrocode}
%Empty if not set:
%    \begin{macrocode}
\tl_new:N \l__flowfram_width_tl
\tl_new:N \l__flowfram_height_tl
\tl_new:N \l__flowfram_x_tl
\tl_new:N \l__flowfram_y_tl
\tl_new:N \l__flowfram_evenx_tl
\tl_new:N \l__flowfram_eveny_tl
\tl_new:N \l__flowfram_oddx_tl
\tl_new:N \l__flowfram_oddy_tl
\tl_new:N \l__flowfram_offset_tl
\tl_new:N \l__flowfram_angle_tl
\tl_new:N \l__flowfram_margin_tl
%    \end{macrocode}
%Empty if not set otherwise "true" or "false":
%    \begin{macrocode}
\tl_new:N \l__flowfram_frameflag_tl
\tl_new:N \l__flowfram_clearflag_tl
\tl_new:N \l__flowfram_hideflag_tl
\tl_new:N \l__flowfram_hidethisflag_tl
%    \end{macrocode}
%
%\begin{macro}{\sdfparindent}
% Define a length to govern default paragraph indentation within 
% static and dynamic frames.
% This is initially 0pt. 
%    \begin{macrocode}
\newlength\sdfparindent
%    \end{macrocode}
%\end{macro}
%
%Utility command. Iterate over frame IDs in the list but the list
%may just be the keywords "all", "odd" or "even" or may contain
%ranges. The id can be referenced in \meta{code} with
%"\l__flowfram_id_int".
%Syntax \marg{clist}\marg{type}\marg{code}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_map_idns:nnn
 {
   \tl_if_eq:NnTF \c_flowfram_all_tl { #1 }
    {
      \int_step_inline:nn { \value { max #2 } }
       { 
         \int_set:Nn \l__flowfram_id_int { ##1 }
        #3
       }
    }
    {
      \tl_if_eq:NnTF \c_flowfram_odd_tl { #1 }
       {
         \int_step_inline:nnn { \c_one_int } { 2 } { \value { max #2 } }
          {
            \int_set:Nn \l__flowfram_id_int { ##1 }
            #3
          }
       }
       {
         \tl_if_eq:NnTF \c_flowfram_even_tl { #1 }
          {
            \int_step_inline:nnn { 2 } { 2 } { \value { max #2 } }
             {
               \int_set:Nn \l__flowfram_id_int { ##1 }
               #3
             }
          }
          {
            \clist_map_inline:nn { #1 }
             {
               \__flowfram_get_range:n { ##1 }
               \int_compare:nNnT { \l__flowfram_range_start_int } < { \c_one_int }
                {
                  \int_set_eq:NN \l__flowfram_range_start_int \c_one_int
                }
               \int_compare:nNnT
                  { \l__flowfram_range_end_int } > { \value { max #2 } }
                {
                  \int_set_eq:Nc \l__flowfram_range_end_int { c@max #2}
                }
               \int_compare:nNnTF
                 { \l__flowfram_range_start_int } < {  \l__flowfram_range_end_int }
                 {
                   \int_step_inline:nNnTF
                      { \l__flowfram_range_start_int } 
                      { \l__flowfram_range_end_int }
                    {
                      \int_set:Nn \l__flowfram_id_int { ##1 }
                      #3
                    }
                }
                {
                  \int_set_eq:NN
                    \l__flowfram_id_int
                    \l__flowfram_range_start_int
                  #3
                }
             }
          }
       }
    }
 }
\cs_generate_variant:Nn \__flowfram_map_idns:nnn { enn }
%    \end{macrocode}
%
%\subsection{Frame Attributes}
%Convenient commands to define frames and set and access frame attributes.
%
%Determine the frame type from its label. The integer variable
%provided will be set to one of the constants if valid otherwise
%trigger an error and set to -1.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_frame_type:Nn
 {
   \int_if_exist:cTF { c_flowfram_frame_type_ #2 _int }
     {
       \int_set_eq:Nc #1 { c_flowfram_frame_type_ #2 _int }
     }
     {
        \int_set:Nn #1 { - \c_one_int }
        \msg_error:nnn { flowfram } { invalid-frame-type } { #2 }
     }
 }
\cs_new:Nn \__flowfram_get_frame_type:n
 {
   \__flowfram_get_frame_type:Nn
    \l__flowfram_type_int
    { #1 }
 }
%    \end{macrocode}
%
%Store a list of all flow frame labels:
%    \begin{macrocode}
\seq_new:N \g__flowfram_flowlabels_seq
%    \end{macrocode}
%
%Store a list of all static frame labels:
%    \begin{macrocode}
\seq_new:N \g__flowfram_staticlabels_seq
%    \end{macrocode}
%
%Store a list of all dynamic frame labels:
%    \begin{macrocode}
\seq_new:N \g__flowfram_dynamiclabels_seq
%    \end{macrocode}
%
% Set up the keys for use with "\setflowframe", 
% "\setstaticframe" and "\setdynamicframe".
% Version 2.0: switched to l3keys.
%
%    \begin{macrocode}
\keys_define:nn { flowfram / frame }
 {
%    \end{macrocode}
% Frame width. (Dimensions are temporarily stored in a token list
% variable which is initialised to empty to determine whether or not
% the dimension has been updated.)
%    \begin{macrocode}
   width .tl_set:N = \l__flowfram_width_tl ,
   width .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame height.
%    \begin{macrocode}
   height .tl_set:N = \l__flowfram_height_tl ,
   height .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame $x$ co-ordinate (odd and even pages):
%    \begin{macrocode}
   x .tl_set:N = \l__flowfram_x_tl ,
   x .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame $y$ co-ordinate (odd and even pages):
%    \begin{macrocode}
   y .tl_set:N = \l__flowfram_y_tl ,
   y .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame $x$ co-ordinate (even pages only):
%    \begin{macrocode}
   evenx .tl_set:N = \l__flowfram_evenx_tl ,
   evenx .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame $y$ co-ordinate (even pages only):
%    \begin{macrocode}
   eveny .tl_set:N = \l__flowfram_eveny_tl ,
   eveny .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame $x$ co-ordinate (odd pages only if twoside implemented):
%    \begin{macrocode}
   oddx .tl_set:N = \l__flowfram_oddx_tl ,
   oddx .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame $y$ co-ordinate (odd pages only if twoside implemented):
%    \begin{macrocode}
   oddy .tl_set:N = \l__flowfram_oddy_tl ,
   oddy .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% New \gls{idl} for \gls{frame}:
%    \begin{macrocode}
   label .tl_set_e:N = \l__flowfram_label_tl ,
   label .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame border. If "none", define "\l__flowfram_frameflag_tl" as "false", 
% otherwise define "\l__flowfram_frameflag_tl" as "true". If "plain", define
% "\l__flowfram_frametype_tl" 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}
   border .choice: ,
   border .default:n = { plain } ,
   border / plain .code:n = 
    {
      \tl_set:Nn \l__flowfram_frameflag_tl { true }
      \tl_set:Nn \l__flowfram_frametype_tl { fbox }
    } ,
   border / none .code:n = 
    {
      \tl_set:Nn \l__flowfram_frameflag_tl { false }
    } ,
   border / unknown .code:n = 
    {
      \tl_set:Nn \l__flowfram_frameflag_tl { true }
      \tl_set:Ne \l__flowfram_frametype_tl { #1 }
    } ,
   border .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame's border colour. (This may not work for non-standard
% \glspl{fcmd}.)
%    \begin{macrocode}
   bordercolor .tl_set_e:N = \l__flowfram_bordercolor_tl ,
   bordercolour .tl_set_e:N = \l__flowfram_bordercolor_tl ,
   border-color .tl_set_e:N = \l__flowfram_bordercolor_tl ,
   border-colour .tl_set_e:N = \l__flowfram_bordercolor_tl ,
   bordercolor .groups:n = { flow , static , dynamic } ,
   bordercolour .groups:n = { flow , static , dynamic } ,
   border-color .groups:n = { flow , static , dynamic } ,
   border-colour .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Frame's text colour.
%    \begin{macrocode}
   textcolor .tl_set_e:N = \l__flowfram_textcolor_tl ,
   textcolour .tl_set_e:N = \l__flowfram_textcolor_tl ,
   text-color .tl_set_e:N = \l__flowfram_textcolor_tl ,
   text-colour .tl_set_e:N = \l__flowfram_textcolor_tl ,
   textcolor .groups:n = { flow , static , dynamic } ,
   textcolour .groups:n = { flow , static , dynamic } ,
   text-color .groups:n = { flow , static , dynamic } ,
   text-colour .groups:n = { flow , static , dynamic } ,
%    \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}
   backcolor .tl_set_e:N = \l__flowfram_backcolor_tl ,
   backcolour .tl_set_e:N = \l__flowfram_backcolor_tl ,
   back-color .tl_set_e:N = \l__flowfram_backcolor_tl ,
   back-colour .tl_set_e:N = \l__flowfram_backcolor_tl ,
   backcolor .groups:n = { flow , static , dynamic } ,
   backcolour .groups:n = { flow , static , dynamic } ,
   back-color .groups:n = { flow , static , dynamic } ,
   back-colour .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% \Gls{pglist} for which the \gls{frame} should appear:
%    \begin{macrocode}
   pages .tl_set_e:N = \l__flowfram_pages_tl ,
   pages .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Exclusion list:
%    \begin{macrocode}
   excludepages .tl_set_e:N = \l__flowfram_exclude_pages_tl ,
   excludepages .groups:n = { flow , static , dynamic } ,
%    \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.
%%Value may be "compute" or a length.
%    \begin{macrocode}
   offset .tl_set:N = \l__flowfram_offset_tl ,
   offset .groups:n = { flow , static , dynamic } ,
%    \end{macrocode}
% Angle to rotate frame (if allowed):
%    \begin{macrocode}
   angle .code:n =
     {
       \bool_if:NTF \l__flowfram_allow_frame_rotation_bool
        {
          \tl_set:Ne \l__flowfram_angle_tl { #1 }
        }
        {
          \tl_if_eq:enF { #1 } { 0 }
           {
             \msg_info:nn { flowfram } { info-no-rotation }
           }
        }
     } ,
   angle .groups:n = { flow , static , angle } ,
%    \end{macrocode}
% This key is only for \glspl{flow}:
%    \begin{macrocode}
   margin .choice: ,
   margin / inner .code:n =
     { \tl_set:Nn \l__flowfram_margin_tl { inner } } ,
   margin / outer .code:n =
     { \tl_set:Nn \l__flowfram_margin_tl { outer } } ,
   margin / left .code:n =
     { \tl_set:Nn \l__flowfram_margin_tl { left } } ,
   margin / right .code:n =
     { \tl_set:Nn \l__flowfram_margin_tl { right } } ,
   margin .groups:n = { flow } ,
%    \end{macrocode}
% This key is only for \gls{static} and \glspl{dynamic}.
% (Not using a boolean as the token list is initially clear to
% indicate no change.)
%    \begin{macrocode}
   clear .choice: ,
   clear / true .code:n =
     {
       \tl_set:Nn \l__flowfram_clearflag_tl { true }
     } ,
   clear / false .code:n =
     {
       \tl_set:Nn \l__flowfram_clearflag_tl { false }
     } ,
   clear .default:n = { true } ,
   clear .groups:n = { static, dynamic } ,
%    \end{macrocode}
% This key is only for \glspl{dynamic}:
%    \begin{macrocode}
   style .choice: ,
   style / none .code:n =
     {
       \tl_set:Nn \l__flowfram_style_tl { @firstofone }
     } ,
   style / unknown .code:n =
     {
       \tl_set:Ne \l__flowfram_style_tl { #1 }
     } ,
   style .groups:n = { dynamic } ,
%    \end{macrocode}
% This key is only for \glspl{static} and \glspl{dynamic}.
%    \begin{macrocode}
   shape .tl_set:N = \l__flowfram_shape_tl ,
   shape .groups:n = { static, dynamic } ,
%    \end{macrocode}
% This key is only for \glspl{static} and \glspl{dynamic}.
%    \begin{macrocode}
   parindent .tl_set:N = \l__flowfram_parindent_tl ,
   parindent .groups:n = { static, dynamic } ,
%    \end{macrocode}
% These keys are only for \glspl{static} and \glspl{dynamic}.
%    \begin{macrocode}
   valign .choice: ,
   valign / c .code:n =
     { \tl_set:Nn \l__flowfram_valign_tl { c } } ,
   valign / t .code:n =
     { \tl_set:Nn \l__flowfram_valign_tl { t } } ,
   valign / b .code:n =
     { \tl_set:Nn \l__flowfram_valign_tl { b } } ,
   valign .groups:n = { static, dynamic } ,
%    \end{macrocode}
%\changes{2014-06-04}{1.16}{added `hide' and `hidethis' keys}
%(Not using a boolean as token list variables initially clear to
%indicate no change.)
%    \begin{macrocode}
   hide .choice: ,
   hide / true .code:n =
     { \tl_set:Nn \l__flowfram_hideflag_tl { true } } ,
   hide / false .code:n =
     { \tl_set:Nn \l__flowfram_hideflag_tl { false } } ,
   hide .default:n = { true } ,
   hide .groups:n = { static, dynamic } ,
   hidethis .choice: ,
   hidethis / true .code:n = 
     { \tl_set:Ne \l__flowfram_hidethisflag_tl { true } } ,
   hidethis / false .code:n = 
     { \tl_set:Ne \l__flowfram_hidethisflag_tl { false } } ,
   hidethis .default:n = { true } ,
   hidethis .groups:n = { static, dynamic } ,
%    \end{macrocode}
%The following is reserved for \LaTeX\ to HTML parsers. 
%With \TeX\ engines, they just write information to the aux file.
%The value should be the options to pass to the parser.
%Suggested options: show=\meta{bool} (if true, put the frame contents in a
%div element at this point), style=\marg{css-style} (if set, add
%the style attribute to the div element), class=\marg{css-class}
%(if set, add the class attribute to the div element),
%image=\marg{bool} (if true, convert the frame contents to an
%image), image-type=\marg{mime type} (if image=true, the image
%should be this type).
%    \begin{macrocode}
   html .tl_set:N = \l__flowfram_html_tl ,
   html .groups:n = { static, dynamic } ,
 }
%    \end{macrocode}
%
%Syntax \marg{options}\marg{type}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_keys_for_type:nnn
 {
  \tl_clear:N \l__flowfram_frameflag_tl
  \tl_clear:N \l__flowfram_width_tl
  \tl_clear:N \l__flowfram_height_tl
  \tl_clear:N \l__flowfram_margin_tl
  \tl_clear:N \l__flowfram_x_tl
  \tl_clear:N \l__flowfram_y_tl
  \tl_clear:N \l__flowfram_frametype_tl
  \tl_clear:N \l__flowfram_bordercolor_tl
  \tl_clear:N \l__flowfram_valign_tl
  \tl_clear:N \l__flowfram_style_tl
  \tl_clear:N \l__flowfram_hideflag_tl
  \tl_clear:N \l__flowfram_hidethisflag_tl
  \tl_clear:N \l__flowfram_textcolor_tl
  \tl_clear:N \l__flowfram_clearflag_tl
  \tl_clear:N \l__flowfram_offset_tl
  \tl_clear:N \l__flowfram_pages_tl
  \tl_clear:N \l__flowfram_label_tl
  \tl_clear:N \l__flowfram_backcolor_tl
  \tl_clear:N \l__flowfram_evenx_tl
  \tl_clear:N \l__flowfram_eveny_tl
  \tl_clear:N \l__flowfram_oddx_tl
  \tl_clear:N \l__flowfram_oddy_tl
  \tl_clear:N \l__flowfram_angle_tl
  \tl_set_eq:NN \l__flowfram_exclude_pages_tl \c_novalue_tl 
  \tl_set_eq:NN \l__flowfram_shape_tl \c_novalue_tl 
  \tl_set_eq:NN \l__flowfram_parindent_tl \c_novalue_tl 
  \tl_clear:N \l__flowfram_html_tl
  \keys_set_groups:nnnN { flowfram / frame } { #2 } { #1 }
    \l__flowfram_remainder_tl
  \tl_if_empty:NF \l__flowfram_remainder_tl
   {
     \__flowfram_error:eee
       { frame-unsupported-options }
      { #2 } { \l__flowfram_remainder_tl }
   }
%    \end{macrocode}
%Set common options.
%    \begin{macrocode}
  \tl_if_empty:NF \l__flowfram_frameflag_tl
   {
     \flowfram_frame_set_bool_from_option:nnnV
       { #2 } { hasframe } { #3 }
       \l__flowfram_frameflag_tl 
   }
  \tl_if_empty:NF \l__flowfram_width_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { width } { #3 }
       { \l__flowfram_width_tl }
   }
  \tl_if_empty:NF \l__flowfram_height_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { height } { #3 }
       { \l__flowfram_height_tl }
   }
  \tl_if_empty:NF \l__flowfram_x_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { posx } { #3 }
       { \l__flowfram_x_tl }
     \flowfram_frame_set_dim:nnnn { #2 } { evenx } { #3 }
       { \l__flowfram_x_tl }
   }
  \tl_if_empty:NF \l__flowfram_y_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { posy } { #3 }
       { \l__flowfram_y_tl }
     \flowfram_frame_set_dim:nnnn { #2 } { eveny } { #3 }
       { \l__flowfram_y_tl }
   }
  \tl_if_empty:NF \l__flowfram_evenx_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { evenx } { #3 }
       { \l__flowfram_evenx_tl }
   }
  \tl_if_empty:NF \l__flowfram_eveny_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { eveny } { #3 }
       { \l__flowfram_eveny_tl }
   }
  \tl_if_empty:NF \l__flowfram_oddx_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { posx } { #3 }
       { \l__flowfram_oddx_tl }
   }
  \tl_if_empty:NF \l__flowfram_oddy_tl
   {
     \flowfram_frame_set_dim:nnnn { #2 } { posy } { #3 }
      { \l__flowfram_oddy_tl }
   }
  \tl_if_empty:NF \l__flowfram_label_tl
   {
     \__flowfram_set_frame_id:nnV { #2 } { #3 } \l__flowfram_label_tl
   }
  \tl_if_empty:NF \l__flowfram_frametype_tl
   {
     \flowfram_frame_set_tl:nnnV
        { #2 } { frametype } { #3 }
       \l__flowfram_frametype_tl
   }
  \tl_if_empty:NF \l__flowfram_bordercolor_tl
   {
    \exp_after:wN \__flowfram_set_frame_color:w
      \l__flowfram_bordercolor_tl
      \q_stop { #2 } { bordercolor } { #3 }
   }
  \tl_if_empty:NF \l__flowfram_textcolor_tl
   {
    \exp_after:wN \__flowfram_set_frame_color:w
      \l__flowfram_textcolor_tl
      \q_stop { #2 } { textcolor } { #3 }
   }
  \tl_if_empty:NF \l__flowfram_backcolor_tl
   {
    \exp_after:wN \__flowfram_set_frame_color:w
      \l__flowfram_backcolor_tl
      \q_stop { #2 } { backcolor } { #3 }
   }
  \tl_if_empty:NF \l__flowfram_pages_tl
   {
     \flowfram_set_frame_pagelist:nnV
       { #2 } { #3 } \l__flowfram_pages_tl
   }
  \exp_args:NV \tl_if_novalue:nF \l__flowfram_exclude_pages_tl 
   {
     \flowfram_set_frame_excludelist:nnV
       { #2 } { #3 } \l__flowfram_exclude_pages_tl
   }
  \tl_if_empty:NF \l__flowfram_offset_tl
   {
     \flowfram_frame_set_tl:nnnV
       { #2 } { offset } { #3 }
       \l__flowfram_offset_tl 
   }
  \tl_if_empty:NF \l__flowfram_angle_tl
   {
     \flowfram_frame_set_tl:nnnV
      { #2 } { angle } { #3 }
      \l__flowfram_angle_tl
   }
  \tl_if_empty:NF \l__flowfram_html_tl
   {
     \dim_zero:N \l__flowfram_sfdf_width_dim
     \dim_zero:N \l__flowfram_sfdf_height_dim
     \flowfram_set_dim_to_frame_dim:Nnnn
       \l__flowfram_sfdf_width_dim
        { #2 } { width } { #3 }
     \flowfram_set_dim_to_frame_dim:Nnnn
       \l__flowfram_sfdf_height_dim
        { #2 } { height } { #3 }
     \tl_put_left:Ne \l__flowfram_html_tl
      {
        width = \dim_eval:n { \l__flowfram_sfdf_width_dim } ,
        height = \dim_eval:n { \l__flowfram_sfdf_height_dim } ,
      }
     \exp_args:NV \__flowfram_write_html_opts:nnn
       \l__flowfram_html_tl { #2 } { \int_eval:n { #3 } }
   }
 }
%    \end{macrocode}
%For the benefit of \LaTeX\ to HTML parsers.
%    \begin{macrocode}
\int_new:N \g__flowfram_html_opts_int
%    \end{macrocode}
%Each option set has a unique numeric identifier to help match up
%the information in the aux file with the setting in the \LaTeX\
%document. The following starts by using the preamble command but
%will be changed in the begin document hook to use the document
%command.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_write_html_opts:nnn
 {
   \__flowfram_preamble_write_html_opts:nnn { #1 } { #2 } { #3 }
 }
%    \end{macrocode}
%The command used in the preamble:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_preamble_write_html_opts:nnn
 {
   \int_gincr:N \g__flowfram_html_opts_int
   \protected@write \@auxout
     { \let \theabsolutepage \relax }
     {
       \string \flowfram@preamble@htmlopts
        { \int_use:N \g__flowfram_html_opts_int }
        { #2 } { #3 } { #1 }
        { \thepage }
        { \theabsolutepage }
     }
 }
%    \end{macrocode}
%The command used in the document:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_doc_write_html_opts:nnn
 {
   \int_gincr:N \g__flowfram_html_opts_int
   \protected@write \@auxout
     { \let \theabsolutepage \relax }
     {
       \string \flowfram@doc@htmlopts
        { \int_use:N \g__flowfram_html_opts_int }
        { #2 } { #3 } { #1 }
        { \thepage }
        { \theabsolutepage }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\flowfram@preamble@htmlopts}
%\changes{2.0}{2025-11-24}{new}
%Syntax:
%\marg{opt-id}\marg{frame-type}\marg{idn}\marg{options}\marg{page}\marg{absolute-page}
%    \begin{macrocode}
\newcommand*\flowfram@preamble@htmlopts[6]{}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowfram@doc@htmlopts}
%\changes{2.0}{2025-11-24}{new}
%Syntax:
%\marg{opt-id}\marg{frame-type}\marg{idn}\marg{options}\marg{page}\marg{absolute-page}
%    \begin{macrocode}
\newcommand*\flowfram@doc@htmlopts[6]{}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@setframecol}
%\changes{2.0}{2025-11-24}{renamed}
% Set the colour of the frame, this is a little tricky 
% because the model may need to be specified in square
% brackets but the specs might not be grouped
% (e.g. "[rgb]1,0,0" vs "[named]red" vs "red").
% First check to see if a colour model has been
% specified.
%Version 2.0 renamed \cs{@setframecol}
%\oarg{model}\marg{specs}\verb"\q_stop"
%\marg{type}\marg{attr}\marg{idn}
%    \begin{macrocode}
\cs_new:Npn \__flowfram_set_frame_color:w
 {
   \@ifnextchar [
     \__flowfram_set_frame_color:wnnnn
     \__flowfram_set_frame_color:wnnn
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@setframecol}
% A colour model has been specified.
%Version 2.0 renamed \cs{@@setframecol}.
%    \begin{macrocode}
\cs_new:Npn \__flowfram_set_frame_color:wnnnn
   [ #1 ] #2 \q_stop #3 #4 #5
 {
  \flowfram_frame_set_tl:nnne
    { #3 } { #4 } { #5 }
    { [ #1 ] { #2 } } 
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@setfr@mecol}
% A colour model has not been specified.
% Version 2.0 renamed \cs{@@setfr@mecol}.
%    \begin{macrocode}
\cs_new:Npn \__flowfram_set_frame_color:wnnn
 #1 \q_stop #2 #3 #4
 {
  \flowfram_frame_set_tl:nnne
    { #2 } { #3 } { #4 }
    { { #1 } } 
 }
%    \end{macrocode}
%\end{macro}
%
%Syntax:
%\marg{page list}\marg{width}\marg{height}\marg{x}\marg{y}\marg{label}\marg{type}
%    \begin{macrocode}
\cs_new_nopar:Nn \__flowfram_new_frame:nnnnnnn
 {
  \int_gincr:c { c@max #7 }
%    \end{macrocode}
%Set common attributes.
%    \begin{macrocode}
  \flowfram_frame_new_bool:nnnN
    { #7 } { hasframe } { \int_use:c { c@max #7 } } \c_false_bool
%    \end{macrocode}
%Dimension checks are only required for flow frames. Static or
%dynamic frames may simply be decorative.
%    \begin{macrocode}
  \tl_if_eq:NnTF \c_flowfram_flow_tl { #7 }
   {
%    \end{macrocode}
%\changes{2.1}{2026-02-23}{add dimension check}
%Sanity check on width. If all defined flow frames accidentally have the width
%set to zero it can trigger an infinite number of pages.
%    \begin{macrocode}
    \dim_compare:nNnTF { #2 } > { \c_zero_dim }
     {
       \flowfram_frame_new_dim:nnnn
         { #7 } { width } { \int_use:c { c@max #7 } } { #2 }
     }
     {
       \__flowfram_error:eeee { invalid-width }
         { \dim_eval:n { #2 } } { #7 } { \token_to_str:N \typeblockwidth }
       \flowfram_frame_new_dim:nnnn
         { #7 } { width } { \int_use:c { c@max #7 } } { \typeblockwidth }
     }
    \dim_compare:nNnTF { #3 } > { \c_zero_dim }
     {
       \flowfram_frame_new_dim:nnnn
         { #7 } { height } { \int_use:c { c@max #7 } } { #3 }
     }
     {
       \__flowfram_error:eeee { invalid-height }
         { \dim_eval:n { #3 } } { #7 } { \token_to_str:N \typeblockheight }
       \flowfram_frame_new_dim:nnnn
         { #7 } { height } { \int_use:c { c@max #7 } } { \typeblockheight }
     }
   }
   {
     \flowfram_frame_new_dim:nnnn
       { #7 } { width } { \int_use:c { c@max #7 } } { #2 }
     \flowfram_frame_new_dim:nnnn
       { #7 } { height } { \int_use:c { c@max #7 } } { #3 }
   }
  \flowfram_frame_new_dim:nnnn
    { #7 } { posx } { \int_use:c { c@max #7 } } { #4 }
  \flowfram_frame_new_dim:nnnn
    { #7 } { posy } { \int_use:c { c@max #7 } } { #5 }
  \flowfram_frame_new_dim:nnnn
    { #7 } { evenx } { \int_use:c { c@max #7 } } { #4 }
  \flowfram_frame_new_dim:nnnn
    { #7 } { eveny } { \int_use:c { c@max #7 } } { #5 }
  \flowfram_frame_new_tl:nnnn
    { #7 } { frametype } { \int_use:c { c@max #7 } } { fbox }
  \flowfram_frame_new_tl:nnnn
    { #7 } { bordercolor } { \int_use:c { c@max #7 } } { \flowframecol }
  \flowfram_frame_new_tl:nnnn
    { #7 } { textcolor } { \int_use:c { c@max #7 } } { \flowframetextcol }
  \flowfram_frame_new_tl:nnnn
    { #7 } { backcolor } { \int_use:c { c@max #7 } } { { none } }
  \flowfram_frame_new_tl:nnnn
    { #7 } { angle } { \int_use:c { c@max #7 } } { 0 }
  \clist_set:Ne \l__flowfram_pages_clist { #1 }
  \exp_args:NV 
  \flowfram_if_valid_pagelist:nTF \l__flowfram_pages_clist
   {
     \flowfram_frame_new_clist:nnnV
       { #7 } { pagelist } { \int_use:c { c@max #7 } } 
       \l__flowfram_pages_clist
   }
   {
     \msg_error:nnn { flowfram } { invalid-pagelist } { #1 }
     \flowfram_frame_new_clist:nnnn
       { #7 } { pagelist } { \int_use:c { c@max #7 } } { all }
   }
%    \end{macrocode}
% Page exclusion list:
%\changes{1.14}{2012-11-10}{added page exclusion list}
%    \begin{macrocode}
  \flowfram_frame_new_clist:nnnn
    { #7 } { excludelist } { \int_use:c { c@max #7 } } { }
  \flowfram_frame_new_tl:nnnn
    { #7 } { offset } { \int_use:c { c@max #7 } } { compute }
  \__flowfram_set_frame_id:nnn { #7 } { \int_use:c { c@max #7 } } { #6 }
 }
%    \end{macrocode}
%Set the frame's label.
%\marg{type}\marg{idn}\marg{label}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_frame_id:nnn
{
  \tl_set:Ne \l__flowfram_label_tl { #3 }
  \int_compare:nNnTF
    { #2 } > { \seq_count:c { g__flowfram_ #1 labels_seq } }
   {
%    \end{macrocode}
%This is a label for a new frame.
%    \begin{macrocode}
     \exp_args:NnV
        \__flowfram_checkunique_frame_idl:nnF { #1 } \l__flowfram_label_tl 
      {
%    \end{macrocode}
%Not unique so fallback on IDN (which isn't guaranteed to be unique
%if another frame has confusingly been given a numeric label).
%    \begin{macrocode}
        \tl_set:Ne \l__flowfram_label_tl { \int_eval:n { #2 } }
      }
     \seq_gput_right:cV { g__flowfram_ #1 labels_seq } \l__flowfram_label_tl
     \flowfram_frame_new_tl:nnnV
       { #1 } { label } { #2 } 
       \l__flowfram_label_tl
   }
   {
%    \end{macrocode}
%This is a label for an existing flow frame.
%Temporarily set the corresponding sequence item to empty before
%checking uniqueness.
%    \begin{macrocode}
     \seq_set_item:cnn { g__flowfram_ #1 labels_seq } { #2 } { }
     \exp_args:NnV
        \__flowfram_checkunique_frame_idl:nnF { #1 } \l__flowfram_label_tl 
      {
        \tl_set:Ne \l__flowfram_label_tl { \int_eval:n { #2 } }
      }
     \exp_args:NcnV
       \seq_gset_item:Nnn
       { g__flowfram_ #1 labels_seq }
       { #2 } 
       \l__flowfram_label_tl 
     \flowfram_frame_set_tl:nnnV
       { #1 } { label } { #2 } 
       \l__flowfram_label_tl
   }
}
\cs_generate_variant:Nn \__flowfram_set_frame_id:nnn { nne , nnV }
%    \end{macrocode}
%
%Check if label is unique for given frame type.
%Syntax \marg{type}\marg{label}
%    \begin{macrocode}
\prg_new_conditional:Nnn \__flowfram_checkunique_frame_idl:nn
 { T, F, TF }
{
 \seq_if_in:cnTF { g__flowfram_ #1 labels_seq } { #2 }
  {
%    \end{macrocode}
% Label already exists.
% Find the index number to help with the error message.
%    \begin{macrocode}
    \exp_args:Nc
    \seq_map_indexed_inline:Nn
       { g__flowfram_ #1 labels_seq }
      {
        \tl_if_eq:nnT { ##2 } { #2 }
         {
           \msg_error:nnnnn { flowfram } { label-defined }
             { #2 } { #1 } { ##1 }
            \seq_map_break:
         }
      }
   \prg_return_false: 
  }
  { \prg_return_true: }
}
%    \end{macrocode}
%
%Test if label exists for given type of frame.
%Syntax \marg{type}\marg{label}\meta{int-var}
%If true, the corresponding IDN is stored in the \meta{int-vat}
%    \begin{macrocode}
\prg_new_conditional:Nnn \__flowfram_if_frame_label_exists:nnN
 { TF , T , F }
 {
  \int_zero:N #3
  \exp_args:Nc \seq_map_indexed_inline:Nn
     { g__flowfram_ #1 labels_seq }
    {
      \tl_if_eq:neT { ##2 } { #2 }
       {
         \int_set:Nn #3 { ##1 }
         \seq_map_break:
       }
    }
  \int_if_zero:nTF { #3 }
    { \prg_return_false: }
    { \prg_return_true: }
 }
%    \end{macrocode}
%
%The simplest way of determining if a frame identified by its number has been defined is to
%test if the label attribute is set.
%Syntax \marg{frame-type}{idn}
%    \begin{macrocode}
\prg_new_conditional:Nnn \__flowfram_if_frame_idn_exists:nn
   { p , T , F, TF }
 {
   \tl_if_exist:cTF
     { g__flowfram_ #1 _ label _ \romannumeral #2 _ tl }
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
%\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 "\l__flowfram_id_int".
% Version 2.0 renamed \cs{@getframeid}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_frame_id:nn
{
  \__flowfram_if_frame_label_exists:nnNF
     { #1 } { #2 } \l__flowfram_id_int
   {
     \__flowfram_error:eee { label-undefined } { #2 } { #1 }
   }
}
\cs_generate_variant:Nn \__flowfram_get_frame_id:nn { ne, nV }
%    \end{macrocode}
%\end{macro}
%
%Frame attributes.
%    \begin{macrocode}
\prop_new:N \g__flowfram_flow_attributes_prop
\prop_new:N \g__flowfram_static_attributes_prop
\prop_new:N \g__flowfram_dynamic_attributes_prop
%    \end{macrocode}
%
%Show flow frame attributes:
%    \begin{macrocode}
\cs_new:Nn \flowfram_show_flow_frame_by_idl:n
 {
   \__flowfram_if_flow_label_exists:nTF { #1 }
    {
      \__flowfram_show_flow_frame:
    }
    {
      \__flowfram_error:eee { label-undefined } { #1 } { flow }
    }
 }
\cs_new:Nn \flowfram_show_flow_frame_by_idn:n
 {
   \int_set:Nn \l__flowfram_id_int { #1 }
   \tl_if_exist:cTF
      { g__flowfram_flow_label_ \romannumeral \l__flowfram_id_int _ tl }
    {
      \__flowfram_show_flow_frame:
    }
    {
      \msg_error:nnee { flowfram } { idn-undefined }
       { flow } { \int_use:N \l__flowfram_id_int }
    }
 }
%    \end{macrocode}
%
%Show all flow frames:
%    \begin{macrocode}
\cs_new:Nn \flowfram_show_all_flow_frames:
 {
   \int_if_zero:nTF  { \c@maxflow }
    {
      \msg_show:nnne { flowfram } { show-all-frames-none }
       { flow }
    }
    {
      \msg_show:nnne { flowfram } { show-all-frames }
       { flow } 
       {
         \exp_args:NV \msg_show_item_unbraced:n
           \c@maxflow
       }
      \int_step_inline:nn { \c@maxflow }
       {
         \int_set:Nn \l__flowfram_id_int { ##1 }
         \__flowfram_show_flow_frame:
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_show_flow_frame:
 {
   \msg_show:nneee { flowfram } { show-frame-attributes }
    { flow } { \int_use:N \l__flowfram_id_int }
    {
      \prop_map_function:NN
         \g__flowfram_flow_attributes_prop 
         \__flowfram_show_flow_attribute:nn
   }
 }
\cs_new:Nn \__flowfram_show_flow_attribute:nn
  {
    \exp_args:Ne \msg_show_item_unbraced:n
     {
       \__flowfram_show_attribute:nnnn
        { flow } { #1 } { \l__flowfram_id_int } { #2 }
     }
  }
%    \end{macrocode}
%
%Show static frame attributes:
%    \begin{macrocode}
\cs_new:Nn \flowfram_show_static_frame_by_idl:n
 {
   \__flowfram_if_static_label_exists:nTF { #1 }
    {
      \__flowfram_show_static_frame:
    }
    {
      \__flowfram_error:eee { label-undefined } { #1 } { static }
    }
 }
\cs_new:Nn \flowfram_show_static_frame_by_idn:n
 {
   \int_set:Nn \l__flowfram_id_int { #1 }
   \tl_if_exist:cTF
      { g__flowfram_static_label_ \romannumeral \l__flowfram_id_int _ tl }
    {
      \__flowfram_show_static_frame:
    }
    {
      \msg_error:nnee { flowfram } { idn-undefined }
       { static } { \int_use:N \l__flowfram_id_int }
    }
 }
%    \end{macrocode}
%
%Show all static frames:
%    \begin{macrocode}
\cs_new:Nn \flowfram_show_all_static_frames:
 {
   \int_if_zero:nTF  { \c@maxstatic }
    {
      \msg_show:nnne { flowfram } { show-all-frames-none }
       { static }
    }
    {
      \msg_show:nnne { flowfram } { show-all-frames }
       { static } 
       {
         \exp_args:NV \msg_show_item_unbraced:n
           \c@maxstatic
       }
      \int_step_inline:nn { \c@maxstatic }
       {
         \int_set:Nn \l__flowfram_id_int { ##1 }
         \__flowfram_show_static_frame:
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_show_static_frame:
 {
   \msg_show:nneee { flowfram } { show-frame-attributes }
    { static } { \int_use:N \l__flowfram_id_int }
    {
      \prop_map_function:NN
         \g__flowfram_static_attributes_prop 
         \__flowfram_show_static_attribute:nn
   }
 }
\cs_new:Nn \__flowfram_show_static_attribute:nn
  {
    \exp_args:Ne \msg_show_item_unbraced:n
     {
       \__flowfram_show_attribute:nnnn
        { static } { #1 } { \l__flowfram_id_int } { #2 }
     }
  }
%    \end{macrocode}
%
%Show dynamic frame attributes:
%    \begin{macrocode}
\cs_new:Nn \flowfram_show_dynamic_frame_by_idl:n
 {
   \__flowfram_if_dynamic_label_exists:nTF { #1 }
    {
      \__flowfram_show_dynamic_frame:
    }
    {
      \__flowfram_error:eee { label-undefined } { #1 } { dynamic }
    }
 }
\cs_new:Nn \flowfram_show_dynamic_frame_by_idn:n
 {
   \int_set:Nn \l__flowfram_id_int { #1 }
   \tl_if_exist:cTF
      { g__flowfram_dynamic_label_ \romannumeral \l__flowfram_id_int _ tl }
    {
      \__flowfram_show_dynamic_frame:
    }
    {
      \msg_error:nnee { flowfram } { idn-undefined }
       { dynamic } { \int_use:N \l__flowfram_id_int }
    }
 }
%    \end{macrocode}
%Show all dynamic frames:
%    \begin{macrocode}
\cs_new:Nn \flowfram_show_all_dynamic_frames:
 {
   \int_if_zero:nTF  { \c@maxdynamic }
    {
      \msg_show:nnne { flowfram } { show-all-frames-none }
       { dynamic }
    }
    {
      \msg_show:nnne { flowfram } { show-all-frames }
       { dynamic } 
       {
         \exp_args:NV \msg_show_item_unbraced:n
           \c@maxdynamic
       }
      \int_step_inline:nn { \c@maxdynamic }
       {
         \int_set:Nn \l__flowfram_id_int { ##1 }
         \__flowfram_show_dynamic_frame:
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_show_dynamic_frame:
 {
   \msg_show:nneee { flowfram } { show-frame-attributes }
    { dynamic } { \int_use:N \l__flowfram_id_int }
    {
      \prop_map_function:NN
         \g__flowfram_dynamic_attributes_prop 
         \__flowfram_show_dynamic_attribute:nn
   }
 }
\cs_new:Nn \__flowfram_show_dynamic_attribute:nn
  {
    \exp_args:Ne \msg_show_item_unbraced:n
     {
       \__flowfram_show_attribute:nnnn
        { dynamic } { #1 } { \l__flowfram_id_int } { #2 }
     }
  }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_show_bool_attribute:nnn
 {
   \bool_if:cTF 
     { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
     { true }
     { false }
 }
\cs_new:Nn \__flowfram_show_box_attribute:nnn
 {
   \box_if_empty:cTF 
     { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
     { empty }
     { not ~ empty }
 }
\cs_new:Nn \__flowfram_show_attribute:nnnn
 {
   #2 ~ ( #4 ) : ~
   \cs_if_exist:cTF { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ #4 }
    {
      \cs_if_exist:cTF { __flowfram_show_ #4 _attribute:nnn }
       {
         \use:c { __flowfram_show_ #4 _attribute:nnn }
           { #1 } { #2 } { #3 }
       }
       {
         \use:c { #4 _use:c }
           { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ #4 }
       }
    }
    { undefined }
 }
%    \end{macrocode}
%
%\meta{prop-var}\marg{tag}\marg{var type}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_add_frame_attribute:Nnn
 {
   \prop_get:NnNTF #1 { #2 } \l__flowfram_tmpa_tl
    {
      \tl_if_eq:NnF \l__flowfram_tmpa_tl { #3 }
       {
          \msg_error:nneee { flowfram } {attribute-type-change}
           { #2 } { \l__flowfram_tmpa_tl } { #3 }
       }
    }
    {
      \prop_gput:Nnn #1 { #2 } { #3 }
    }
 }
\cs_generate_variant:Nn \__flowfram_add_frame_attribute:Nnn { cen }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_dim:nnn
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \dim_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ dim }
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { dim }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_dim:nnnn
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \dim_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ dim }
      \dim_gset:cn
       { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ dim }
       { #4 }
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { dim }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_use_dim:nnn
 {
   \dim_use:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ dim }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_set_dim:nnnn
 {
   \dim_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ dim }
    {
      \dim_gset:cn
       { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ dim }
       { #4 }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { dim }
    }
 }
%    \end{macrocode}
%
%Syntax: \meta{dim}\marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_dim_to_frame_dim:Nnnn
 {
   \dim_if_exist:cTF
      { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ dim }
    {
      \dim_set_eq:Nc
       #1
       { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ dim }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #2 } { #3 } { \int_eval:n { #4 } } { dim }
    }
 }
%    \end{macrocode}
%
%Syntax: \meta{dim}\marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_gset_dim_to_frame_dim:Nnnn
 {
   \dim_if_exist:cTF
      { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ dim }
    {
      \dim_gset_eq:Nc
       #1
       { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ dim }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #2 } { #3 } { \int_eval:n { #4 } } { dim }
    }
 }
%    \end{macrocode}
%
%Syntax: \meta{dim}\marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_dim_to_frame_tl:Nnnn
 {
   \dim_if_exist:cTF
      { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ tl }
    {
      \dim_set:Nn
       #1
       { \tl_use:c { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ tl } }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #2 } { #3 } { \int_eval:n { #4 } } { tl }
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag1}\marg{tag2}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_swap_dim:nnnn
 {
   \dim_set_eq:Nc \l__flowfram_tmpa_dim
     { g__flowfram_ #1 _ #2 _ \romannumeral #4 _ dim }
   \dim_gset_eq:cc
    { g__flowfram_ #1 _ #2 _ \romannumeral #4 _ dim }
    { g__flowfram_ #1 _ #3 _ \romannumeral #4 _ dim }
   \dim_gset_eq:cN
    { g__flowfram_ #1 _ #3 _ \romannumeral #4 _ dim }
    \l__flowfram_tmpa_dim
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_box:nnn
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \box_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { box }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_set_box_eq:nnnN
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    {
      \box_gset_eq:cN
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
        #4
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
        { #1 } { #2 } { \int_eval:n { #3 } } { box }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_clear_box:nnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    {
      \box_gclear:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
        { #1 } { #2 } { \int_eval:n { #3 } } { box }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_use_box:nnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    {
      \leavevmode
      \box_use:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
        { #1 } { #2 } { \int_eval:n { #3 } } { box }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_use_drop_box:nnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    {
      \box_use_drop:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
        { #1 } { #2 } { \int_eval:n { #3 } } { box }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_frame_if_box_empty:nnn
 { T, F, TF }
 {
   \exp_args:Nc \if_box_empty:N
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ box }
    \prg_return_true: 
   \else:
    \prg_return_false: 
   \fi:
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_tl:nnn
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \tl_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { tl }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_tl:nnnn
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \tl_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
      \tl_gset:cn
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
        { #4 }
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { tl }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
%    \end{macrocode}
%\changes{2.3}{2026-06-19}{corrected variant}
%    \begin{macrocode}
\cs_generate_variant:Nn  \flowfram_frame_new_tl:nnnn
 { nnnV , nnne }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_use_tl:nnn
 {
   \tl_use:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_set_tl:nnnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
    {
       \__flowfram_message:nnnen 
        { info-setting-frame-attribute }
        { #2 } { #1 } { \int_eval:n { #3 } } { #4 }
       \tl_gset:cn
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
        { #4 }
    }
    {
     \__flowfram_error:eeeee{ frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { tl }
    }
 }
\cs_generate_variant:Nn \flowfram_frame_set_tl:nnnn { nnne , nnnV }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_clear_tl:nnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
    {
       \__flowfram_message:nnnen
          { info-setting-frame-attribute }
          { #2 } { #1 } { \int_eval:n { #3 } } { }
       \tl_gclear:c
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { tl }
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_put_right_tl:nnnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
    {
       \tl_gput_right:cn
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
        { #4 }
      \__flowfram_message:nnnev
        { info-setting-frame-attribute }
        { #2 } { #1 } { \int_eval:n { #3 } }
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { tl }
    }
 }
\cs_generate_variant:Nn \flowfram_frame_put_right_tl:nnnn { nnne , nnnV }
%    \end{macrocode}
%
%Syntax: \meta{tl}\marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_tl_to_frame_tl:Nnnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ tl }
    {
      \tl_set_eq:Nc
       #1
       { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ tl }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #2 } { #3 } { \int_eval:n { #4 } } { tl } 
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\meta{tl}
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_frame_tl_to_tl:Nnnn
 {
   \tl_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
    {
       \__flowfram_message:nnneV
        { info-setting-frame-attribute }
        { #2 } { #1 } { \int_eval:n { #3 } } #4
      \tl_gset_eq:cN
       { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
       #4
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #2 } { #3 } { \int_eval:n { #4 } } { tl }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_tl_eq_frame_tl:Nnnn
   { T, F, TF }
 {
   \tl_if_eq:NcTF
     #1
     { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ tl }
   { \prg_return_true: }
   { \prg_return_false: }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_tl_eq_frame_tl:nnnn
   { T, F, TF }
 {
   \tl_if_eq:cnTF
     { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ tl }
     { #1 }
   { \prg_return_true: }
   { \prg_return_false: }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_tl_exist:nnn
   { T, F, TF }
 {
   \tl_if_exist:cTF
     { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
   { \prg_return_true: }
   { \prg_return_false: }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_tl_empty:nnn
   { T, F, TF }
 {
   \tl_if_empty:cTF
     { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ tl }
   { \prg_return_true: }
   { \prg_return_false: }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_clist:nnnn
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \clist_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
      \clist_gset:cn
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
        { #4 }
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { clist }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
\cs_generate_variant:Nn \flowfram_frame_new_clist:nnnn
  { nnne , nnnV }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_use_clist:nnn
 {
   \clist_use:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_set_clist:nnnn
 {
   \clist_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
    {
      \__flowfram_message:nnnen
        { info-setting-frame-attribute }
        { #2 } { #1 } { \int_eval:n { #3 } } { #4 }
       \clist_gset:cn
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
        { #4 }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { clist }
    }
 }
\cs_generate_variant:Nn \flowfram_frame_set_clist:nnnn { nnne , nnnV }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_put_right_clist:nnnn
 {
   \clist_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
    {
       \clist_gput_right:cn
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
        { #4 }
      \__flowfram_message:nnnev
        { info-setting-frame-attribute }
        { #2 } { #1 } { \int_eval:n { #3 } }
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { clist }
    }
 }
\cs_generate_variant:Nn \flowfram_frame_put_right_clist:nnnn { nnne , nnnV }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{clist var}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_concat_clist:nnnN
 {
   \clist_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
    {
       \exp_args:Ncc
       \clist_gconcat:NNN
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
         #4 
      \__flowfram_message:nnnev
        { info-setting-frame-attribute }
        { #2 } { #1 } { \int_eval:n { #3 } }
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { clist }
    }
 }
\cs_generate_variant:Nn \flowfram_frame_concat_clist:nnnN { nnnc }
%    \end{macrocode}
%
%Syntax: \meta{clist}\marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_clist_to_frame_clist:Nnnn
 {
   \clist_if_exist:cTF
      { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ clist }
    {
      \clist_set_eq:Nc
       #1
       { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ clist }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #2 } { #3 } { \int_eval:n { #4 } } { clist }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_tl_eq_frame_clist:Nnnn
   { T, F, TF }
 {
   \tl_if_eq:cNTF
     { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ clist }
     #1
   { \prg_return_true: }
   { \prg_return_false: }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{code}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_clist_map_inline:nnnn
 {
   \clist_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
    {
      \clist_map_inline:cn
       { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ clist }
        { #4 }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
        { #1 } { #2 } { \int_eval:n { #3 } } { clist }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_in_frame_clist:nnnn
   { T, F, TF }
 {
   \clist_if_in:cnTF
     { g__flowfram_ #2 _ #3 _ \romannumeral #4 _ clist }
     { #1 }
   { \prg_return_true: }
   { \prg_return_false: }
 }
%    \end{macrocode}
%
%\marg{page num}\marg{frame type}\marg{idn}
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_excludedpage:nnn
 { T, F, TF}
 {
   \flowfram_if_in_frame_clist:nnnnTF
     { #1 } { #2 } { excludelist } { #3 }
   { \prg_return_true: }
   { \prg_return_false: }
 }
%    \end{macrocode}
%
%Syntax: \marg{page num}\marg{frame type}\marg{idn}
%Check if given page is in the page list for a frame.
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_in_frame_pagelist:nnn
 { T, F, TF}
 {
   \flowfram_if_frame_allpages:nnTF { #2 } { #3 }
    { \prg_return_true: }
    {
      \flowfram_if_frame_nopages:nnTF { #2 } { #3 }
       { \prg_return_false: }
       {
         \flowfram_if_frame_oddpages_only:nnTF { #2 } { #3 }
          {
            \int_if_odd:nTF { #1 }
             { \prg_return_true: }
             { \prg_return_false: }
          }
          {
            \flowfram_if_frame_evenpages_only:nnTF { #2 } { #3 }
             {
               \int_if_even:nTF { #1 }
                { \prg_return_true: }
                { \prg_return_false: }
             }
             {
               \flowfram_if_in_frame_clist:nnnnTF
                 { #1 } { #2 } { pagelist } { #3 }
                { \prg_return_true: }
                {
                  \bool_set_false:N \l__flowfram_found_bool
                  \flowfram_frame_clist_map_inline:nnnn
                   { #2 } { pagelist } { #3 }
                  {
                    \flowfram_if_in_pagerange:nnT { #1 } { ##1 }
                     {
                        \clist_map_break:n
                         {
                           \bool_set_true:N \l__flowfram_found_bool
                         }
                     }
                  }
                 \bool_if:NTF \l__flowfram_found_bool
                  { \prg_return_true: }
                  { \prg_return_false: }
                }
             }
          }
       }
    }
 }
%    \end{macrocode}
%
%\marg{num}\marg{range}
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_in_pagerange:nn
   { T, F, TF }
 {
   \__flowfram_get_range:n { #2 }
   \bool_lazy_or:nnTF
    {
      \int_compare_p:nNn { #1 } < { \l__flowfram_range_start_int }
    }
    {
      \int_compare_p:nNn { #1 } > { \l__flowfram_range_end_int }
    }
   { \prg_return_false: }
   { \prg_return_true: }
 }
%    \end{macrocode}
%
%Syntax: \marg{page num}\marg{frame type}\marg{idn}
%Check if there is at least one more page in the page list after the
%given number.
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_has_morepages:nnn
 { T, F, TF}
 {
   \flowfram_if_frame_allpages:nnTF { #2 } { #3 }
    { \prg_return_true: }
    {
      \flowfram_if_frame_nopages:nnTF { #2 } { #3 }
       { \prg_return_false: }
       {
         \flowfram_if_frame_oddpages_only:nnTF { #2 } { #3 }
           { \prg_return_true: }
          {
            \flowfram_if_frame_evenpages_only:nnTF { #2 } { #3 }
              { \prg_return_true: }
             {
%    \end{macrocode}
%Get the last range in the page list.
%    \begin{macrocode}
               \exp_args:Ne
               \__flowfram_get_range:n
                {
                  \clist_item:cn
                   { g__flowfram_ #2 _ pagelist _ \romannumeral #3 _ clist }
                   {
                     \clist_count:c
                       { g__flowfram_ #2 _ pagelist _ \romannumeral #3 _ clist }
                   }
                }
              \int_compare:nNnTF
               { \l__flowfram_range_end_int } > { #1 }
               { \prg_return_true: }
               { \prg_return_false: }
             }
          }
       }
    }
 }
%    \end{macrocode}
%
%\meta{int-var}\marg{type}\marg{idn}
%Gets the starting page and stores in \meta{int-var}.
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_get_start_page:Nnn
 {
   \flowfram_if_frame_allpages:nnTF { #2 } { #3 }
    { 
      \int_set_eq:NN #1 \c_one_int
    }
    {
      \flowfram_if_frame_nopages:nnTF { #2 } { #3 }
       {
         \int_set:Nn #1
          { \c_flowfram_max_page_int + \c_one_int }
       }
       {
         \flowfram_if_frame_oddpages_only:nnTF { #2 } { #3 }
          { 
            \int_set_eq:NN #1 \c_one_int
          }
          {
            \flowfram_if_frame_evenpages_only:nnTF { #2 } { #3 }
             { 
               \int_set:Nn #1 { 2 }
             }
             {
%    \end{macrocode}
%Get the first range in the page list.
%    \begin{macrocode}
               \exp_args:Ne
               \__flowfram_get_range:n
                {
                  \clist_item:cn
                   { g__flowfram_ #2 _ pagelist _ \romannumeral #3 _ clist }
                   { \c_one_int }
                }
               \int_if_zero:nT { #1 }
                {
                  \int_set_eq:NN #1 \c_one_int
                }
             }
          }
       }
    }
 }
%    \end{macrocode}
%
%Gets the starting page (stored in "\l__flowfram_range_start_int").
%\marg{type}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_frame_get_start_page:nn
 {
   \flowfram_frame_get_start_page:Nnn
     \l__flowfram_range_start_int { #1 } { #2 }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_frame_pagelist:nnn
 {
   \flowfram_if_valid_pagelist:nTF { #3 }
    {
      \flowfram_frame_set_clist:nnnn
       { #1 } { pagelist } { #2 } { #3 }
    }
    {
      \msg_error:nnn { flowfram } { invalid-pagelist } { #3 }
    }
 }
\cs_generate_variant:Nn \flowfram_set_frame_pagelist:nnn
  { nne , nnV }
%    \end{macrocode}
%
%Check if value is a valid page list.
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_valid_pagelist:n
   { T, F, TF }
 {
   \tl_if_blank:nTF { #1 }
    { \prg_return_false: }
    {
      \flowfram_if_all_or_odd:nTF { #1 }
       { \prg_return_true: }
       {
         \flowfram_if_none_or_even:nTF { #1 }
         { \prg_return_true: }
         {
           \bool_set_false:N \l__flowfram_found_bool
           \int_set_eq:NN \l__flowfram_tmpa_int \c_zero_int
           \clist_map_inline:nn { #1 }
            {
              \__flowfram_get_range:n { ##1 }
              \int_if_zero:nT { \l__flowfram_range_start_int }
               {
                 \int_set_eq:NN \l__flowfram_range_start_int \c_one_int
               }
              \bool_lazy_or:nnT
               {
                 \int_compare_p:nNn 
                 { \l__flowfram_range_start_int } > { \l__flowfram_range_end_int }
               }
               {
                 \bool_not_p:n
                  {
                    \int_compare_p:nNn
                      { \l__flowfram_range_start_int } > { \l__flowfram_tmpa_int }
                  }
               }
               {
                 \clist_map_break:n
                  {
                    \bool_set_true:N \l__flowfram_found_bool
                  }
               }
            \int_set_eq:NN \l__flowfram_tmpa_int \l__flowfram_range_end_int
          }
         \bool_if:NTF \l__flowfram_found_bool
          { \prg_return_false: }
          { \prg_return_true: }
       }
     }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_frame_excludelist:nnn
{
   \flowfram_frame_set_clist:nnnn
    { #1 } { excludelist } { #2 } { #3 }
}
\cs_generate_variant:Nn \flowfram_set_frame_excludelist:nnn
  { nne , nnV }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_concat_frame_excludelist:nnN
{
   \flowfram_frame_concat_clist:nnnN
    { #1 } { excludelist } { #2 }  #3 
}
\cs_generate_variant:Nn \flowfram_concat_frame_excludelist:nnN { nnc }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_concat_frame_excludelist:nnn
{
  \clist_set:Nn \l__flowfram_exclude_pages_clist { #3 }
  \flowfram_concat_frame_excludelist:nnN
   { #1 } { #2 } \l__flowfram_exclude_pages_clist 
}
\cs_generate_variant:Nn \flowfram_concat_frame_excludelist:nnn { nne }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{idn}
% If frame's page list is set to "odd":
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_oddpages_only:nn
  { p , T , F , TF }
 {
   \flowfram_if_tl_eq_frame_clist:NnnnTF
     \c_flowfram_odd_tl
     { #1 } { pagelist } { #2 }
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
% If frame's page list is set to "even":
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_evenpages_only:nn
  { p , T , F , TF }
 {
   \flowfram_if_tl_eq_frame_clist:NnnnTF
     \c_flowfram_even_tl
     { #1 } { pagelist } { #2 }
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
% If frame's page list is set to "all":
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_allpages:nn
  { p , T , F , TF }
 {
   \flowfram_if_tl_eq_frame_clist:NnnnTF
     \c_flowfram_all_tl
     { #1 } { pagelist } { #2 }
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
% If frame's page list is set to "none":
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_nopages:nn
  { p , T , F , TF }
 {
   \flowfram_if_tl_eq_frame_clist:NnnnTF
     \c_flowfram_none_tl
     { #1 } { pagelist } { #2 }
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_all_or_odd:N 
  { p, T, F, TF }
 {
   \bool_lazy_or:nnTF
    {
      \tl_if_eq_p:NN #1 \c_flowfram_all_tl
    }
    {
      \tl_if_eq_p:NN #1 \c_flowfram_odd_tl
    }
  { \prg_return_true: }
  { \prg_return_false: }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_all_or_odd:n
  { T, F, TF }
 {
   \tl_if_eq:NnTF \c_flowfram_all_tl { #1 }
    { \prg_return_true: }
    {
      \tl_if_eq:NnTF \c_flowfram_odd_tl { #1 }
      { \prg_return_true: }
      { \prg_return_false: }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_none_or_even:N 
  { p, T, F, TF }
 {
   \bool_lazy_or:nnTF
    {
      \tl_if_eq_p:NN #1 \c_flowfram_none_tl
    }
    {
      \tl_if_eq_p:NN #1 \c_flowfram_even_tl
    }
  { \prg_return_true: }
  { \prg_return_false: }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_none_or_even:n 
  { T, F, TF }
 {
   \tl_if_eq:NnTF \c_flowfram_none_tl { #1 }
    { \prg_return_true: }
    {
      \tl_if_eq:NnTF \c_flowfram_even_tl { #1 }
      { \prg_return_true: }
      { \prg_return_false: }
    }
 }
%    \end{macrocode}
%
%
%\begin{macro}{\@ff@getrange}
%\changes{2.0}{2025-11-24}{renamed \cs{@ff@getrange} command}
% Find out what kind of range the argument is (for example, a single
% number "24" or a closed range "30-40" or an open range, "<10" or
% ">25") and set integer variables to start and end. Version 2.0 renamed command.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_range:n
 {
  \flowfram_if_all_or_odd:nTF { #1 } 
   {
     \int_set_eq:NN \l__flowfram_range_start_int \c_one_int
     \int_set_eq:NN
        \l__flowfram_range_end_int
        \c_flowfram_max_page_int
   }
   {
     \tl_if_eq:nnTF { #1 } { even }
      {
        \int_set:Nn \l__flowfram_range_start_int { 2 }
        \int_set_eq:NN
           \l__flowfram_range_end_int
           \c_flowfram_max_page_int
      }
      {
        \tl_if_eq:nnTF { #1 } { none }
         {
           \int_zero:N \l__flowfram_range_start_int
           \int_zero:N \l__flowfram_range_end_int
         }
         {
           \__flowfram_get_range:w #1 - \q_nil \q_stop
         }
      }
   }
 }
\cs_generate_variant:Nn \__flowfram_get_range:n { e }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@@getrange}
%\changes{2.0}{2025-11-24}{renamed \cs{\@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}
\cs_new:Npn \__flowfram_get_range:w #1 - #2 \q_stop
 {
  \quark_if_nil:nTF { #2 }
   {
     \tl_if_head_eq_meaning:nNTF { #1 } <
      {
        \int_zero:N \l__flowfram_range_start_int
        \int_set:Nn \l__flowfram_range_end_int
         {
           \tl_tail:n { #1 } - \c_one_int
         }
      }
      {
        \tl_if_head_eq_meaning:nNTF { #1 } >
         {
           \int_set:Nn \l__flowfram_range_start_int
            {
              \tl_tail:n { #1 } + \c_one_int
            }
           \int_set_eq:NN 
            \l__flowfram_range_end_int
            \c_flowfram_max_page_int
         }
         {
           \int_set:Nn \l__flowfram_range_start_int { #1 }
           \int_set:Nn \l__flowfram_range_end_int { #1 }
         }
      }
   }
   {
     \int_set:Nn \l__flowfram_range_start_int { #1 }
     \__flowfram_get_end_range:w #2 - \q_stop
   }
}
%    \end{macrocode}
%\end{macro}
%Discard trailing content.
%    \begin{macrocode}
\cs_new:Npn \__flowfram_get_end_range:w #1 - #2 \q_stop
 {
   \int_set:Nn \l__flowfram_range_end_int { #1 }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_bool:nnn
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \bool_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { bool }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{value}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_new_bool:nnnN
 {
   \prop_if_exist:cTF 
    { g__flowfram_ #1 _attributes_prop }
    {
      \bool_new:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
      \bool_gset_eq:cN
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
        #4
      \__flowfram_add_frame_attribute:cen
        { g__flowfram_ #1 _attributes_prop }
        { #2 } { bool }
    }
    {
      \msg_error:nne { flowfram } {invalid-frame-type} { #1 }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \flowfram_if_frame_bool:nnn
   { T, F, TF }
 {
   \bool_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
    {
      \bool_if:cTF
        { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
      { \prg_return_true: }
      { \prg_return_false: }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { bool }
      \prg_return_false: 
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_set_bool_true:nnn
 {
   \bool_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
    {
      \bool_gset_true:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { bool }
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_set_bool_false:nnn
 {
   \bool_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
    {
      \bool_gset_false:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { bool }
    }
 }
%    \end{macrocode}
%
%Syntax: \marg{frame type}\marg{tag}\marg{idn}\marg{choice value}
%The \meta{choice value} should be either "true" or "false".
%    \begin{macrocode}
\cs_new:Nn \flowfram_frame_set_bool_from_option:nnnn
 {
   \bool_if_exist:cTF
      { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
    {
      \tl_if_eq:nnTF { #4 } { true }
       {
         \bool_gset_true:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
       }
       {
         \tl_if_eq:nnTF { #4 } { false }
          {
            \bool_gset_false:c { g__flowfram_ #1 _ #2 _ \romannumeral #3 _ bool }
          }
          {
            \msg_error:nnnnnn { flowfram } { invalid-bool }
             { #4 } { #2 } { #1 } { #3 }
          }
       }
    }
    {
      \__flowfram_error:eeeee { frame-unknown-tag }
       { #1 } { #2 } { \int_eval:n { #3 } } { bool }
    }
 }
\cs_generate_variant:Nn \flowfram_frame_set_bool_from_option:nnnn
 { nnnV , nnne }
%    \end{macrocode}
%
%Frames may only be defined in the preamble although the output
%routine will create one if there are none available.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_only_preamble:Nn { #2 }
\cs_new:Nn \__flowfram_forbidden:Nn
 { 
   \msg_error:nnn { flowfram } { misplaced-col-cmd } { #1 }
 }
%    \end{macrocode}
%
%Document only commands:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_only_document_env:Nn
 {
   \msg_error:nnn { flowfram } { doc-env-only } { #1 }
 }
%    \end{macrocode}
%
% \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}
%\changes{2.0}{2025-11-24}{changed to document command}
% 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.
%    \begin{macrocode}
\NewDocumentCommand \flowframeshowlayout { }
 {
  \finishthispage
   \group_begin:
     \__flowfram_set_draft:
     \mbox{}
     \finishthispage
     \clearpage
   \group_end:
 }
%    \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".
%\changes{1.14}{2012-11-10}{made change to switch global}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\newif\ifusedframebreak
\usedframebreaktrue
\NewDocumentCommand \framebreak { O{4} }
{
  \global \usedframebreaktrue
  \group_begin:
    \dim_zero:N \parfillskip
    \pagebreak [ #1 ]
    \dim_zero:N \parskip
    \par
    \noindent
  \group_end: 
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\finishthispage}
% The commands \cs{newpage} and
% \cs{pagebreak} can be used to move on to the next
% \gls{flow}, but to finish the entire page, use 
% "\finishthispage". This is (loosely) based on the code for
% \cs{clearpage}. (\cs{@dbltopnum} not required as we can't have
% column-spanning floats.)
%\changes{1.14}{2012-11-10}{change \cs{c@page} to
%\cs{@ff@pages@countreg}}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \finishthispage { }
{
  \ifvmode
    \int_set_eq:NN \l__flowfram_current_frame_int \c@thisframe
    \int_set_eq:NN \l__flowfram_current_abspage_int \c@absolutepage 
    \dim_compare:nNnT { \pagetotal } < { \topskip }
     {
       \hbox { }
     }
    \newpage
    \write \m@ne { }
    \vbox { }
    \penalty -\@Mi
%    \end{macrocode}
% If that was the last \gls{flow} on the page, then we're done,
% otherwise iterate through the remaining \glspl{flow}.
%    \begin{macrocode}
    \int_compare:nNnT
       { \l__flowfram_current_abspage_int } = { \c@absolutepage }
     {
       \bool_while_do:nn
         {
           \bool_not_p:n
            {
              \int_compare_p:nNn
                { \l__flowfram_current_frame_int } > { \c@maxflow }
            }
         }
       {
         \__flowfram_check_if_this_page:nn
            { \g__flowfram_pagecounter_tl } { \l__flowfram_current_frame_int }
         \bool_if:NF \g__flowfram_not_this_frame_bool
          {
            \int_gset:Nn \c@thisframe { \l__flowfram_current_frame_int }
            \hbox { }
            \newpage
          }
         \int_incr:N \l__flowfram_current_frame_int
       }
     }
  \fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\cleardoublepage}
% Modify the definition of "\cleardoublepage". This may
% or may not be defined.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\providecommand\cleardoublepage{}
\RenewDocumentCommand \cleardoublepage { }
{
  \clearpage
  \if@twoside
    \ifodd \c@page
    \else
      \hbox { }
      \clearpage
    \fi
  \fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\cleartoevenpage}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\NewDocumentCommand \cleartoevenpage { }
{
  \clearpage
  \if@twoside
    \ifodd \c@page
      \hbox { }
      \clearpage
    \fi
  \fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\newpage}
% Modify the definition of \cs{newpage} so that it sets the
% "usedframebreak" flag.
%\changes{1.14}{2012-11-10}{Modified definition of \cs{newpage}}
%    \begin{macrocode}
\preto\newpage{\global\usedframebreaktrue}
%    \end{macrocode}
%\end{macro}
%Need to prevent \cs{@topnewpage} from pushing things out of
%whack as \cs{twocolumn} now behaves differently.
%    \begin{macrocode}
\long\def\@topnewpage[#1]{#1}
%    \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.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \globalreversemargin { }
 {
  \global \@mparbottom \z@
  \global \@reversemargintrue
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\globalnormalmargin}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \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" (to the right or left) 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.) The setting 
% is stored in "\l__flowfram_margin_tl".
% Version 2.0 renamed \cs{@getmarginpos}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_margin_pos:n
 {
  \tl_if_eq:NnTF \c_flowfram_inner_tl { #1 }
   {
     \legacy_if:nTF { @twoside }
      {
        \int_if_odd:nTF { \c@page }
         {
           \tl_set_eq:NN
             \l__flowfram_margin_tl
             \c_flowfram_left_tl
         }
         {
           \tl_set_eq:NN
             \l__flowfram_margin_tl
             \c_flowfram_right_tl
         }
      }
      {
       \tl_set_eq:NN
         \l__flowfram_margin_tl
         \c_flowfram_left_tl
      }
   }
   {
    \tl_if_eq:NnTF \c_flowfram_outer_tl { #1 }
     {
       \legacy_if:nTF { @twoside }
        {
          \int_if_odd:nTF { \c@page }
           {
             \tl_set_eq:NN
               \l__flowfram_margin_tl
               \c_flowfram_right_tl
           }
           {
             \tl_set_eq:NN
               \l__flowfram_margin_tl
               \c_flowfram_left_tl
           }
        }
        {
          \tl_set_eq:NN
            \l__flowfram_margin_tl
            \c_flowfram_right_tl
        }
     }
     {
      \tl_set:Nn \l__flowfram_margin_tl { #1 }
     }
   }
 }
\cs_generate_variant:Nn \__flowfram_get_margin_pos:n { e }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\setmargin}
% Set the margin for current \gls{flow}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setmargin { }
{
 \__flowfram_get_margin_pos:e
  {
    \flowfram_frame_use_tl:nnn { flow } { margin } { \c@thisframe }
  }
 \tl_if_eq:NNTF \l__flowfram_margin_tl \c_flowfram_left_tl 
  {
    \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}.
%    \begin{macrocode}
\NewDocumentCommand \newflowframe
  { s O{all} m m m m O { \int_use:N \c@maxflow } }
 {
   \__flowfram_only_preamble:Nn \newflowframe
    {
      \__flowfram_new_flow:nnnnnn
       { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
%    \end{macrocode}
%If the starred version was used, enable the border frame setting.
%    \begin{macrocode}
      \IfBooleanT { #1 }
        {
%    \end{macrocode}
%\changes{2.1}{2026-02-23}{corrected function name}
%    \begin{macrocode}
          \flowfram_frame_set_bool_true:nnn { flow } { hasframe } { \c@maxflow }
        }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@n@wflowframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@n@wflowframe}
%\end{macro}
%\begin{macro}{\@snewflowframe}
% Starred version sets boolean flag to indicate a border
%Version 2.0 removed \cs{@snewflowframe}.
%\end{macro}
%\begin{macro}{\@newflowframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@newflowframe}.
%\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.
% Version 2.0 removed \cs{@@newflowframe}
%
%\marg{page list}\marg{width}\marg{height}\marg{x}\marg{y}
%    \begin{macrocode}
\cs_new_nopar:Nn \__flowfram_new_flow:nnnnn
 {
   \__flowfram_new_flow:nnnnnn
     { #1 } { #2 } { #3 } { #4 } { #5 } { \int_use:N \c@maxflow }
 }
%    \end{macrocode}
%
%\marg{page list}\marg{width}\marg{height}\marg{x}\marg{y}\marg{label}
%    \begin{macrocode}
\cs_new:Nn  \__flowfram_new_flow:nnnnnn
{
  \__flowfram_new_frame:nnnnnnn
   { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { flow }
%    \end{macrocode}
%Define content box.
%    \begin{macrocode}
  \flowfram_frame_new_box:nnn { flow } { column } { \c@maxflow } 
%    \end{macrocode}
%Define attributes specific to flow frames.
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn { flow } { margin } { \c@maxflow } { right }
%    \end{macrocode}
%Initialise if first (frame may have been created on the fly by the output
%routine).
%    \begin{macrocode}
  \int_if_zero:nT { \c@thisframe }
   {
     \__flowfram_frame_get_start_page:nn { flow } { \c@maxflow }
     \int_compare:nNnT
       { \l__flowfram_range_start_int } = { \c_one_int }
      {
        \int_gset_eq:NN \c@thisframe \c@maxflow
        \__flowfram_set_column:n { \c@maxflow }
        \global\usedframebreaktrue
      }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tflowframeid}
%\changes{2.0}{2025-11-24}{removed}
% If square brackets occur after "\newflowframe", take
% the contents to be the label, otherwise the label will be
% the \gls{flow} number.
% Version 2.0 removed \cs{@s@tflowframeid}.
%\end{macro}
%
%\begin{macro}{\@ff@checkuniqueidl}
%\changes{2.0}{2025-11-24}{removed}
%\marg{flow-id}\marg{label}
% Check proposed label for flow frame is unique.
%Version 2.0 removed \cs{@ff@checkuniqueidl}.
%\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]{%
  \flowfram_frame_use_tl:nnn { flow } { label } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getflowid}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \getflowid { m m }
 {
  \__flowfram_get_flow_id:e { #2 }
  \tl_set:Ne #1 { \int_use:N \l__flowfram_id_int }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowframeid}
%\changes{2.0}{2025-11-24}{renamed}
% Work out the flow frame IDN from the label. This
% iterates through the flow frames, so if you have a lot of
% them it is quicker to identify them by their \gls{idn}
% rather than their \gls{idl}.
% The \gls{idn} will be stored in "\l__flowfram_id_int".
%Version 2.0 renamed \cs{@flowframeid}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_flow_id:n
{
  \__flowfram_if_flow_label_exists:nF { #1 }
   {
     \__flowfram_error:eee { label-undefined } { #1 } { flow }
   }
}
\cs_generate_variant:Nn \__flowfram_get_flow_id:n { e, V }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \__flowfram_if_flow_label_exists:n
 { TF , T , F }
 {
   \__flowfram_if_frame_label_exists:nnNTF
      { flow } { #1 } \l__flowfram_id_int
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
%\begin{macro}{\setallflowframes}
%\changes{2.0}{2025-11-24}{changed to document command}
% 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}
\NewDocumentCommand \setallflowframes { m }
{
  \int_step_inline:nn { \c@maxflow }
   {
     \__flowfram_set_flow_by_idn:nn { ##1 } { #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}
\NewDocumentCommand \setflowframe { s m m }
 {
   \IfBooleanTF { #1 }
    {
      \exp_args:Ne \clist_map_inline:nn { #2 }
       {
         \__flowfram_if_flow_label_exists:nTF { ##1 }
          {
            \__flowfram_set_flow_by_idn:nn { \l__flowfram_id_int } { #3 }
          }
          {
            \__flowfram_error:eee { label-undefined } { ##1 } { flow }
          }
       }
    }
    {
      \__flowfram_map_idns:enn { #2 } { flow }
       {
          \__flowfram_set_flow_by_idn:nn { \l__flowfram_id_int } { #3 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ssetflowframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ssetflowframe}.
%\end{macro}
%
%\begin{macro}{\@setflowframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@setflowframe}.
%\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}
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed from \cs{@@setflowframe}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_flow_by_idn:nn
{
  \__flowfram_set_keys_for_type:nnn { #2 } { flow } { #1 }
%    \end{macrocode}
%Option specific to flow frames:
%    \begin{macrocode}
  \tl_if_empty:NF \l__flowfram_margin_tl
   {
     \flowfram_frame_set_tl:nnnV
       { flow } { margin } { #1 }
       \l__flowfram_margin_tl
   }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowsetpagelist}
% Sets the page list for the \gls{flow} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \flowsetpagelist { m m }
 {
  \flowfram_set_frame_pagelist:nne { flow } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowsetexclusion}
% Sets the exclusion list for the \gls{flow} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \flowsetexclusion { m m }
 {
   \flowfram_set_frame_excludelist:nne { flow } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowaddexclusion}
% Adds to the exclusion list for the \gls{flow} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \flowaddexclusion { m m }
{
  \flowfram_concat_frame_excludelist:nne
   { flow } { #1 } { #2 } 
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@@flowframeswapcoords}
% Swap odd and even offsets for a given \gls{flow}. Do the main stuff for 
% a given \gls{flow} \gls{idn}.
% Version 2.0 renamed \cs{@@flowframeswapcoords}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_swap_coords:n
{
  \flowfram_frame_swap_dim:nnnn
    { flow } { posx } { evenx } { #1 }
  \flowfram_frame_swap_dim:nnnn
    { flow } { posy } { eveny } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffswapoddeven}
% Allow user to specify \gls{flow} either by \gls{idn} or \gls{idl}:
%    \begin{macrocode}
\NewDocumentCommand \ffswapoddeven { s m }
 {
   \IfValueTF { #1 }
    {
      \exp_args:Ne \clist_map_inline:nn { #2 }
       {
         \__flowfram_get_flow_id:n { ##1 }
         \__flowfram_flow_swap_coords:n { \l__flowfram_id_int }
       }
    }
    {
       \__flowfram_map_idns:enn { #2 } { flow }
        {
          \__flowfram_flow_swap_coords:n { \l__flowfram_id_int }
        }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sflowframeswapcoords}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@sflowframeswapcoords}.
%\end{macro}
%\begin{macro}{\@flowframeswapcoords}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@flowframeswapcoords}.
%\end{macro}
%
% Allow user to get the dimensions of \gls{flow} (useful for
% \glspl{flow} created using "\Ncolumn" etc.) Only the \gls{idn} can
% be used for these commands.
%\begin{macro}{\flowframex}
%    \begin{macrocode}
\newcommand*{\flowframex}[1]{%
  \flowfram_frame_use_dim:nnn { flow } { posx } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframey}
%    \begin{macrocode}
\newcommand*{\flowframey}[1]{%
  \flowfram_frame_use_dim:nnn { flow } { posy } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframeevenx}
%    \begin{macrocode}
\newcommand*{\flowframeevenx}[1]{%
  \flowfram_frame_use_dim:nnn { flow } { evenx } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframeeveny}
%    \begin{macrocode}
\newcommand*{\flowframeeveny}[1]{%
  \flowfram_frame_use_dim:nnn { flow } { eveny } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframewidth}
%    \begin{macrocode}
\newcommand{\flowframewidth}[1]{%
  \flowfram_frame_use_dim:nnn { flow } { width } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowframeheight}
%    \begin{macrocode}
\newcommand*{\flowframeheight}[1]{%
  \flowfram_frame_use_dim:nnn { flow } { height } { #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.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \newstaticframe
  { s O{all} m m m m O { \int_use:N \c@maxstatic } }
 {
   \__flowfram_new_static:nnnnnn
    { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
   \IfBooleanT { #1 }
     {
%    \end{macrocode}
%\changes{2.1}{2026-02-23}{corrected function name}
%    \begin{macrocode}
       \flowfram_frame_set_bool_true:nnn
          { static } { hasframe } { \c@maxstatic }
     }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_new_static:nnnnn
 {
   \__flowfram_new_static:nnnnnn
    { #1 } { #2 } { #3 } { #4 } { #5 } { \int_use:N \c@maxstatic }
 }
%    \end{macrocode}
%
%\begin{macro}{\@n@wstaticframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@n@wstaticframe}.
%\end{macro}
%\begin{macro}{\@snewstaticframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@snewstaticframe}.
%\end{macro}
%\begin{macro}{\@newstaticframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@newstaticframe}.
%\end{macro}
%\begin{macro}{\@@newstaticframe}
% Now set up the \gls{static}:
%Version 2.0 renamed \cs{@@newstaticframe}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new_nopar:Nn \__flowfram_new_static:nnnnnn
 {
  \__flowfram_new_frame:nnnnnnn
   { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { static }
%    \end{macrocode}
%Define content box.
%    \begin{macrocode}
  \flowfram_frame_new_box:nnn { static } { content } { \c@maxstatic } 
%    \end{macrocode}
%Define attributes specific to static frames.
%    \begin{macrocode}
  \flowfram_frame_new_bool:nnnN
    { static } { clear } { \c@maxstatic } \c_false_bool 
  \flowfram_frame_new_bool:nnnN
    { static } { hide } { \c@maxstatic } \c_false_bool 
  \flowfram_frame_new_bool:nnnN
    { static } { hidethis } { \c@maxstatic } \c_false_bool 
%    \end{macrocode}
%Inner position argument for minipage environment:
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn
    { static } { valign } { \c@maxstatic } { c }
%    \end{macrocode}
%Paragraph shaping declaration.
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn
    { static } { shape } { \c@maxstatic } { \relax }
%    \end{macrocode}
%Paragraph indentation defaults to \cs{sdfparindent}.
%This is stored as a token list variable rather than a dimension to
%allow it to pick up changes if \cs{sdfparindent} is changed
%afterwards.
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn
    { static } { parindent } { \c@maxstatic } { \sdfparindent }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tstaticframeid}
%\changes{2.0}{2025-11-24}{removed}
%Removed \cs{@s@tstaticframeid}
%\end{macro}
%\begin{macro}{\@sf@checkuniqueidl}
%\changes{2.0}{2025-11-24}{removed}
% Removed \cs{@sf@checkuniqueidl}
%\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]{%
  \flowfram_frame_use_tl:nnn { static } { label } { #1 }
}
%    \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.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \getstaticid { m m }
 {
  \__flowfram_get_static_id:e { #2 }
  \tl_set:Ne #1 { \int_use:N \l__flowfram_id_int }
 }
%    \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 "\l__flowfram_id_int".
%Version 2.0 renamed \cs{@staticframeid}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_static_id:n
{
  \__flowfram_if_static_label_exists:nF { #1 }
   {
     \__flowfram_error:eee { label-undefined } { #1 } { static }
   }
}
\cs_generate_variant:Nn \__flowfram_get_static_id:n { e, V }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \__flowfram_if_static_label_exists:n
 { TF , T , F }
 {
   \__flowfram_if_frame_label_exists:nnNTF
      { static } { #1 } \l__flowfram_id_int
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
% Make it easier to get the x and y values for static
% frames.
%\begin{macro}{\staticframex}
%    \begin{macrocode}
\newcommand*{\staticframex}[1]{%
  \flowfram_frame_use_dim:nnn { static } { posx } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticframey}
%    \begin{macrocode}
\newcommand*{\staticframey}[1]{%
  \flowfram_frame_use_dim:nnn { static } { posy } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticframeevenx}
%    \begin{macrocode}
\newcommand*{\staticframeevenx}[1]{%
  \flowfram_frame_use_dim:nnn { static } { evenx } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticframeeveny}
%    \begin{macrocode}
\newcommand*{\staticframeeveny}[1]{%
  \flowfram_frame_use_dim:nnn { static } { eveny } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticframewidth}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand*{\staticframewidth}[1]{%
  \flowfram_frame_use_dim:nnn { static } { width } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticframeheight}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand*{\staticframeheight}[1]{%
  \flowfram_frame_use_dim:nnn { static } { height } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\setallstaticframes}
% Modify the settings for all the \glspl{static}:
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setallstaticframes { m }
 {
  \int_step_inline:nn { \c@maxstatic }
   {
     \__flowfram_set_static_by_idn:nn { ##1 } { #1 }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setstaticframe}
% Modify the settings for the specified \glspl{static}:
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setstaticframe { s m m }
 {
   \IfBooleanTF { #1 }
    {
      \exp_args:Ne \clist_map_inline:nn { #2 }
       {
         \__flowfram_if_static_label_exists:nTF { ##1 }
          {
            \__flowfram_set_static_by_idn:nn { \l__flowfram_id_int } { #3 }
          }
          {
            \__flowfram_error:eee { label-undefined } { ##1 } { static }
          }
       }
    }
    {
      \__flowfram_map_idns:enn { #2 } { static }
       {
          \__flowfram_set_static_by_idn:nn { \l__flowfram_id_int } { #3 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ssetstaticframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ssetstaticframe}.
%\end{macro}
%\begin{macro}{\@setstaticframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@setstaticframe}.
%\end{macro}
%\begin{macro}{\@@setstaticframe}
%\changes{2.0}{2025-11-24}{renamed}
% Modify the settings for the \gls{static} whose \gls{idn}
% is given by the first argument.
% Version 2.0 renamed \cs{@@setstaticframe}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_static_by_idn:nn
{
  \__flowfram_set_keys_for_type:nnn { #2 } { static } { #1 }
%    \end{macrocode}
%Option specific to static frames:
%    \begin{macrocode}
  \tl_if_empty:NF \l__flowfram_clearflag_tl
   {
     \flowfram_frame_set_bool_from_option:nnnV
      { static } { clear } { #1 }
     \l__flowfram_clearflag_tl
   }
  \tl_if_empty:NF \l__flowfram_hideflag_tl
   {
     \flowfram_frame_set_bool_from_option:nnnV
      { static } { hide } { #1 }
     \l__flowfram_hideflag_tl
   }
  \tl_if_empty:NF \l__flowfram_hidethisflag_tl
   {
     \flowfram_frame_set_bool_from_option:nnnV
      { static } { hidethis } { #1 }
     \l__flowfram_hidethisflag_tl
   }
  \exp_args:NV \tl_if_novalue:nF \l__flowfram_shape_tl
   {
     \flowfram_frame_set_tl:nnnV
      { static } { shape } { #1 } \l__flowfram_shape_tl
   }
  \exp_args:NV \tl_if_novalue:nF \l__flowfram_parindent_tl
   {
     \flowfram_frame_set_tl:nnnV
      { static } { parindent } { #1 } \l__flowfram_parindent_tl
   }
  \tl_if_empty:NF \l__flowfram_valign_tl
   {
     \flowfram_frame_set_tl:nnnV
        { static } { valign } { #1 }
       \l__flowfram_valign_tl
   }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FLFsimpar}
%\changes{2.0}{2025-11-24}{new}
% Simulate paragraph break inside "\shapepar".
%Version 2.0: the command is now called \cs{FLFsimpar}
%to reduce the chances of a name clash.
%    \begin{macrocode}
\NewDocumentCommand \FLFsimpar { }
 {
  \hfill \newline
  \hspace* { \parindent }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\simpar}
%Provide old command for backward-compatibility if it doesn't clash.
%    \begin{macrocode}
\providecommand*{\simpar}{\FLFsimpar}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffpshpar}
% Provide means to allow parshape to be carried over a paragraph 
% break. Deprecated as from v2.0.
% Does nothing now. Marked for removal.
%\changes{2.0}{2025-11-24}{deprecated}
%    \begin{macrocode}
\newcommand \ffpshpar { }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\FLForgpar}
%Version 2.0: no longer used.
%\changes{2.0}{2025-11-24}{deprecated}
%    \begin{macrocode}
\let\FLForgpar\par
%    \end{macrocode}
%\end{macro}
%
% Provide a means to have section headings within "\parshape".
%\begin{macro}{\@ff@parshape}
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed \cs{@ff@parshape}.
%    \begin{macrocode}
\tl_new:N \l__flowfram_parshape_tl 
\tl_set:Nn \l__flowfram_parshape_tl { \parshape = 0 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@sectionhead}
% Version 2.0 removed \cs{@ff@sectionhead}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@s@ff@heading}
% Version 2.0 removed \cs{@s@ff@heading}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@ff@heading}
% Version 2.0 removed \cs{@ff@heading}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%    \begin{macrocode}
\tl_new:N \l__flowfram_current_pre_section_tl
\tl_new:N \@@flowfram@current@pre@section@title
\tl_new:N \l__flowfram_current_post_section_tl
%    \end{macrocode}
%
%If a document class supports an optional argument for sectioning
%units, redefine to include the second argument in square brackets.
%    \begin{macrocode}
\cs_new:Nn \flowfram_nonum_section:Nnn
 {
   #1 * { #3 }
 }
\cs_generate_variant:Nn \flowfram_nonum_section:Nnn { cVn }
%    \end{macrocode}
%
%\begin{macro}{\addtocontents}
%\changes{2.0}{2025-11-24}{added redefinition}
%    \begin{macrocode}
\renewcommand \addtocontents [2]
 {
   \protected@write \@auxout
     {
       \let \label \@gobble@om
       \let \index \@gobble@som
       \let \glossary \@gobble@om
       \let \@@flowfram@current@pre@section@title \empty
       \let \theFramePageCounter \relax
     }
     {
       \string \@writefile { #1 } { #2 }
     }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FlowFramSectionUnit}
%Do the original sectioning command but take into account the
%current paragraph shape and thumb tab settings. This has an extra
%optional argument for the thumbtab title. NB memoir also has an
%extra optional argument for the header so include option to allow
%for this. The KOMA-Script classes now support a key=value optional
%argument, so also need an option to allow for that.
%    \begin{macrocode}
\bool_new:N \l__flowfram_starred_section_bool
\tl_new:N \l__flowfram_section_thumbtab_title_tl
\NewDocumentCommand \FlowFramSectionUnit { m s o o m }
 {
   \tl_clear:N \l__flowfram_section_toc_tl
   \tl_clear:N \l__flowfram_section_head_tl
   \tl_clear:N \l__flowfram_section_opti_tl
   \tl_clear:N \l__flowfram_section_optii_tl
   \tl_clear:N \l__flowfram_section_thumbtab_title_tl 
   \cs_if_exist:cTF { __flowfram_org_ #1 : }
    {
%    \end{macrocode}
%Do initial hook.
%    \begin{macrocode}
      \l__flowfram_current_pre_section_tl
%    \end{macrocode}
%Initialise header and toc variables:
%    \begin{macrocode}
      \IfValueTF { #3 }
       {
         \tl_if_empty:nTF { #3 }
          {
            \tl_set:Nn \l__flowfram_section_opti_tl { #5 }
            \tl_set:Nn \l__flowfram_section_toc_tl { #5 }
          }
          {
            \tl_set:Nn \l__flowfram_section_opti_tl { #3 }
            \tl_set:Nn \l__flowfram_section_toc_tl { #3 }
          }
         \bool_if:NT \l__flowfram_section_keyval_opt_bool
          {
%    \end{macrocode}
%The first optional argument may be a key=value list.
%    \begin{macrocode}
            \tl_if_in:NnT = { #3 }
             {
               \keys_set_known:nn { flowfram / section } { #3 }
             }
          }
       }
       {
         \tl_set:Nn \l__flowfram_section_opti_tl { #5 }
       }
      \tl_if_empty:NT \l__flowfram_section_toc_tl
       {
         \tl_set:Nn \l__flowfram_section_toc_tl { #5 }
       }
      \IfValueT { #4 }
       {
%    \end{macrocode}
% Second optional argument has been provided.
%    \begin{macrocode}
         \bool_if:NT \l__flowfram_section_header_opt_bool
          {
%    \end{macrocode}
% Second optional argument should be passed to original command.
%    \begin{macrocode}
            \tl_set:Nn \l__flowfram_section_optii_tl { #4 }
          }
         \bool_if:NTF \l__flowfram_section_header_opt_thumbtab_bool 
          {
%    \end{macrocode}
% Second optional argument should be used as the thumbtab title.
%    \begin{macrocode}
            \tl_set:Nn \l__flowfram_section_thumbtab_title_tl { #4 }
          }
          {
            \tl_set_eq:NN
              \l__flowfram_section_thumbtab_title_tl 
              \l__flowfram_section_toc_tl
          }
       }
     \tl_if_empty:NT \l__flowfram_section_head_tl
      {
         \tl_set_eq:NN
           \l__flowfram_section_head_tl
           \l__flowfram_section_toc_tl
       }
     \tl_if_empty:NT \l__flowfram_section_thumbtab_title_tl 
       {
         \tl_set_eq:NN
           \l__flowfram_section_thumbtab_title_tl 
           \l__flowfram_section_head_tl
       }
%    \end{macrocode}
%Starred?
%    \begin{macrocode}
      \IfBooleanTF { #2 }
       {
         \bool_set_true:N \l__flowfram_starred_section_bool
         \__flowfram_if_df_chapter:nTF { #1 }
          {
%    \end{macrocode}
%Ensure arguments are expanded in case they contain placeholder
%commands, such as \cs{glossarytitle}.
%    \begin{macrocode}
            \exp_args:Nee
            \__flowfram_df_chapter_star:nn
               { \l__flowfram_section_opti_tl }
               { #5 }
          }
          {
            \flowfram_nonum_section:cVn
              { __flowfram_org_ #1 : } 
               \l__flowfram_section_opti_tl
              {
                \@@flowfram@current@pre@section@title
                #5
              }
          }
       }
       {
         \bool_set_false:N \l__flowfram_starred_section_bool
         \__flowfram_if_df_chapter:nTF { #1 }
          {
%    \end{macrocode}
%Ensure arguments are expanded in case they contain placeholder
%commands, such as \cs{glossarytitle}.
%    \begin{macrocode}
             \tl_if_empty:NTF \l__flowfram_section_optii_tl
              {
                \exp_args:Nee
                \__flowfram_df_chapter:nn 
                { \l__flowfram_section_opti_tl }
                { #5 } 
              }
              {
                \exp_args:Neee
                \__flowfram_df_chapter:nnn
                { \l__flowfram_section_opti_tl }
                { \l__flowfram_section_optii_tl }
                { #5 } 
              }
          }
          {
            \__flowfram_use_original_sec:cVVn
              { __flowfram_org_ #1 : } 
              \l__flowfram_section_opti_tl
              \l__flowfram_section_optii_tl
              { #5 }
          }
       }
      \cs_if_exist:cF { __flowfram_org_end_ #1 : }
       {
         \__flowfram_post_section_unit:n { #1 }
       } 
      \l__flowfram_current_post_section_tl
   }
   {
     \msg_error:nne { flowfram } { unknown-heading-cmd }
       { #1 }
   }
  \@afterheading
 }
%    \end{macrocode}
%\end{macro}
%Use original section command:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_use_original_sec:Nnnn
 {
   \tl_if_empty:nTF { #3 }
    {
      #1 [ #2 ]
        {
          \@@flowfram@current@pre@section@title
          #4
        }
    }
    {
      #1 [ #2 ] [ #3 ]
        {
          \@@flowfram@current@pre@section@title
          #4
        }
    }
 }
\cs_generate_variant:Nn \__flowfram_use_original_sec:Nnnn
  { cVVn , cVnn , cnnn }
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_post_section_unit:n
 {
%    \end{macrocode}
% Add thumbtab if applicable.
%    \begin{macrocode}
   \__flowfram_add_thumbtab:n { #1 }
%    \end{macrocode}
%Do minitoc if supported.
%    \begin{macrocode}
   \bool_if:NF \l__flowfram_starred_section_bool
    {
      \__flowfram_minitoc_post_section_unit:n { #1 }
    }
 }
%    \end{macrocode}
%Does nothing until redefined by \cs{enablethumbtabs}:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_add_thumbtab:n { }
\cs_new:Nn \__flowfram_actual_add_thumbtab:n 
 {
   \tl_if_eq:eeT \g__flowfram_thumbtab_type_tl { #1 }
    {
      \bool_if:NTF \l__flowfram_starred_section_bool
       {
         \__flowfram_ttb_nonum:n { \l__flowfram_section_thumbtab_title_tl }
       }
       {
         \flowfram_if_mainmatter:TF
          {
            \__flowfram_ttb_num:n
              { \l__flowfram_section_thumbtab_title_tl }
          }
          {
            \__flowfram_ttb_notmainmatter_num:n
              { \l__flowfram_section_thumbtab_title_tl }
          }
       }
    }
 }
%    \end{macrocode}
%Hook for minitocs (redefined by \cs{enableminitoc}):
%    \begin{macrocode}
\cs_new:Nn \__flowfram_minitoc_post_section_unit:n
 {
 }
%    \end{macrocode}
%
%Adjust sectioning commands definitions.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_provide_section_unit:n
 {
   \cs_if_exist:cT { #1 }
    {
      \cs_set_eq:cc { __flowfram_org_ #1 : }  { #1 }
      \cs_set:cpn { #1 }
       {
          \FlowFramSectionUnit { #1 }
       }
%    \end{macrocode}
% 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.)
%    \begin{macrocode}
      \cs_if_exist:cT { @end #1 }
       {
         \cs_set_eq:cc { __flowfram_org_end_ #1 : }  { @end #1 }
         \cs_set:cpn { @end #1 }
          {
            \__flowfram_post_section_unit:n { #1 }
            \use:c {  __flowfram_org_end_ #1 : }
          }
       }
    }
 }
\__flowfram_provide_section_unit:n { part }
\__flowfram_provide_section_unit:n { chapter }
\__flowfram_provide_section_unit:n { section }
\__flowfram_provide_section_unit:n { subsection }
\__flowfram_provide_section_unit:n { subsubsection }
\__flowfram_provide_section_unit:n { paragraph }
\__flowfram_provide_section_unit:n { subparagraph }
%    \end{macrocode}
%
%\begin{macro}{\@ff@setsecthead}
% Define command to switch to adjusted section headings:
% Version 2.0 renamed \cs{@ff@setsecthead}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_shaped_section_headings:  
 {
   \tl_set:Nn \l__flowfram_current_pre_section_tl
    {
       \FLFsimpar
       \begin { minipage } { \linewidth }
       \let \par \endgraf
    }
   \tl_set:Nn \l__flowfram_current_post_section_tl
    {
       \end { minipage }
       \FLFsimpar
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@getshape}
%\changes{2.0}{2025-11-24}{renamed}
% Determine what shape command is being used:
% Version 2.0 renamed \cs{@ff@getshape}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_shape:n
 {
   \tl_if_head_eq_meaning:nNTF { #1 } \parshape
    {
      \int_set_eq:NN
        \l__flowfram_shape_int
        \c_flowfram_shape_type_parshape_int
    }
    {
      \tl_if_head_eq_meaning:nNTF { #1 } \shapepar
       {
         \int_set_eq:NN
           \l__flowfram_shape_int
           \c_flowfram_shape_type_shapepar_int
       }
       {
         \tl_if_head_eq_meaning:nNTF { #1 } \Shapepar
          {
            \int_set_eq:NN
              \l__flowfram_shape_int
              \c_flowfram_shape_type_shapepar_int
          }
          {
            \tl_if_head_eq_meaning:nNTF { #1 } \relax
             {
               \int_set_eq:NN
                \l__flowfram_shape_int
                \c_flowfram_shape_type_none_int
             }
             {
               \msg_error:nnn { flowfram } { unknown-shape } { #1 }
               \int_set_eq:NN
                 \l__flowfram_shape_int
                 \c_flowfram_shape_type_shapepar_int
             }
          }
       }
    }
 }
\cs_generate_variant:Nn \__flowfram_get_shape:n { V }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_disabled_sec:NN
 {
   \msg_error:nnnn { flowfram } { forbidden-cmd-in-shape } { #1 } { #2 }
   \@gobble@som
 }
%    \end{macrocode}
%
%\begin{macro}{\@ff@disablesec}
% Disable sectioning commands
%    \begin{macrocode}
\newcommand*{\@ff@disablesec}{%
  \def\section{
    \__flowfram_disabled_sec:NN \section \shapepar
  }
  \def\subsection{
    \__flowfram_disabled_sec:NN \subsection \shapepar
  }
  \def\subsubsection{
    \__flowfram_disabled_sec:NN \subsubsection \shapepar
  }
  \def\paragraph{
    \__flowfram_disabled_sec:NN \paragraph \shapepar
  }
  \def\subparagraph{
    \__flowfram_disabled_sec:NN \subparagraph \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}.
%\changes{2.0}{2025-11-24}{changed to document environment}
%Version 2.0 added optional argument to also set frame options at
%the same time. (All settings are global so this shouldn't be
%localised by the environment.)
%    \begin{macrocode}
\newbox\staticframe
\NewDocumentEnvironment { staticcontents } { o m } 
{
  \IfValueT { #1 }
   {
     \__flowfram_set_static_by_idn:nn { #2 } { #1 }
   }
  \RenewDocumentCommand \continueonframe { o m }
    {
      \__flowfram_static_continue_idn:nn { ##1 } { ##2 }
    }
  \__flowfram_static_contents_begin:n { #2 }
}
{
  \__flowfram_static_contents_end:
  \ignorespacesafterend
}
%    \end{macrocode}
%\end{environment}
%\begin{environment}{staticcontents*}
% Set the contents of the \gls{static} given by its \gls{idl}.
% Syntax: "\begin{staticcontents*}"\marg{label}.
%Version 2.0 added optional argument to also set frame options at
%the same time. (All settings are global so this shouldn't be
%localised by the environment.)
%\changes{2.0}{2025-11-24}{changed to document environment}
%    \begin{macrocode}
\NewDocumentEnvironment { staticcontents* } { o m }
{
  \__flowfram_get_static_id:n { #2 }
  \IfValueT { #1 }
   {
     \__flowfram_set_static_by_idn:nn
        { \l__flowfram_id_int }
        { #1 }
   }
  \RenewDocumentCommand \continueonframe { o m }
    {
       \__flowfram_static_continue_idl:nn { ##1 } { ##2 }
    }
  \__flowfram_static_contents_begin:n { \l__flowfram_id_int }
}
{
  \__flowfram_static_contents_end:
  \ignorespacesafterend
}
%    \end{macrocode}
%\end{environment}
%
%\begin{macro}{\@beginstaticcontents}
%\changes{2.0}{2025-11-24}{renamed}
% Begin staticcontents stuff.
%Version 2.0 renamed \cs{@beginstaticcontents}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_contents_begin:n
{
  \int_zero:N \l__flowfram_current_static_int
  \box_if_exist:cTF
      { g__flowfram_static_content_ \romannumeral #1 _box }
   {
     \int_set:Nn \l__flowfram_current_static_int { #1 }
     \tl_set:Ne \l__flowfram_minipage_tl
      {
        \exp_not:N \begin { minipage }
         [ c ]
         [
           \staticframeheight { #1 }
         ]
         [
           \flowfram_frame_use_tl:nnn
            { static } { valign } { #1 }
         ]
         {
           \staticframewidth { #1 }
         }
      }
     \flowfram_set_tl_to_frame_tl:Nnnn
       \l__flowfram_parindent_tl
       { static } { parindent } { #1 }
     \flowfram_set_tl_to_frame_tl:Nnnn
       \l__flowfram_parshape_tl
       { static } { shape } { #1 }
     \__flowfram_get_shape:V \l__flowfram_parshape_tl
     \int_case:nnF { \l__flowfram_shape_int }
      {
        { \c_flowfram_shape_type_none_int }
%    \end{macrocode}
% No shape (nothing extra to do)
%    \begin{macrocode}
          { }
        { \c_flowfram_shape_type_parshape_int }
         {
%    \end{macrocode}
% \cs{parshape}:
%    \begin{macrocode}
           \tl_put_right:NV
             \l__flowfram_minipage_tl
             \l__flowfram_parshape_tl
           \tl_put_right:Nn \l__flowfram_minipage_tl
             {
               \let \par \FLFsimpar
               \__flowfram_set_shaped_section_headings: 
             }
         }
      }
      {
%    \end{macrocode}
% \cs{shapepar} or \cs{Shapepar}:
%    \begin{macrocode}
        \tl_put_right:Nn \l__flowfram_minipage_tl
          {
            \@ff@disablesec
          }
        \tl_put_right:NV
          \l__flowfram_minipage_tl
          \l__flowfram_parshape_tl
      }
     \UseHook { flowfram / staticbox / before }
     \begin { lrbox } { \staticframe }
       \flowfram_set_tl_to_frame_tl:Nnnn
         \l__flowfram_textcolor_tl
         { static } { textcolor } { #1 }
       \__flowfram_set_text_color:
       \noindent
       \l__flowfram_minipage_tl
       \dim_set:Nn \parindent { \l__flowfram_parindent_tl }
   }
   {
     \msg_error:nnnn { flowfram } { idn-undefined } { static } { #1 }
   }
}
%    \end{macrocode}
%\end{macro}
%
%Hooks used before and after lrbox environment when static contents
%are set. Since the box is set within the \env{staticcontents} or
%\env{staticcontents*} environments, it will be within a scoped
%context.
%    \begin{macrocode}
\NewMirroredHookPair
 { flowfram / staticbox / before }
 { flowfram / staticbox / after }
%    \end{macrocode}
%
%\begin{macro}{\@endstaticcontents}
%\changes{2.0}{2025-11-24}{renamed}
% End staticcontents stuff.
% Version 2.0 renamed \cs{@endstaticcontents}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_contents_end:
{
  \int_if_zero:nF { \l__flowfram_current_static_int }
   {
     \endgraf 
%    \end{macrocode}
%Grouping has been removed as it interferes with \cs{shapepar} but
%the environment already provides scoping.
%    \begin{macrocode}
     \end { minipage }
     \end { lrbox }
     \UseHook { flowfram / staticbox / after }
     \flowfram_frame_set_box_eq:nnnN
       { static } { content } { \l__flowfram_current_static_int }
       \staticframe
   }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\setstaticcontents}
% Provide a command version.
% Syntax: \cs{setstaticcontents}\oarg{options}\marg{idn}\marg{text}.
%\changes{2.0}{2025-11-24}{changed to document command}
%Version 2.0 added optional argument to also set frame options at
%the same time.
%    \begin{macrocode}
\NewDocumentCommand \setstaticcontents { s o m +m }
{
  \IfBooleanTF { #1 }
   {
     \__flowfram_get_static_id:n { #3 }
     \IfValueT { #2 }
      {
        \__flowfram_set_static_by_idn:nn
           { \l__flowfram_id_int }
           { #2 }
      }
     \begin { staticcontents } { \l__flowfram_id_int }
       #4
     \end { staticcontents }
   }
   {
     \IfValueT { #2 }
      {
        \__flowfram_set_static_by_idn:nn { #3 } { #2 }
      }
     \begin { staticcontents } { #3 }
       #4
     \end { staticcontents }
   }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticconts}
%Version 2.0 removed \cs{@sstaticconts}.
%\end{macro}
%\begin{macro}{\@staticconts}
%Version 2.0 removed \cs{@staticconts}.
%\end{macro}
%
%\begin{macro}{\staticsetpagelist}
% Sets the page list for the \gls{static} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \staticsetpagelist { m m }
 {
  \flowfram_set_frame_pagelist:nne { static } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticsetexclusion}
% Sets the exclusion list for the \gls{static} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \staticsetexclusion { m m }
 {
   \flowfram_set_frame_excludelist:nne { static } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticaddexclusion}
% Adds to the exclusion list for the \gls{static} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \staticaddexclusion { m m }
 {
  \flowfram_concat_frame_excludelist:nne
   { static } { #1 } { #2 } 
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@@staticframeswapcoords}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@@staticframeswapcoords}.
%\end{macro}
%\begin{macro}{\sfswapoddeven}
% Swap odd and even offsets for a given \gls{static}.
% Allow user to specify \gls{static} either by \gls{idn} or \gls{idl}:
%    \begin{macrocode}
\NewDocumentCommand \sfswapoddeven { s m }
{
   \IfValueTF { #1 }
    {
      \exp_args:Ne \clist_map_inline:nn { #2 }
       {
         \__flowfram_get_static_id:n { ##1 }
         \__flowfram_static_swap_coords:n { \l__flowfram_id_int }
       }
    }
    {
       \__flowfram_map_idns:enn { #2 } { static }
        {
          \__flowfram_static_swap_coords:n { \l__flowfram_id_int }
        }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sstaticframeswapcoords}
%\changes{2.0}{2025-11-24}{removed}
% Version 2.0 removed \cs{@sstaticframeswapcoords}.
%\end{macro}
%\begin{macro}{\@staticframeswapcoords}
%\changes{2.0}{2025-11-24}{renamed}
% Version 1.18 renamed \cs{@staticframeswapcoords}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_swap_coords:n
{
  \flowfram_frame_swap_dim:nnnn
    { static } { posx } { evenx } { #1 }
  \flowfram_frame_swap_dim:nnnn
    { static } { posy } { eveny } { #1 }
}
%    \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.
% Version 2.0 now allows \cs{continueonframe} in
% \cs{setdynamiccontents} but not in
% \cs{appenddynamiccontents}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \continueonframe { O{} m }
 {
   \msg_error:nn { flowfram } { cant-continue }
 }
%    \end{macrocode}
%\end{macro}
% \cs{@scontinueonframe} and \cs{@continueonframe} are set
% by \env{staticcontents} and \env{dynamiccontents} environments
% (and their starred forms).
%
%\begin{macro}{\@staticscontinueonframe}
% Static starred version uses \gls{idl}
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 replaced \cs{@staticscontinueonframe}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_continue_idl:nn
 {
   \IfValueTF { #1 }
    {
      \ffcontinuedtextlayout { #1 }
    }
    {
      \ffcontinuedtextlayout
       {
         \flowfram_continue_on_static_frame_idl:Nn
           \l__flowfram_current_static_int 
           { #2 }
       }
    }
   \exp_args:NnNV
   \end { staticcontents* }
   \__flowfram_set_post_continued:nnn
      \l__flowfram_current_static_int
      { \l__flowfram_current_static_int }
      { \c_flowfram_frame_type_static_int }
   \tl_put_left:Nn \l__flowfram_postcontinued_tl
     { \begin { staticcontents* } { #2 } }
   \l__flowfram_postcontinued_tl
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@staticcontinueonframe}
% Static unstarred version uses \gls{idn}
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 replaced \cs{@staticcontinueonframe}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_continue_idn:nn
 {
   \IfValueTF { #1 }
    {
      \ffcontinuedtextlayout { #1 }
    }
    {
      \ffcontinuedtextlayout
       { 
         \flowfram_continue_on_static_frame_idn:Nn
           \l__flowfram_current_static_int 
           { #2 }
       }
    }
   \exp_args:NnNV
   \end { staticcontents }
    \__flowfram_set_post_continued:nnn
      \l__flowfram_current_static_int
      { \l__flowfram_current_static_int }
      { \c_flowfram_frame_type_static_int }
   \tl_put_left:Nn \l__flowfram_postcontinued_tl
     { \begin { staticcontents } { #1 } }
   \l__flowfram_postcontinued_tl
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\tl_new:N \l__flowfram_postcontinued_tl
\cs_new:Nn \__flowfram_set_post_continued:nnn
 {
  \int_case:nnF { #3 }
   { 
     { \c_flowfram_frame_type_static_int }
      {
        \tl_set:Nn \l__flowfram_postcontinued_tl
          {
            \ffstaticpostcontinued { #1 } { #2 }
          }
      }
     { \c_flowfram_frame_type_dynamic_int }
      {
        \tl_set:Nn \l__flowfram_postcontinued_tl
          {
            \ffdynamicpostcontinued { #1 } { #2 }
          }
      }
   }
   {
      \tl_clear:N \l__flowfram_postcontinued_tl
   }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_continue_on_static_frame_idn:Nn
 {
   \ffdefaultstaticcontinuetext { #1 } { #2 }
 }
%    \end{macrocode}
%
%The first argument is the IDN of the current frame and the second
%is the label of the next frame.
%    \begin{macrocode}
\cs_new:Nn \flowfram_continue_on_static_frame_idl:Nn
 {
   \__flowfram_get_static_id:n { #2 }
   \flowfram_continue_on_static_frame_idn:Nn #1 { \l__flowfram_id_int }
 }
%    \end{macrocode}
%
%\begin{macro}{\ffdefaultstaticcontinuetext}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ffdefaultstaticcontinuetext [ 2 ] { \ffdefaultcontinuetext }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffdefaultdynamiccontinuetext}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ffdefaultdynamiccontinuetext [ 2 ] { \ffdefaultcontinuetext }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffdefaultcontinuetext}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ffdefaultcontinuetext { }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffstaticpostcontinued}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ffstaticpostcontinued [ 2 ]
 {
   \ffdefaultpostcontinued 
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffdynamicpostcontinued}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ffdynamicpostcontinued [ 2 ]
 {
   \ffdefaultpostcontinued 
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffdefaultpostcontinued}
%\changes{2.0}{2025-11-24}{new}
%\begin{definition}
%\cs{ffdefaultpostcontinued}
%\end{definition}
%Hook for start of next frame:
%    \begin{macrocode}
\newcommand{\ffdefaultpostcontinued}{%
  \par
  \noindent
  \ignorespaces
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffcontinuedtextlayout}
%Displays the continued text used by \cs{continueonframe}.
%    \begin{macrocode}
\newcommand{\ffcontinuedtextlayout}[1]{%
  \group_begin:
  \dim_zero:N \parfillskip
  \par
  \hfill
  \ffcontinuedtextfont { #1 }
  \par
  \group_end:
}
%    \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{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}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \newdynamicframe 
  { s O{all} m m m m O { \int_use:N \c@maxdynamic } }
 {
   \__flowfram_new_dynamic:nnnnnn
    { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
   \IfBooleanT { #1 }
     {
%    \end{macrocode}
%\changes{2.1}{2026-02-23}{corrected function name}
%    \begin{macrocode}
       \flowfram_frame_set_bool_true:nnn
          { dynamic } { hasframe } { \c@maxdynamic }
     }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_new_dynamic:nnnnn
 {
   \__flowfram_new_dynamic:nnnnnn
    { #1 } { #2 } { #3 } { #4 } { #5 } { \int_use:N \c@maxdynamic }
 }
%    \end{macrocode}
%
%\begin{macro}{\@n@wdynamicframe}
%Version 2.0 removed \cs{@n@wdynamicframe}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@snewdynamicframe}
%Version 2.0 removed \cs{@snewdynamicframe}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@newdynamicframe}
%Version 2.0 removed \cs{@newdynamicframe}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@newdynamicframe}
% Create new \gls{dynamic}:
%Version 2.0 renamed \cs{@@newdynamicframe}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new_nopar:Nn \__flowfram_new_dynamic:nnnnnn
 {
  \__flowfram_new_frame:nnnnnnn
   { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { dynamic }
%    \end{macrocode}
%Define content token list.
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnn { dynamic } { content } { \c@maxdynamic } 
%    \end{macrocode}
%Define attributes specific to dynamic frames.
%    \begin{macrocode}
  \flowfram_frame_new_bool:nnnN
    { dynamic } { clear } { \c@maxdynamic } \c_false_bool 
  \flowfram_frame_new_bool:nnnN
    { dynamic } { hide } { \c@maxdynamic } \c_false_bool 
  \flowfram_frame_new_bool:nnnN
    { dynamic } { hidethis } { \c@maxdynamic } \c_false_bool 
%    \end{macrocode}
%Inner position argument for \cs{parbox}:
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn
    { dynamic } { valign } { \c@maxdynamic } { t }
%    \end{macrocode}
%Paragraph shaping declaration.
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn
    { dynamic } { shape } { \c@maxdynamic } { \relax }
%    \end{macrocode}
%Paragraph indentation defaults to \cs{sdfparindent}.
%This is stored as a token list variable rather than a dimension to
%allow it to pick up changes if \cs{sdfparindent} is changed.
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn
    { dynamic } { parindent } { \c@maxdynamic } { \sdfparindent }
%    \end{macrocode}
%Formatting style csname.
%    \begin{macrocode}
  \flowfram_frame_new_tl:nnnn
    { dynamic } { style } { \c@maxdynamic } { @firstofone }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tdynamicframeid}
%Version 2.0 removed \cs{@s@tdynamicframeid}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@df@checkuniqueidl}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@df@checkuniqueidl}.
%\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]{%
  \flowfram_frame_use_tl:nnn { dynamic } { label } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getdynamicid}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \getdynamicid { m m }
 {
  \__flowfram_get_dynamic_id:e { #2 }
  \tl_set:Ne #1 { \int_use:N \l__flowfram_id_int }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicframeid}
% Determine the \gls{idn} of the \gls{dynamic} from its label.
% The \gls{idn} is stored in "\l__flowfram_id_int".
%Version 2.0 renamed \cs{@dynamicframeid}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_dynamic_id:n
{
  \__flowfram_if_dynamic_label_exists:nF { #1 }
   {
     \__flowfram_error:eee { label-undefined } { #1 } { dynamic }
   }
}
\cs_generate_variant:Nn \__flowfram_get_dynamic_id:n { e, V }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\prg_new_conditional:Nnn \__flowfram_if_dynamic_label_exists:n
 { TF , T , F }
 {
   \__flowfram_if_frame_label_exists:nnNTF
      { dynamic } { #1 } \l__flowfram_id_int
    { \prg_return_true: }
    { \prg_return_false: }
 }
%    \end{macrocode}
%
% 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]{%
  \flowfram_frame_use_dim:nnn { dynamic } { posx } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicframey}
%    \begin{macrocode}
\newcommand*{\dynamicframey}[1]{%
  \flowfram_frame_use_dim:nnn { dynamic } { posy } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicframeevenx}
%    \begin{macrocode}
\newcommand*{\dynamicframeevenx}[1]{%
  \flowfram_frame_use_dim:nnn { dynamic } { evenx } { #1 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicframeeveny}
%    \begin{macrocode}
\newcommand*{\dynamicframeeveny}[1]{%
  \flowfram_frame_use_dim:nnn { dynamic } { eveny } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicframewidth}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand*{\dynamicframewidth}[1]{%
  \flowfram_frame_use_dim:nnn { dynamic } { width } { #1 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicframeheight}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand*{\dynamicframeheight}[1]{%
  \flowfram_frame_use_dim:nnn { dynamic } { height } { #1 }
}
%    \end{macrocode}
%
%\end{macro}
%\begin{macro}{\setalldynamicframes}
% Change the settings for all the \glspl{dynamic}:
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setalldynamicframes { m }
 {
  \int_step_inline:nn { \c@maxdynamic }
   {
     \__flowfram_set_dynamic_by_idn:nn { ##1 } { #1 }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\setdynamicframe}
% Change the settings for specified \glspl{dynamic}:
% The starred version iterates through comma-separated list
% of labels.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setdynamicframe { s m m }
 {
   \IfBooleanTF { #1 }
    {
      \exp_args:Ne \clist_map_inline:nn { #2 }
       {
         \__flowfram_if_dynamic_label_exists:nTF { ##1 }
          {
            \__flowfram_set_dynamic_by_idn:nn { \l__flowfram_id_int } { #3 }
          }
          {
            \__flowfram_error:eee { label-undefined } { ##1 } { dynamic }
          }
       }
    }
    {
      \__flowfram_map_idns:enn { #2 } { dynamic }
       {
          \__flowfram_set_dynamic_by_idn:nn { \l__flowfram_id_int } { #3 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ssetdynamicframe}
%Version 2.0 removed \cs{@ssetdynamicframe}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@setdynamicframe}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@setdynamicframe}.
%\end{macro}
%
%\begin{macro}{\@@setdynamicframe}
% Change the setting for the \gls{dynamic} given by its \gls{idn}.
% Version 2.0 renamed \cs{@@setdynamicframe}.
%\changes{1.11}{2008/06/27}{removed unwanted space}
%\changes{1.11}{2008/06/27}{fixed bug in clear key}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_dynamic_by_idn:nn
{
  \__flowfram_set_keys_for_type:nnn { #2 } { dynamic } { #1 }
%    \end{macrocode}
%Option specific to dynamic frames:
%    \begin{macrocode}
  \tl_if_empty:NF \l__flowfram_style_tl
   {
     \flowfram_frame_set_tl:nnnV
      { dynamic } { style } { #1 } \l__flowfram_style_tl
   }
  \tl_if_empty:NF \l__flowfram_clearflag_tl
   {
     \flowfram_frame_set_bool_from_option:nnnV
      { dynamic } { clear } { #1 }
     \l__flowfram_clearflag_tl
   }
  \tl_if_empty:NF \l__flowfram_hideflag_tl
   {
     \flowfram_frame_set_bool_from_option:nnnV
      { dynamic } { hide } { #1 }
     \l__flowfram_hideflag_tl
   }
  \tl_if_empty:NF \l__flowfram_hidethisflag_tl
   {
     \flowfram_frame_set_bool_from_option:nnnV
      { dynamic } { hidethis } { #1 }
     \l__flowfram_hidethisflag_tl
   }
  \exp_args:NV \tl_if_novalue:nF \l__flowfram_shape_tl
   {
     \flowfram_frame_set_tl:nnnV
      { dynamic } { shape } { #1 } \l__flowfram_shape_tl
   }
  \exp_args:NV \tl_if_novalue:nF \l__flowfram_parindent_tl
   {
     \flowfram_frame_set_tl:nnnV
      { dynamic } { parindent } { #1 } \l__flowfram_parindent_tl
   }
  \tl_if_empty:NF \l__flowfram_valign_tl
   {
     \flowfram_frame_set_tl:nnnV
        { dynamic } { valign } { #1 }
       \l__flowfram_valign_tl
   }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicsetpagelist}
% Sets the page list for the \gls{dynamic} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \dynamicsetpagelist { m m }
 {
  \flowfram_set_frame_pagelist:nne { dynamic } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicsetexclusion}
% Sets the exclusion list for the \gls{dynamic} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \dynamicsetexclusion { m m }
{
  \flowfram_set_frame_excludelist:nne { dynamic } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicaddexclusion}
% Adds to the exclusion list for the \gls{dynamic} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \dynamicaddexclusion { m m }
 {
  \flowfram_concat_frame_excludelist:nne
   { dynamic } { #1 } { #2 } 
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@@dynamicframeswapcoords}
% Swap odd and even offsets for a given \gls{dynamic}. Do the main stuff for 
% a given \gls{dynamic} \gls{idn}.
%Version 2.0 removed \cs{@@dynamicframeswapcoords}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\dfswapoddeven}
% Allow user to specify \gls{flow} either by \gls{idn} or \gls{idl}:
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \dfswapoddeven { s m }
{
   \IfValueTF { #1 }
    {
      \exp_args:Ne \clist_map_inline:nn { #2 }
       {
         \__flowfram_get_dynamic_id:n { ##1 }
         \__flowfram_dynamic_swap_coords:n { \l__flowfram_id_int }
       }
    }
    {
       \__flowfram_map_idns:enn { #2 } { dynamic }
        {
          \__flowfram_dynamic_swap_coords:n { \l__flowfram_id_int }
        }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sdynamicframeswapcoords}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@sdynamicframeswapcoords}.
%\end{macro}
%\begin{macro}{\@dynamicframeswapcoords}
% Version 2.0 renamed \cs{@dynamicframeswapcoords}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_swap_coords:n
{
  \flowfram_frame_swap_dim:nnnn
    { dynamic } { posx } { evenx } { #1 }
  \flowfram_frame_swap_dim:nnnn
    { dynamic } { posy } { eveny } { #1 }
}
%    \end{macrocode}
%\end{macro}
% Set the contents of a \gls{dynamic}.
%
%\begin{environment}{dynamiccontents}
% Syntax: "\begin{dynamiccontents}"\marg{idn}
% Set the contents of a dynamic frame with an environment that
% captures its body.
%\changes{2.0}{2025-11-24}{changed to document environment}
%    \begin{macrocode}
\NewDocumentEnvironment { dynamiccontents } { o m +b }
 {
   \IfValueT { #1 }
    {
      \__flowfram_set_dynamic_by_idn:nn { #2 } { #1 }
    }
   \setdynamiccontents { #2 } { #3 }
 }
 { }
%    \end{macrocode}
%\end{environment}
%
%\begin{environment}{dynamiccontents*}
% Starred version references the frame by its label.
%\changes{2.0}{2025-11-24}{changed to document environment}
%    \begin{macrocode}
\NewDocumentEnvironment { dynamiccontents* } { o m +b }
 {
   \__flowfram_get_dynamic_id:n { #2 }
   \IfValueT { #1 }
    {
      \__flowfram_set_dynamic_by_idn:nn
        { \l__flowfram_id_int } { #1 }
    }
   \setdynamiccontents 
        { \l__flowfram_id_int } { #3 }
 }
 { }
%    \end{macrocode}
%\end{environment}
%
%\begin{macro}{\@dynamictok}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@dynamictok}.
%\end{macro}
%\begin{macro}{\xdynamiccontents}
%Version 2.0 removed \cs{xdynamiccontents}.
%\end{macro}
%
%\begin{macro}{\@flf@get@body}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@flf@get@body}.
%\end{macro}
%\begin{macro}{\ifdfcontinued}
%Version 2.0 removed \cs{ifdfcontinued}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flf@checkcontinued}
%Version 2.0 removed \cs{@flf@checkcontinued}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@lempty}
%Version 2.0 removed \cs{@lempty}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\flf@getcontargs}
%Version 2.0 removed \cs{flf@getcontargs}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flf@getcontargs}
%Version 2.0 removed \cs{@flf@getcontargs}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@flf@find@end}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@flf@find@end}.
%\end{macro}
%
%\begin{macro}{\endxdynamiccontents}
%Version 2.0 removed \cs{endxdynamiccontents}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flf@endxdynamiccontents}
%Version 2.0 removed \cs{@flf@endxdynamiccontents}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\setdynamiccontents}
%    \begin{macrocode}
\NewDocumentCommand \setdynamiccontents { s o m +m }
 {
  \group_begin:
   \IfBooleanTF { #1 }
    {
      \__flowfram_get_dynamic_id:n { #3 }
      \IfValueT { #2 }
       {
         \__flowfram_set_dynamic_by_idn:nn
           { \l__flowfram_id_int } { #2 }
       }
      \RenewDocumentCommand \continueonframe { o m }
       {
         \__flowfram_dynamic_continue_idl:nn { ##1 } { ##2 }
       }
      \__flowfram_set_dynamic_contents_from_body:nn
       { \l__flowfram_id_int } { #4 }
    }
    {
      \IfValueT { #2 }
       {
         \__flowfram_set_dynamic_by_idn:nn { #3 } { #2 }
       }
      \RenewDocumentCommand \continueonframe { O{} m }
       {
         \__flowfram_dynamic_continue_idn:nn { ##1 } { ##2 }
       }
      \__flowfram_set_dynamic_contents_from_body:nn
       { #3 } { #4 }
    }
  \group_end:
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_continue_idn:nn
 {
   \IfValueTF { #1 }
    {
      \__flowfram_append_dynamic_contents_idn:nn
       { \l__flowfram_current_dynamic_int }
       { \ffcontinuedtextlayout { #1 } }
    }
    {
%    \end{macrocode}
%Expansion required variables may have different values when the
%frame contents are displayed.
%    \begin{macrocode}
      \exp_args:Nne
      \__flowfram_append_dynamic_contents_idn:nn
       { \l__flowfram_current_dynamic_int }
       {
         \exp_not:N \ffcontinuedtextlayout
          {
            \exp_not:N \flowfram_continue_on_dynamic_frame_idn:nn
              { \int_use:N \l__flowfram_current_dynamic_int }
              { \int_eval:n { #2 } }
          }
       }
    }
   \exp_args:NV
   \__flowfram_set_post_continued:nnn
      \l__flowfram_current_dynamic_int
      { \l__flowfram_current_dynamic_int }
      { \c_flowfram_frame_type_dynamic_int }
   \int_set:Nn \l__flowfram_current_dynamic_int { #2 }
   \exp_after:wN
   \__flowfram_set_dynamic_contents_from_body:w
      \l__flowfram_postcontinued_tl
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_continue_idl:nn
 {
   \IfValueTF { #1 }
    {
      \__flowfram_append_dynamic_contents_idn:nn
       { \l__flowfram_current_dynamic_int }
       { \ffcontinuedtextlayout { #1 } }
    }
    {
%    \end{macrocode}
%Expansion required variables may have different values when the
%frame contents are displayed.
%    \begin{macrocode}
      \exp_args:Nne
      \__flowfram_append_dynamic_contents_idn:nn
       { \l__flowfram_current_dynamic_int }
       {
         \exp_not:N \ffcontinuedtextlayout
          {
            \exp_not:N \flowfram_continue_on_dynamic_frame_idl:nn
              { \int_use:N \l__flowfram_current_dynamic_int }
              { #2 }
          }
       }
    }
   \exp_args:NV
   \__flowfram_set_post_continued:nnn
      \l__flowfram_current_dynamic_int
      { \l__flowfram_current_dynamic_int }
      { \c_flowfram_frame_type_dynamic_int }
   \__flowfram_get_dynamic_id:n { #2 }
   \int_set_eq:Nn
    \l__flowfram_current_dynamic_int 
    \l__flowfram_id_int
   \exp_after:wN
   \__flowfram_set_dynamic_contents_from_body:w
      \l__flowfram_postcontinued_tl
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_continue_on_dynamic_frame_idn:nn
 {
   \ffdefaultdynamiccontinuetext { #1 } { #2 }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_continue_on_dynamic_frame_idl:nn
 {
   \__flowfram_get_dynamic_id:n { #2 }
   \ffdefaultdynamiccontinuetext { #1 } {  \l__flowfram_id_int }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_dynamic_contents_from_body:nn
 {
   \int_set:Nn \l__flowfram_current_dynamic_int { #1 }
   \__flowfram_set_dynamic_contents_from_body:w 
    #2 \continueonframe \q_nil \q_stop
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Npn \__flowfram_set_dynamic_contents_from_body:w
   #1 \continueonframe #2 \q_stop
 {
   \__flowfram_set_dynamic_contents:nn
      { \l__flowfram_current_dynamic_int }
      { #1 }
   \tl_if_head_eq_meaning:nNTF { #2 } [
    {
      \__flowfram_dynamic_continued_opt_conts:wn #2 \q_stop
    }
    {
     \quark_if_nil:nF { #2 }
      {
         \__flowfram_dynamic_continued_conts:wn
         #2
        \q_stop
      }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Npn \__flowfram_dynamic_continued_opt_conts:wn
   [ #1 ] #2 #3 \q_stop
 {
   \continueonframe [ #1 ] { #2 }
   #3 \q_stop
 } 
\cs_new:Npn \__flowfram_dynamic_continued_conts:wn
   #1 #2 \q_stop
 {
   \continueonframe { #1 }
   #2 \q_stop
 } 
%    \end{macrocode}
%
%\begin{macro}{\@ssetdynamiccontents}
% Starred version: identify \gls{dynamic} by its \gls{idl}:
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ssetdynamiccontents}.
%\end{macro}
%
%\begin{macro}{\@setdynamiccontents}
% Set the contents of a dynamic frame identified by its \gls{idn}:
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed \cs{@setdynamiccontents}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_dynamic_contents:nn
 {
   \flowfram_frame_set_tl:nnnn
      { dynamic } { content } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\appenddynamiccontents}
% Append information to \gls{dynamic}. First check to
% see if starred or unstarred version is being used.
%\changes{2.0}{2025-11-24}{changed to document command}
%\changes{2.0}{2025-11-24}{added optional argument}
%    \begin{macrocode}
\NewDocumentCommand \appenddynamiccontents { s o m +m }
 {
  \IfBooleanTF { #1 }
   {
      \__flowfram_get_dynamic_id:n { #3 }
      \IfValueT { #2 }
       {
         \__flowfram_set_dynamic_by_idn:nn
           { \l__flowfram_id_int } { #2 }
       }
     \__flowfram_append_dynamic_contents_idn:nn { \l__flowfram_id_int } { #4 }
   }
   {
      \IfValueT { #2 }
       {
         \__flowfram_set_dynamic_by_idn:nn { #3 } { #2 }
       }
     \__flowfram_append_dynamic_contents_idn:nn { #3 } { #4 }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sappenddynamic}
% Append to dynamic frame identified by its \gls{idl}.
%Version 2.0 renamed \cs{@sappenddynamic}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_append_dynamic_contents_idl:nn
 {
   \__flowfram_get_dynamic_id:n { #1 }
   \__flowfram_append_dynamic_contents_idn:nn
     { \l__flowfram_id_int } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@appenddynamic}
% Append to dynamic frame identified by its \gls{idn}.
%Version 2.0 renamed \cs{@appenddynamic}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_append_dynamic_contents_idn:nn
 {
   \flowfram_frame_put_right_tl:nnnn
     { dynamic } { content } { #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flf@ta}
% Version 2.0 removed \cs{flf@ta}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\flf@tb}
% Version 2.0 removed \cs{flf@tb}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@ff@addtolist}
%\changes{2.0}{2025-11-24}{removed}
% Version 2.0 removed \cs{@ff@addtolist}.
%\end{macro}
%
%\subsection{Determining Dimensions and Locations}
%\begin{macro}{\computeleftedgeodd}
% Compute the position of the leftmost 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.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \computeleftedgeodd { m }
 {
   \dim_set:Nn #1 { -1in - \hoffset - \oddsidemargin }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computeleftedgeeven}
%\changes{2.0}{2025-11-24}{changed to document command}
% Now for the even pages
%    \begin{macrocode}
\NewDocumentCommand \computeleftedgeeven { m }
 {
   \dim_set:Nn #1 { -1in - \hoffset - \evensidemargin }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computetopedge}
%\changes{2.0}{2025-11-24}{changed to document command}
% Compute the top edge of the page, relative to the bottom of 
% the \gls{typeblock}.
%    \begin{macrocode}
\NewDocumentCommand \computetopedge { m }
 {
   \dim_set:Nn #1
    {
      \typeblockheight
    + \typeblockoffsety
    + 1in
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computebottomedge}
%\changes{2.0}{2025-11-24}{changed to document command}
% Compute the bottom edge of the page, relative to the bottom 
% of the \gls{typeblock}.
%    \begin{macrocode}
\NewDocumentCommand \computebottomedge { m }
 {
   \computetopedge { #1 }
   \addtolength { #1 } { - \paperheight }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computerightedgeodd}
%\changes{2.0}{2025-11-24}{changed to document command}
% 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}
\NewDocumentCommand \computerightedgeodd { m }
 {
   \computeleftedgeodd { #1 }
   \addtolength { #1 } { \paperwidth }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\computerightedgeeven}
%\changes{2.0}{2025-11-24}{changed to document command}
% Now for the even pages.
%    \begin{macrocode}
\NewDocumentCommand \computerightedgeeven { m }
 {
   \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}
%\changes{2.0}{2025-11-24}{changed to document command}
% Starred version identifies frame by \gls{idl}, unstarred
% version identifies frame by \gls{idn}.
%    \begin{macrocode}
\NewDocumentCommand \computeflowframearea { s m }
{
  \setlength \ffareax { \paperwidth }
  \setlength \ffareay { \paperheight }
  \dim_zero:N \l__flowfram_x_dim
  \dim_zero:N \l__flowfram_y_dim
  \IfBooleanTF { #1 }
   {
      \exp_args:Ne \clist_map_inline:nn { #1 }
       {
         \__flowfram_if_flow_label_exists:nTF { ##1 }
          {
            \__flowfram_compute_flow_area_by_idn:n { \l__flowfram_id_int } 
          }
          {
            \__flowfram_error:eee { label-undefined } { ##1 } { flow }
          }
       }
   }
   {
      \__flowfram_map_idns:enn { #2 } { flow }
       {
          \__flowfram_compute_flow_area_by_idn:n { \l__flowfram_id_int } 
       }
   }
  \dim_set:Nn \ffareawidth
   {
     \l__flowfram_x_dim -\ffareax
   }
  \dim_set:Nn \ffareaheight
   {
     \l__flowfram_y_dim - \ffareay
   }
}
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_compute_flow_area_by_idn:n
 {
   \dim_compare:nNnT
      { \ffareax } > { \flowframex { #1 } } 
    {
      \dim_set:Nn \ffareax { \flowframex { #1 } }
    }
   \dim_compare:nNnT
      { \ffareay } > { \flowframey { #1 } }
    {
      \dim_set:Nn \ffareay { \flowframey { #1 } }
    }
   \dim_set:Nn \l__flowfram_offset_dim
     {
       \flowframex { #1 }
       + \flowframewidth { #1 }
     }
   \dim_compare:nNnT
      { \l__flowfram_x_dim } < { \l__flowfram_offset_dim }
     {
      \dim_set_eq:NN \l__flowfram_x_dim \l__flowfram_offset_dim 
     }
   \dim_set:Nn \l__flowfram_offset_dim
     {
       \flowframey { #1 }
       + \flowframeheight { #1 }
     }
   \dim_compare:nNnT
      { \l__flowfram_y_dim } < { \l__flowfram_offset_dim }
     {
       \dim_set_eq:NN \l__flowfram_y_dim \l__flowfram_offset_dim
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@scomputeffarea}
% Version 2.0 removed \cs{@scomputeffarea}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@computeffarea}
% Version 2.0 removed \cs{@computeffarea}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@ff@swaplen}
% Swap the values of two dimensions.
% Version 2.0 renamed \cs{@ff@swaplen}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_swap_dim:NN
 {
   \dim_set_eq:NN \l__flowfram_tmpa_dim #1
   \dim_set_eq:NN #1 #2
   \dim_set_eq:NN #2 \l__flowfram_tmpa_dim
 }
%    \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".
% Version 2.0 renamed \cs{@ff@getdim}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_frame_bounds_by_typeid:nn
 {
   \int_case:nnF { #1 }
    {
      { \c_flowfram_frame_type_flow_int }
       {
         \__flowfram_get_flow_bounds:n { #2 }
       }
      { \c_flowfram_frame_type_static_int }
       {
         \__flowfram_get_static_bounds:n { #2 }
       }
      { \c_flowfram_frame_type_dynamic_int }
       {
         \__flowfram_get_dynamic_bounds:n { #2 }
       }
    }
    {
       \msg_error:nne { flowfram } { invalid-frame-typeid }
         { \int_eval:n { #1 } }
    }
 }
%    \end{macrocode}
%\end{macro}
%Identify by type label.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_frame_bounds_by_type:nn
 {
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareax { #1 } { posx } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareay { #1 } { posy } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareaevenx { #1 } { evenx } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareaeveny { #1 } { eveny } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareawidth { #1 } { width } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareaheight { #1 } { height } { #2 }
 }
%    \end{macrocode}
%
%\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}
\cs_new:Nn \__flowfram_get_frame_even_bounds_by_typeid:nn
 {
   \int_case:nnF { #1 }
    {
      { \c_flowfram_frame_type_flow_int }
       {
         \__flowfram_get_flow_even_bounds:n { #2 }
       }
      { \c_flowfram_frame_type_static_int }
       {
         \__flowfram_get_static_even_bounds:n { #2 }
       }
      { \c_flowfram_frame_type_dynamic_int }
       {
         \__flowfram_get_dynamic_even_bounds:n { #2 }
       }
    }
    {
       \msg_error:nne { flowfram } { invalid-frame-typeid }
         { \int_eval:n { #1 } }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_frame_even_bounds_by_type:nn
 {
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareax { #1 } { evenx } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareay { #1 } { eveny } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareawidth { #1 } { width } { #2 }
  \flowfram_set_dim_to_frame_dim:Nnnn
    \ffareaheight { #1 } { height } { #2 }
 }
%    \end{macrocode}
%
%\begin{macro}{\getstaticbounds}
% Convenience method for calling the above. Firstly for static
% frames:
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \getstaticbounds { s m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_get_static_id:n { #2 }
      \__flowfram_get_static_bounds:n { \l__flowfram_id_int }
    }
    {
      \__flowfram_get_static_bounds:n { #2 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetstaticbounds}
% Version 2.0 removed \cs{@sgetstaticbounds}.
%\changes{2.0}{2025-11-24}{removed}
%\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)}
%Version 2.0 renamed \cs{@getstaticbounds}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_static_bounds:n
 {
   \__flowfram_get_frame_bounds_by_type:nn { static } { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getstaticevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Even pages.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \getstaticevenbounds { s m }
 {
  \IfBooleanTF { #1 }
    {
      \__flowfram_get_static_id:n { #2 }
      \__flowfram_get_static_even_bounds:n { \l__flowfram_id_int }
    } 
    {
      \__flowfram_get_static_even_bounds:n { #2 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetstaticevenbounds}
% Version 2.0 removed \cs{@sgetstaticevenbounds}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@getstaticevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Get static bounds by \gls{idn}.
% Version 2.0 renamed \cs{@getstaticevenbounds}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_static_even_bounds:n
 {
   \__flowfram_get_frame_even_bounds_by_type:nn { static } { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getflowbounds}
% Next flow frames:
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \getflowbounds { s m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_get_flow_id:e { #2 }
      \__flowfram_get_flow_bounds:n { \l__flowfram_id_int }
    }
    {
      \__flowfram_get_flow_bounds:n { #2 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetflowbounds}
%Version 2.0 removed \cs{@sgetflowbounds}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@getflowbounds}
% Get flow bounds by \gls{idn}).
% Version 2.0 renamed \cs{@getflowbounds}.
%\changes{1.11}{2008/06/27}{fixed bug: changed frame id from
% 2 to 1 (thanks to Lutz Goldmann for pointing it out)}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_flow_bounds:n
 {
   \__flowfram_get_frame_bounds_by_type:nn { flow } { #1 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\getflowevenbounds}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Even pages:
%    \begin{macrocode}
\NewDocumentCommand \getflowevenbounds { s m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_get_flow_id:e { #1 }
      \__flowfram_get_flow_even_bounds:n { \l__flowfram_id_int }
    }
    {
      \__flowfram_get_flow_even_bounds:n { #2 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetflowevenbounds}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@sgetflowevenbounds}.
%\end{macro}
%\begin{macro}{\@getflowevenbounds}
%\changes{1.11}{2008/06/27}{new}
% Get bounds by \gls{idn}.
%Version 2.0 renamed \cs{@getflowevenbounds}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_flow_even_bounds:n
 {
   \__flowfram_get_frame_even_bounds_by_type:nn { flow } { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getdynamicbounds}
%\changes{2.0}{2025-11-24}{changed to document command}
% Next dynamic frames:
%    \begin{macrocode}
\NewDocumentCommand \getdynamicbounds { s m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_get_dynamic_id:n { #1 }
      \__flowfram_get_dynamic_bounds:n { \l__flowfram_id_int }
    }
    {
      \__flowfram_get_dynamic_bounds:n { #2 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetdynamicbounds}
%Version 2.0 removed \cs{@sgetdynamicbounds}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@getdynamicbounds}
% Get bounds by \gls{idn}):
%Version 2.0 renamed \cs{@getdynamicbounds}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_dynamic_bounds:n
 {
   \__flowfram_get_frame_bounds_by_type:nn { dynamic } { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\getdynamicevenbounds}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Even pages:
%    \begin{macrocode}
\NewDocumentCommand \getdynamicevenbounds { s m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_get_dynamic_id:n { #1 }
      \__flowfram_get_dynamic_even_bounds:n { \l__flowfram_id_int }
    }
    {
      \__flowfram_get_dynamic_even_bounds:n { #2 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sgetdynamicevenbounds}
%Version 2.0 removed \cs{@sgetdynamicevenbounds}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@getdynamicevenbounds}
% Get bounds by \gls{idn}).
% Version 2.0 renamed \cs{@getdynamicevenbounds}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_dynamic_even_bounds:n
 {
   \__flowfram_get_frame_even_bounds_by_type:nn { dynamic } { #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.
%
%\begin{macro}{\checkifframeabove}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \checkifframeabove { s m m m m }
{
  \IfBooleanTF { #1 }
   {
     \__flowframe_check_if_frame_above_by_idl:nnnn
       { #2 } { #3 } { #4 } { #5 }
   }
   {
     \__flowframe_check_if_frame_above_by_idn:nnnn
       { #2 } { #3 } { #4 } { #5 }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@scheckifframeabove}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@scheckifframeabove}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_above_by_idl:nnnn
 {
  \int_if_odd:nTF { \c@page }
   {
     \__flowframe_check_odd_if_frame_above_by_idl:nnnn
       { #1 } { #2 } { #3 } { #4 }
   }
   {
     \__flowframe_check_even_if_frame_above_by_idl:nnnn
       { #1 } { #2 } { #3 } { #4 }
   }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@checkifframeabove}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@checkifframeabove}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_above_by_idn:nnnn
 {
   \__flowframe_check_if_frame_above_by_idn:nnnnn
     { \c@page } { #1 } { #2 } { #3 } { #4 }
 }
%    \end{macrocode}
%\end{macro}
%Supply page number in first argument:
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_above_by_idn:nnnnn
 {
   \int_if_odd:nTF { #1 }
    {
      \__flowframe_check_odd_if_frame_above_by_idn:nnnn
         { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_even_if_frame_above_by_idn:nnnn
         { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%
%\begin{macro}{\oddcheckifframeabove}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \oddcheckifframeabove { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_odd_if_frame_above_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_odd_if_frame_above_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@soddcheckifframeabove}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@soddcheckifframeabove}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_above_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareay { \ffareaheight } 
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } > { \ffareay }
    {
     \FLFabovetrue
    }
    {
     \FLFabovefalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@oddcheckifframeabove}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@oddcheckifframeabove}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_above_by_idn:nnnn
 {
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { #2 }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { #4 }
   \dim_add:Nn \ffareay { \ffareaheight } 
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } > { \ffareay }
    {
     \FLFabovetrue
    }
    {
     \FLFabovefalse
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\checkifframebelow}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \checkifframebelow { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_if_frame_below_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_if_frame_below_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@scheckifframebelow}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@scheckifframebelow}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_below_by_idl:nnnn
 {
   \int_if_odd { \c@page }
    {
       \__flowframe_check_odd_if_frame_below_by_idl:nnnn
        { #1 } { #2 } { #3 } { #4 }
    }
    {
       \__flowframe_check_even_if_frame_below_by_idl:nnnn
        { #1 } { #2 } { #3 } { #4 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@checkifframebelow}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@checkifframebelow}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_below_by_idn:nnnn
 {
   \__flowframe_check_if_frame_below_by_idn:nnnnn
     { \c@page } { #1 } { #2 } { #3 } { #4 }
 }
\cs_new:Nn \__flowframe_check_if_frame_below_by_idn:nnnnn
 {
   \int_if_odd:nTF { #1 }
    {
      \__flowframe_check_odd_if_frame_below_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
       \__flowframe_check_even_if_frame_below_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\oddcheckifframebelow}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \oddcheckifframebelow { s m m m m }
{
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_odd_if_frame_below_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_odd_if_frame_below_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@soddcheckifframebelow}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@soddcheckifframebelow}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_below_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareay { \ffareaheight }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim} < { \ffareay }
    {
      \FLFbelowtrue
    }
    {
      \FLFbelowfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@oddcheckifframebelow}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@oddcheckifframebelow}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_below_by_idn:nnnn
 {
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { #2 }
   \dim_add:Nn \ffareay { \ffareaheight }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { #4 }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } < { \ffareay }
    {
      \FLFbelowtrue
    }
    {
      \FLFbelowfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\checkifframeleft}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \checkifframeleft { s m m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_if_frame_left_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_if_frame_left_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@scheckifframeleft}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@scheckifframeleft}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_left_by_idl:nnnn
 {
  \int_if_odd:nTF { \c@page }
   {
     \__flowframe_check_odd_if_frame_left_by_idl:nnnn
       { #1 } { #2 } { #3 } { #4 }
   }
   {
     \__flowframe_check_even_if_frame_left_by_idl:nnnn
       { #1 } { #2 } { #3 } { #4 }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@checkifframeleft}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idn}.
%Version 2.0 renamed \cs{@checkifframeleft}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_left_by_idn:nnnn
 {
   \__flowframe_check_if_frame_left_by_idn:nnnnn
    { \c@page } { #1 } { #2 } { #3 } { #4 }
 }
\cs_new:Nn \__flowframe_check_if_frame_left_by_idn:nnnnn
 {
   \int_if_odd:nTF { #1 }
    {
      \__flowframe_check_odd_if_frame_left_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_even_if_frame_left_by_idn:nnnn
         { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \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.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \oddcheckifframeleft { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_odd_if_frame_left_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_odd_if_frame_left_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@soddcheckifframeleft}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{@soddcheckifframeleft}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_left_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } < { \ffareax }
    {
      \FLFlefttrue
    }
    {
      \FLFleftfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@oddcheckifframeleft}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@oddcheckifframeleft}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_left_by_idn:nnnn
 {
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { #2 }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { #4 }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } < { \ffareax }
    {
      \FLFlefttrue
    }
    {
      \FLFleftfalse
    }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\checkifframeright}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \checkifframeright { s m m m m }
 {
  \IfBooleanTF { #1 }
   {
     \__flowframe_check_if_frame_right_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
   }
   {
     \__flowframe_check_if_frame_right_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@scheckifframeright}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
%Version 2.0 renamed \cs{@scheckifframeright}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_right_by_idl:nnnn
 {
   \int_if_odd:nTF { \c@page }
    {
      \__flowframe_check_odd_if_frame_right_by_idl:nnnn
       { #1 } { #2 } { #3 } { #4 }
    }
    {
      \__flowframe_check_even_if_frame_right_by_idl:nnnn
       { #1 } { #2 } { #3 } { #4 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@checkifframeright}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idn}.
%Version 2.0 renamed \cs{@checkifframeright}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_if_frame_right_by_idn:nnnn
 {
   \__flowframe_check_if_frame_right_by_idn:nnnnn
    { \c@page } { #1 } { #2 } { #3 } { #4 }
 }
\cs_new:Nn \__flowframe_check_if_frame_right_by_idn:nnnnn
 {
   \int_if_odd:nTF { #1 }
    {
      \__flowframe_check_odd_if_frame_right_by_idn:nnnn
       { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_even_if_frame_right_by_idn:nnnn
       { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\oddcheckifframeright}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \oddcheckifframeright { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_odd_if_frame_right_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_odd_if_frame_right_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@soddcheckifframeright}
% Check by \gls{idl}.
% Version 2.0 renamed \cs{}@soddcheckifframeright.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_right_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } > { \ffareax }
    {
      \FLFrighttrue
    }
    {
      \FLFrightfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@oddcheckifframeright}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@oddcheckifframeright}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_odd_if_frame_right_by_idn:nnnn
 {
   \__flowfram_get_frame_bounds_by_type:nn { #1 } { #2 }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_bounds_by_type:nn { #3 } { #4 }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } > { \ffareax }
    {
      \FLFrighttrue
    }
    {
      \FLFrightfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframeabove}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \evencheckifframeabove { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_even_if_frame_above_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_even_if_frame_above_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sevencheckifframeabove}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
%Version 2.0 renamed \cs{@sevencheckifframeabove}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_above_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareay { \ffareaheight }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } > { \ffareay }
    {
      \FLFabovetrue
    }
    {
      \FLFabovefalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@evencheckifframeabove}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@evencheckifframeabove}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_above_by_idn:nnnn
 {
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { #2 }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { #4 }
   \dim_add:Nn \ffareay { \ffareaheight }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } > { \ffareay }
    {
      \FLFabovetrue
    }
    {
      \FLFabovefalse
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframebelow}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \evencheckifframebelow { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_even_if_frame_below_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_even_if_frame_below_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sevencheckifframebelow}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
%Version 2.0 renamed \cs{@sevencheckifframebelow}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_below_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareay { \ffareaheight }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } < { \ffareay }
    {
      \FLFbelowtrue
    }
    {
      \FLFbelowfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@evencheckifframebelow}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@evencheckifframebelow}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_below_by_idn:nnnn
 {
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { #2 }
   \dim_add:Nn \ffareay { \ffareaheight }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareay
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { #4 }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } < { \ffareay }
    {
      \FLFbelowtrue
    }
    {
      \FLFbelowfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframeleft}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \evencheckifframeleft { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_even_if_frame_left_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_even_if_frame_left_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sevencheckifframeleft}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
%Version 2.0 renamed \cs{@sevencheckifframeleft}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_left_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } < { \ffareax }
    {
      \FLFlefttrue
    }
    {
      \FLFleftfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@evencheckifframeleft}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@evencheckifframeleft}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_left_by_idn:nnnn
 {
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { #2 }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { #4 }
   \dim_compare:nNnTF { \l__flowfram_tmpa_dim } < { \ffareax }
    {
      \FLFlefttrue
    }
    {
      \FLFleftfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\evencheckifframeright}
%\changes{1.11}{2008/06/27}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
%\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}
\NewDocumentCommand \evencheckifframeright { s m m m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowframe_check_even_if_frame_right_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowframe_check_even_if_frame_right_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sevencheckifframeright}
%\changes{2.0}{2025-11-24}{renamed}
% Check by \gls{idl}.
%Version 2.0 renamed \cs{@sevencheckifframeright}.
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_right_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { \l__flowfram_id_int }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { \l__flowfram_id_int }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_compare:nNnTF {\l__flowfram_tmpa_dim } > { \ffareax }
    {
      \FLFrighttrue
    }
    {
      \FLFrightfalse
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@evencheckifframeright}
% Check by \gls{idn}.
% Version 2.0 renamed \cs{@evencheckifframeright}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_check_even_if_frame_right_by_idn:nnnn
 {
   \__flowfram_get_frame_even_bounds_by_type:nn { #1 } { #2 }
   \dim_set_eq:NN \l__flowfram_tmpa_dim \ffareax
   \__flowfram_get_frame_even_bounds_by_type:nn { #3 } { #4 }
   \dim_add:Nn \ffareax { \ffareawidth }
   \dim_compare:nNnTF {\l__flowfram_tmpa_dim } > { \ffareax }
    {
      \FLFrighttrue
    }
    {
      \FLFrightfalse
    }
 }
%    \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}
%\changes{2.0}{2025-11-24}{changed to document command}
%\begin{definition}
%\cs{relativeframelocation}\marg{type1}\marg{id1}\marg{type2}\marg{id2}
%\end{definition}
% 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}
\NewDocumentCommand \relativeframelocation { s m m m m }
 {
  \IfBooleanTF { #1 }
    {
      \__flowfram_relative_frame_location_by_idl:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
    {
      \__flowfram_relative_frame_location_by_idn:nnnn
        { #2 } { #3 } { #4 } { #5 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@srelativeframelocation}
%\changes{2.0}{2025-11-24}{renamed}
%Check by \gls{idl}.
%Version 2.0 renamed \cs{@srelativeframelocation}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_relative_frame_location_by_idl:nnnn
 {
   \__flowfram_get_frame_id:nn { #1 } { #2 }
   \int_set_eq:NN \l__flowfram_tmpa_int \l__flowfram_id_int
   \__flowfram_get_frame_id:nn { #3 } { #4 }
   \int_set_eq:NN \l__flowfram_tmpb_int \l__flowfram_id_int
   \__flowfram_relative_frame_location_by_idn:nVnV
     { #1 } \l__flowfram_tmpa_int 
     { #3 } \l__flowfram_tmpb_int 
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@relativeframelocation}
%\changes{2.0}{2025-11-24}{renamed}
%Check by \gls{idn}.
%Version 2.0 renamed \cs{@relativeframelocation}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_relative_frame_location_by_idn:nnnn
 {
   \__flowfram_relative_frame_location_by_idn:nnnnn
     { \c@page } { #1 } { #2 } { #3 } { #4 }
 }
\cs_generate_variant:Nn \__flowfram_relative_frame_location_by_idn:nnnn
  { nVnV }
%    \end{macrocode}
%\end{macro}
%For a specific page:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_relative_frame_location_by_idn:nnnnn
 {
  \__flowframe_check_if_frame_above_by_idn:nnnnn
    { #1 } { #2 } { #3 } { #4 } { #5 }
  \__flowframe_check_if_frame_below_by_idn:nnnnn
    { #1 } { #2 } { #3 } { #4 } { #5 }
  \__flowframe_check_if_frame_left_by_idn:nnnnn
    { #1 } { #2 } { #3 } { #4 } { #5 }
  \__flowframe_check_if_frame_right_by_idn:nnnnn
    { #1 } { #2 } { #3 } { #4 } { #5 }
  \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}
%
%\begin{macro}{\SaveRelativeFrameLocation}
%\begin{definition}
%\cs{SaveRelativeFrameLocation}\marg{label}\marg{type1}\marg{ID1}\marg{type2}\marg{ID2}
%\end{definition}
%\changes{2.0}{2025-11-24}{new}
%Save in aux file for next run.
%    \begin{macrocode}
\NewDocumentCommand \SaveRelativeFrameLocation { s m m m m m }
 {
  \IfBooleanTF { #1 }
    {
      \__flowfram_get_frame_id:nn { #3 } { #4 }
      \int_set_eq:NN \l__flowfram_tmpa_int \l__flowfram_id_int
      \__flowfram_get_frame_id:nn { #5 } { #6 }
      \int_set_eq:NN \l__flowfram_tmpb_int \l__flowfram_id_int
    }
    {
      \int_set:Nn \l__flowfram_tmpa_int { #4 }
      \int_set:Nn \l__flowfram_tmpb_int { #6 }
    }
%    \end{macrocode}
%Obtain the dimensions of the first frame:
%    \begin{macrocode}
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_x_dim
      { #3 } { posx } { \l__flowfram_tmpa_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_evenx_dim
      { #3 } { evenx } { \l__flowfram_tmpa_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_y_dim
      { #3 } { posy } { \l__flowfram_tmpa_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_eveny_dim
      { #3 } { eveny } { \l__flowfram_tmpa_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_width_dim
      { #3 } { width } { \l__flowfram_tmpa_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_height_dim
      { #3 } { height } { \l__flowfram_tmpa_int }
%    \end{macrocode}
%Store the first frame values:
%    \begin{macrocode}
   \tl_set:Ne \l__flowfram_x_tl
      { \dim_use:N \l__flowfram_x_dim }
   \tl_set:Ne \l__flowfram_y_tl
      { \dim_use:N \l__flowfram_y_dim }
   \tl_set:Ne \l__flowfram_evenx_tl
      { \dim_use:N \l__flowfram_evenx_dim }
   \tl_set:Ne \l__flowfram_eveny_tl
      { \dim_use:N \l__flowfram_eveny_dim }
   \tl_set:Ne \l__flowfram_width_tl
      { \dim_use:N \l__flowfram_width_dim }
   \tl_set:Ne \l__flowfram_height_tl
      { \dim_use:N \l__flowfram_height_dim }
%    \end{macrocode}
%Obtain the dimensions of the first frame:
%    \begin{macrocode}
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_x_dim
      { #5 } { posx } { \l__flowfram_tmpb_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_evenx_dim
      { #5 } { evenx } { \l__flowfram_tmpb_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_y_dim
      { #5 } { posy } { \l__flowfram_tmpb_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_eveny_dim
      { #5 } { eveny } { \l__flowfram_tmpb_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_width_dim
      { #5 } { width } { \l__flowfram_tmpb_int }
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_height_dim
      { #5 } { height } { \l__flowfram_tmpb_int }
%    \end{macrocode}
%Write the information to the aux file (the actual page value is
%required not \cs{thepage}):
%    \begin{macrocode}
   \protected@write \@auxout
    { \let \flowfram@thepagenumber \relax }
    {
      \string \@flowfram@saverelativeloc
       { #2 }
       { \flowfram@thepagenumber } 
       {
          { \l__flowfram_x_tl }
          { \l__flowfram_y_tl }
          { \l__flowfram_evenx_tl }
          { \l__flowfram_eveny_tl }
          { \l__flowfram_width_tl }
          { \l__flowfram_height_tl }
       }
       {
          { \dim_use:N \l__flowfram_x_dim }
          { \dim_use:N \l__flowfram_y_dim }
          { \dim_use:N \l__flowfram_evenx_dim }
          { \dim_use:N \l__flowfram_eveny_dim }
          { \dim_use:N \l__flowfram_width_dim }
          { \dim_use:N \l__flowfram_height_dim }
       }
    }
   \tl_if_exist:cF { g__flowfram_saved_rel_loc_ #2 _tl }
    {
      \@flowframe@warn@rerun
    }
 }
%    \end{macrocode}
%\end{macro}
%Extract the dimension arguments:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_fetch_odd_dimensions:nnnnnn
 {
   \dim_set:Nn \l__flowfram_x_dim { #1 }
   \dim_set:Nn \l__flowfram_y_dim { #2 }
   \dim_set:Nn \l__flowfram_width_dim { #5 }
   \dim_set:Nn \l__flowfram_height_dim { #6 }
 }
\cs_new:Nn \__flowfram_fetch_even_dimensions:nnnnnn
 {
   \dim_set:Nn \l__flowfram_x_dim { #3 }
   \dim_set:Nn \l__flowfram_y_dim { #4 }
   \dim_set:Nn \l__flowfram_width_dim { #5 }
   \dim_set:Nn \l__flowfram_height_dim { #6 }
 }
%    \end{macrocode}
%\begin{macro}{\@flowfram@saverelativeloc}
%\changes{2.0}{2025-11-24}{new}
%\begin{definition}
%\cs{@flowfram@saverelativeloc}\marg{label}\marg{page}\marg{frame 1
%dimensions}\marg{frame 2 dimensions}
%\end{definition}
%    \begin{macrocode}
\newcommand\@flowfram@saverelativeloc [ 4 ]
 {
   \tl_if_exist:cTF { g__flowfram_saved_rel_loc_ #1 _tl }
    {
      \msg_warning:nnn { flowfram } { relloc-label-already-defined }
         { #1 }
    }
    {
      \tl_const:cn { c__flowfram_saved_data_rel_loc_ #1 _tl }
        { { #2 } { #3 } { #4 } }
      \tl_new:c { g__flowfram_saved_rel_loc_ #1 _tl }
      \int_if_odd:nTF { #2 }
       {
         \__flowfram_fetch_odd_dimensions:nnnnnn #3
       }
       {
         \__flowfram_fetch_even_dimensions:nnnnnn #3
       }
      \dim_set_eq:NN \ffareax \l__flowfram_x_dim
      \dim_set_eq:NN \ffareay \l__flowfram_y_dim
      \dim_set_eq:NN \ffareawidth \l__flowfram_width_dim
      \dim_set_eq:NN \ffareaheight \l__flowfram_height_dim
      \int_if_odd:nTF { #2 }
       {
         \__flowfram_fetch_odd_dimensions:nnnnnn #4
       }
       {
         \__flowfram_fetch_even_dimensions:nnnnnn #4
       }
      \FLFabovefalse
      \FLFbelowfalse
      \FLFleftfalse
      \FLFrightfalse
      \dim_compare:nNnTF 
         { \ffareax } > { \l__flowfram_x_dim + \l__flowfram_width_dim }
       {
         \FLFrighttrue
       }
       {
         \dim_compare:nNnT
            { \ffareax + \ffareawidth } < { \l__flowfram_x_dim }
          {
            \FLFlefttrue
          }
       }
      \dim_compare:nNnTF 
         { \ffareay } > { \l__flowfram_y_dim + \l__flowfram_height_dim }
       {
         \FLFabovetrue
       }
       {
         \dim_compare:nNnT
            { \ffareay + \ffareaheight } < { \l__flowfram_y_dim }
          {
            \FLFbelowtrue
          }
       }
      \ifFLFabove
        \ifFLFleft
          \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
           { \FFaboveleft }
        \else
          \ifFLFright
             \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
             { \FFaboveright }
          \else
             \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
              { \FFabove }
          \fi
        \fi 
      \else
        \ifFLFbelow
          \ifFLFleft
            \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
             { \FFbelowleft }
          \else
            \ifFLFright
              \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
               { \FFbelowright }
            \else
               \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
                 { \FFbelow }
            \fi
          \fi 
        \else
          \ifFLFleft
            \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
             { \FFleft }
          \else
            \ifFLFright
              \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
                { \FFright }
            \else
              \tl_gset:cn { g__flowfram_saved_rel_loc_ #1 _tl }
                { \FFoverlap }
            \fi
          \fi 
        \fi
      \fi
      \bool_new:c { g__flowfram_saved_rel_loc_ #1 _above_bool }
      \bool_new:c { g__flowfram_saved_rel_loc_ #1 _below_bool }
      \bool_new:c { g__flowfram_saved_rel_loc_ #1 _left_bool }
      \bool_new:c { g__flowfram_saved_rel_loc_ #1 _right_bool }
      \ifFLFabove
        \bool_gset_true:c { g__flowfram_saved_rel_loc_ #1 _above_bool }
      \fi
      \ifFLFbelow
        \bool_gset_true:c { g__flowfram_saved_rel_loc_ #1 _below_bool }
      \fi
      \ifFLFleft
        \bool_gset_true:c { g__flowfram_saved_rel_loc_ #1 _left_bool }
      \fi
      \ifFLFright
        \bool_gset_true:c { g__flowfram_saved_rel_loc_ #1 _right_bool }
      \fi
    }
 }
\AddToHook { begindocument / end }
 {
   \cs_gset_eq:NN \@flowfram@saverelativeloc \@flowfram@checkrelativeloc
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowfram@checkrelativeloc}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand\@flowfram@checkrelativeloc [ 4 ]
 {
   \tl_if_exist:cT { c__flowfram_saved_data_rel_loc_ #1 _tl }
    {
      \tl_if_eq:cnF { c__flowfram_saved_data_rel_loc_ #1 _tl }
        { { #2 } { #3 } { #4 } }
       {
         \@flowframe@warn@rerun
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowframe@warn@rerun}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \@flowframe@warn@rerun
 {
   \AtEndDocument
    {
       \msg_warning:nn { flowfram} { data-changed-rerun }
    }
   \global \let \@flowframe@warn@rerun \relax
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\RefSavedRelativeLocation}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\NewDocumentCommand \RefSavedRelativeLocation { m }
 {
   \tl_if_exist:cTF { g__flowfram_saved_rel_loc_ #1 _tl }
    {
      \tl_use:c { g__flowfram_saved_rel_loc_ #1 _tl }
    }
    {
      ??
      \msg_warning:nnn { flowfram } { relloc-label-not-defined }
         { #1 }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\IfSavedRelativeLocationEq}
%\changes{2.0}{2025-11-24}{new}
%\begin{definition}
%\cs{IfSavedRelativeLocationEq}\marg{label}\marg{value}\marg{true}\marg{false}
%\end{definition}
%    \begin{macrocode}
\NewDocumentCommand \IfSavedRelativeLocationEq { m m m m }
 {
   \tl_if_exist:cTF { g__flowfram_saved_rel_loc_ #1 _tl }
    {
      \tl_if_eq:cnTF { g__flowfram_saved_rel_loc_ #1 _tl } { #2 }
       { #3 } { #4 }
    }
    { #4 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\IfSavedRelativeLocationAbove}
%\changes{2.0}{2025-11-24}{new}
%\begin{definition}
%\cs{IfSavedRelativeLocationAbove}\marg{label}\marg{true}\marg{false}
%\end{definition}
%    \begin{macrocode}
\newcommand \IfSavedRelativeLocationAbove [ 3 ]
 {
   \bool_if_exist:cTF { g__flowfram_saved_rel_loc_ #1 _above_bool }
    {
      \bool_if:cTF { g__flowfram_saved_rel_loc_ #1 _above_bool }
       { #2 } { #3 }
    }
    { #3 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\IfSavedRelativeLocationBelow}
%\changes{2.0}{2025-11-24}{new}
%\begin{definition}
%\cs{IfSavedRelativeLocationBelow}\marg{label}\marg{true}\marg{false}
%\end{definition}
%    \begin{macrocode}
\newcommand \IfSavedRelativeLocationBelow [ 3 ]
 {
   \bool_if_exist:cTF { g__flowfram_saved_rel_loc_ #1 _below_bool }
    {
      \bool_if:cTF { g__flowfram_saved_rel_loc_ #1 _below_bool }
       { #2 } { #3 }
    }
    { #3 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\IfSavedRelativeLocationLeft}
%\changes{2.0}{2025-11-24}{new}
%\begin{definition}
%\cs{IfSavedRelativeLocationLeft}\marg{label}\marg{true}\marg{false}
%\end{definition}
%    \begin{macrocode}
\newcommand \IfSavedRelativeLocationLeft [ 3 ]
 {
   \bool_if_exist:cTF { g__flowfram_saved_rel_loc_ #1 _left_bool }
    {
      \bool_if:cTF { g__flowfram_saved_rel_loc_ #1 _left_bool }
       { #2 } { #3 }
    }
    { #3 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\IfSavedRelativeLocationRight}
%\changes{2.0}{2025-11-24}{new}
%\begin{definition}
%\cs{IfSavedRelativeLocationRight}\marg{label}\marg{true}\marg{false}
%\end{definition}
%    \begin{macrocode}
\newcommand \IfSavedRelativeLocationRight [ 3 ]
 {
   \bool_if_exist:cTF { g__flowfram_saved_rel_loc_ #1 _right_bool }
    {
      \bool_if:cTF { g__flowfram_saved_rel_loc_ #1 _right_bool }
       { #2 } { #3 }
    }
    { #3 }
 }
%    \end{macrocode}
%\end{macro}
%
% Short cut commands for \glspl{frame} of the same type.
%\begin{macro}{\reldynamicloc}
%\changes{1.11}{2008/06/27}{new}
%\changes{1.14}{2012-11-10}{removed unwanted spaces}
%\changes{2.0}{2025-11-24}{changed to document command}
%\cs{reldynamicloc}\marg{id1}\marg{id2}
%    \begin{macrocode}
\NewDocumentCommand \reldynamicloc { s m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_relative_frame_location_by_idl:nnnn
        { dynamic } { #2 } { dynamic } { #3 }
    }
    {
      \__flowfram_relative_frame_location_by_idn:nnnn
        { dynamic } { #2 } { dynamic } { #3 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sreldynamicloc}
%Version 2.0 removed \cs{@sreldynamicloc}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@reldynamicloc}
%Version 2.0 removed \cs{@reldynamicloc}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\relstaticloc}
%\changes{1.11}{2008/06/27}{new}
%\changes{1.14}{2012-11-10}{removed unwanted spaces}
%\changes{2.0}{2025-11-24}{changed to document command}
%\cs{relstaticloc}\marg{id1}\marg{id2}
%    \begin{macrocode}
\NewDocumentCommand \relstaticloc { s m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_relative_frame_location_by_idl:nnnn
        { static } { #2 } { static } { #3 }
    }
    {
      \__flowfram_relative_frame_location_by_idn:nnnn
        { static } { #2 } { static } { #3 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@srelstaticloc}
%Version 2.0 removed \cs{@srelstaticloc}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@relstaticloc}
%Version 2.0 removed \cs{@relstaticloc}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\relflowloc}
%\changes{1.11}{2008/06/27}{new}
%\changes{1.14}{2012-11-10}{removed unwanted spaces}
%\changes{2.0}{2025-11-24}{changed to document command}
%\cs{relflowloc}\marg{id1}\marg{id2}
%    \begin{macrocode}
\NewDocumentCommand \relflowloc { s m m }
 {
   \IfBooleanTF { #1 }
    {
      \__flowfram_relative_frame_location_by_idl:nnnn
        { flow } { #2 } { flow } { #3 }
    }
    {
      \__flowfram_relative_frame_location_by_idn:nnnn
        { flow } { #2 } { flow } { #3 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@srelflowloc}
%Version 2.0 removed \cs{@srelflowloc}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@relflowloc}
%Version 2.0 removed \cs{@relflowloc}.
%\changes{2.0}{2025-11-24}{removed}
%\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.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setinitialframe { m }
 {
  \int_gset:Nn \c@thisframe { #1 }
  \global \usedframebreaktrue
  \__flowfram_set_column:n { #1 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\if@setfr@mes}
%Scratch conditional.
% TODO remove ??
%    \begin{macrocode}
\newif\if@setfr@mes
\@setfr@mesfalse
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\setframes}
%\changes{2.0}{2025-11-24}{changed to document command}
% Set the initial frame.
%    \begin{macrocode}
\NewDocumentCommand \setframes { }
{
  \int_if_zero:nT { \c@thisframe }
   {
    \msg_info:nn { flowfram } { no-page1-col }
    \int_gset_eq:NN \g__flowfram_next_frame_int \c_one_int
    \int_gset_eq:NN \g__flowfram_current_page_int \c_one_int
    \__flowfram_get_next_column:N \g__flowfram_next_frame_int 
%    \end{macrocode}
% Shipout pages without flow frames.
%    \begin{macrocode}
    \int_gdecr:N \g__flowfram_current_page_int
    \bool_while_do:nn
      { \int_compare_p:nNn { \g__flowfram_current_page_int } > { \c_zero_int } }
      {
        \int_gdecr:N \g__flowfram_current_page_int
        \setbox \@outputbox 
          \vbox_to_ht:nn { \typeblockheight }
           {
              \__flowfram_do_all_frames: 
           }
        \@outputpage
      }
    \int_gset_eq:NN \c@thisframe \g__flowfram_next_frame_int
   }
  \__flowfram_set_column:n { \c@thisframe }
  \@flowfram@update@col@count { \c@thisframe }
  \@setfr@mestrue
  \flowfram_set_tl_to_frame_tl:Nnnn
     \l__flowfram_textcolor_tl
     { flow } { textcolor } { \c@thisframe }
  \__flowfram_set_text_color:
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\emulatetwocolumn}
%\changes{2.0}{2025-11-24}{changed to document command}
% Emulate original "\twocolumn" declaration.
% This is provided for backward compatibility, and
% may be removed in later versions.
%    \begin{macrocode}
\NewDocumentCommand \emulatetwocolumn { O{} }
 {
   \finishthispage
   \setallflowframes { pages = none }
   \settoheight \l__flowfram_sfdf_height_dim { #1 }
   \settodepth \l__flowfram_tmpa_dim { #1 }
   \addtolength \l__flowfram_sfdf_height_dim
     { \l__flowfram_tmpa_dim }
   \dim_compare:nNnTF
     { \l__flowfram_sfdf_height_dim } > { \c_zero_dim }
    {
      \__flowfram_two_column_with_top_in_area:nnnnnnn
        { \int_eval:n { \g__flowfram_pagecounter_tl } }
        { static }
        { \dim_use:N \l__flowfram_sfdf_height_dim }
        { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \int_gset:Nn \c@thisframe { \c@maxflow - \c_one_int }
      \exp_args:Ne \__flowfram_two_columns:n
          { > \int_eval:n { \g__flowfram_pagecounter_tl } }
      \setstaticcontents { \c@maxstatic } { #1 }
    }
    {
      \__flowfram_two_columns:n { all }
      \int_gset:Nn \c@thisframe { \c@maxflow - \c_one_int }
    }
  \__flowfram_set_column:n { \c@thisframe }
  \relax
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\emulateonecolumn}
%\changes{2.0}{2025-11-24}{changed to document command}
% Emulate original "\onecolumn" declaration.
% This is provided for backward compatibility, and
% may be removed in later versions.
%    \begin{macrocode}
\NewDocumentCommand \emulateonecolumn { O{} }
{
  \finishthispage
  \setallflowframes { pages = none }
  \settoheight \l__flowfram_sfdf_height_dim { #1 }
  \settodepth \l__flowfram_tmpa_dim { #1 }
  \addtolength \l__flowfram_sfdf_height_dim { \l__flowfram_tmpa_dim }
  \dim_compare:nNnTF
    { \l__flowfram_sfdf_height_dim } > { \c_zero_dim }
   {
     \__flowfram_one_column_with_top_in_area:nnnnnnn
       { \int_eval:n { \g__flowfram_pagecounter_tl } }
       { static } 
       { \dim_use:N \l__flowfram_sfdf_height_dim }
       { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
     \int_gset:Nn \c@thisframe { \c@maxflow - \c_one_int }
     \__flowfram_new_flow:nnnnn
       { > \int_eval:n { \g__flowfram_pagecounter_tl } }
       { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
     \setstaticcontents { \c@maxstatic } { #1 }
   }
   {
    \__flowfram_one_column:n { all }
    \int_gset:Nn \c@thisframe { \c@maxflow - \c_one_int }
   }
  \__flowfram_set_column:n { \c@thisframe }
  \relax
}
%    \end{macrocode}
%\end{macro}
%
% If no flow frames have been defined, create a single flow frame
% the size of the \gls{typeblock}, and initialise the frames.
%    \begin{macrocode}
\AtBeginDocument
 {
   \__flowfram_doc_init:
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_doc_init:
 {
%    \end{macrocode}
%Save original definition of \cs{@starttoc} in case it's changed by
%another package loaded after \sty{flowfram}:
%    \begin{macrocode}
  \cs_set_eq:NN \__flowfram_org_starttoc: \@starttoc
%    \end{macrocode}
%Initialise absolutepage.
%    \begin{macrocode}
  \int_gset_eq:NN \c@absolutepage \c_one_int
  \int_if_zero:nT { \c@maxflow }
   {
    \if@twocolumn
      \msg_warning:nnn { flowfram } { no-cols } { 2 }
      \__flowfram_two_columns:n { all }
    \else
      \msg_warning:nnn { flowfram } { no-cols } { 1 }
      \__flowfram_one_column:n { all }
    \fi
   }
  \setframes
  \cs_set_eq:NN \__flowfram_only_document_env:Nn \use_ii:nn
  \cs_set_eq:NN
     \__flowfram_only_preamble:Nn
     \__flowfram_forbidden:Nn
  \cs_set_eq:NN \onecolumn \__flowfram_doc_onecolumn:
  \RenewDocumentCommand \twocolumn { o }
   {
     \__flowfram_doc_twocolumn:n { ##1 }
   }
  \cs_set_eq:NN
      \__flowfram_write_html_opts:nnn
      \__flowfram_doc_write_html_opts:nnn
 }
%    \end{macrocode}
%
%The behaviour of \cs{onecolumn} in the document environment:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_doc_onecolumn:
 {
   \bool_if:NTF  \g__flowfram_ignore_column_changes_bool
    {
      \bool_if:NT \g__flowfram_clearpage_column_changes_bool
       {
         \clearpage
       }
    }
    {
      \flowfram_set_one_col:
    }
 }
%    \end{macrocode}
%The behaviour of \cs{twocolumn} in the document environment:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_doc_twocolumn:n
 {
   \IfValueTF { #1 }
    {
      \bool_if:NTF  \g__flowfram_ignore_column_changes_bool
       {
         \bool_if:NT \g__flowfram_clearpage_column_changes_bool
          {
            \clearpage
          }
          #1
       }
       {
         \flowfram_set_two_col_header:n { #1 }
       }
    }
    {
      \bool_if:NTF  \g__flowfram_ignore_column_changes_bool
       {
          \bool_if:NT \g__flowfram_clearpage_column_changes_bool
           {
             \clearpage
           }
       }
       {
         \flowfram_set_two_col:
       }
    }
   }

%    \end{macrocode}
%If a class or package is being used that automatically inserts
%\cs{onecolumn} or \cs{twocolumn}, identify which frames should be
%switched on or off.
%    \begin{macrocode}
\tl_new:N \g__flowfram_one_col_id_tl
\tl_new:N \g__flowfram_two_col_i_id_tl
\tl_new:N \g__flowfram_two_col_ii_id_tl
\tl_new:N \g__flowfram_two_col_header_id_tl
\tl_new:N \g__flowfram_two_col_header_type_tl
\tl_new:N \g__flowfram_headed_two_col_i_id_tl
\tl_new:N \g__flowfram_headed_two_col_ii_id_tl
%    \end{macrocode}
%\begin{macro}{\SetOneColumnFrame}
%Identify which column should be used if \cs{onecolumn} is
%encountered:
%    \begin{macrocode}
\NewDocumentCommand \SetOneColumnFrame { s m }
 {
   \tl_if_empty:nTF { #2 }
    {
      \tl_gclear:N \g__flowfram_one_col_id_tl
    }
    {
      \IfBooleanTF { #1 }
       {
         \__flowfram_get_flow_id:n { #2 }
         \tl_gset:Ne \g__flowfram_one_col_id_tl
           { \int_use:N \l__flowfram_id_int }
       }
       {
         \bool_lazy_or:nnTF
           {
             \int_compare_p:nNn { #2 } < { \c_one_int }
           }
           {
             \int_compare_p:nNn { #2 } > { \c@maxflow }
           }
          {
             \msg_error:nnnn { flowfram } { idn-undefined }
              { flow } { #2 }
          }
          {
            \tl_gset:Ne \g__flowfram_one_col_id_tl
             { \int_eval:n { #2 } }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\SetTwoColumnFrames}
%Identify which column should be used if \cs{twocolumn} is
%encountered.
%Syntax:
%\oarg{header-type}\oarg{header-id}\marg{col-1}\oarg{header-col1}
%\marg{col-2}\oarg{header-col-2}
%    \begin{macrocode}
\NewDocumentCommand \SetTwoColumnFrames { s o o m o m o }
 {
   \IfValueTF { #2 }
    {
%    \end{macrocode}
% Header frame of given type.
%    \begin{macrocode}
      \cs_if_exist:cTF { __flowfram_get_ #2 _id:n }
       {
         \tl_gset:Ne \g__flowfram_two_col_header_type_tl { #2 }
         \IfValueT { #3 }
          {
            \tl_if_empty:nTF { #3 }
             {
               \tl_gclear:N \g__flowfram_two_col_header_id_tl
             }
             {
               \IfBooleanTF { #1 }
                {
                  \use:c { __flowfram_get_ #2 _id:n } { #3 }
                  \tl_gset:Ne \g__flowfram_two_col_header_id_tl
                    { \int_use:N \l__flowfram_id_int }
                }
                {
                  \bool_lazy_or:nnTF
                    {
                      \int_compare_p:nNn { #3 } < { \c_one_int }
                    }
                    {
                      \int_compare_p:nNn { #3 } > { \int_use:c { c@max #2 } }
                    }
                   {
                      \msg_error:nnnn { flowfram } { idn-undefined }
                       { #2 } { #3 }
                   }
                   {
                     \tl_gset:Ne \g__flowfram_two_col_header_id_tl
                      { \int_eval:n { #3 } }
                   }
                }
             }
          }
       }
       {
          \msg_error:nnn { flowfram } { invalid-frame-type } { #2 }
       }
   }
%    \end{macrocode}
% First flow frame.
%    \begin{macrocode}
   \tl_if_empty:nTF { #4 }
    {
      \tl_gclear:N \g__flowfram_two_col_i_id_tl
    }
    {
      \IfBooleanTF { #1 }
       {
         \__flowfram_get_flow_id:n { #4 }
         \tl_gset:Ne \g__flowfram_two_col_i_id_tl
           { \int_use:N \l__flowfram_id_int }
       }
       {
         \bool_lazy_or:nnTF
           {
             \int_compare_p:nNn { #4 } < { \c_one_int }
           }
           {
             \int_compare_p:nNn { #4 } > { \c@maxflow }
           }
          {
             \msg_error:nnnn { flowfram } { idn-undefined }
              { flow } { #4 }
          }
          {
            \tl_gset:Ne \g__flowfram_two_col_i_id_tl
              { \int_eval:n { #4 } }
          }
       }
    }
%    \end{macrocode}
% First flow frame on headed page.
%    \begin{macrocode}
   \IfValueT { #5 }
    {
      \tl_if_empty:nTF { #5 }
       {
         \tl_gclear:N \g__flowfram_headed_two_col_i_id_tl
       }
       {
         \IfBooleanTF { #1 }
          {
            \__flowfram_get_flow_id:n { #5 }
            \tl_gset:Ne \g__flowfram_headed_two_col_i_id_tl
              { \int_use:N \l__flowfram_id_int }
          }
          {
            \bool_lazy_or:nnTF
              {
                \int_compare_p:nNn { #5 } < { \c_one_int }
              }
              {
                \int_compare_p:nNn { #5 } > { \c@maxflow }
              }
             {
                \msg_error:nnnn { flowfram } { idn-undefined }
                 { flow } { #5 }
             }
             {
               \tl_gset:Ne \g__flowfram_headed_two_col_i_id_tl
                { \int_eval:n { #5 } }
             }
          }
       }
    }
%    \end{macrocode}
% Second flow frame.
%    \begin{macrocode}
   \tl_if_empty:nTF { #6 }
    {
      \tl_gclear:N \g__flowfram_two_col_ii_id_tl
    }
    {
      \IfBooleanTF { #1 }
       {
         \__flowfram_get_flow_id:n { #6 }
         \tl_gset:Ne \g__flowfram_two_col_ii_id_tl
           { \int_use:N \l__flowfram_id_int }
       }
       {
         \bool_lazy_or:nnTF
           {
             \int_compare_p:nNn { #6 } < { \c_one_int }
           }
           {
             \int_compare_p:nNn { #6 } > { \c@maxflow }
           }
          {
             \msg_error:nnnn { flowfram } { idn-undefined }
              { flow } { #6 }
          }
          {
            \tl_gset:Ne \g__flowfram_two_col_ii_id_tl
             { \int_eval:n { #6 } }
          }
       }
    }
%    \end{macrocode}
% Second flow frame on headed page.
%    \begin{macrocode}
   \IfValueT { #7 }
    {
      \tl_if_empty:nTF { #7 }
       {
         \tl_gclear:N \g__flowfram_headed_two_col_ii_id_tl
       }
       {
         \IfBooleanTF { #1 }
          {
            \__flowfram_get_flow_id:n { #7 }
            \tl_gset:Ne \g__flowfram_headed_two_col_ii_id_tl
              { \int_use:N \l__flowfram_id_int }
          }
          {
            \bool_lazy_or:nnTF
              {
                \int_compare_p:nNn { #7 } < { \c_one_int }
              }
              {
                \int_compare_p:nNn { #7 } > { \c@maxflow }
              }
             {
                \msg_error:nnnn { flowfram } { idn-undefined }
                 { flow } { #7 }
             }
             {
               \tl_gset:Ne \g__flowfram_headed_two_col_ii_id_tl
                { \int_eval:n { #7 } }
             }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%Switch to the column associated with \cs{onecolumn}:
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_one_col:
 {
   \tl_if_empty:NTF \g__flowfram_one_col_id_tl
    {
      \msg_warning:nnn { flowfram } { misplaced-col-cmd } { \onecolumn }
    }
    {
      \int_step_inline:nn { \c@maxflow }
       {
%    \end{macrocode}
% Is this frame currently on or off on this page?
%    \begin{macrocode}
          \__flowfram_check_if_this_page:nn
            { \g__flowfram_pagecounter_tl } { ##1 }
         \int_compare:nNnTF
           { ##1 } = { \g__flowfram_one_col_id_tl }
          {
            \bool_if:NT \g__flowfram_not_this_frame_bool
             {
               \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl
                 {
                    \flowsetpagelist { ##1 }
                     {
                       pages =
                        {  > \int_eval:n { \g__flowfram_pagecounter_tl } }
                     }
                 }
             }
          }
          {
            \bool_if:NF \g__flowfram_not_this_frame_bool
             {
               \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl
                 {
                    \flowsetpagelist { ##1 } { pages = none }
                 }
             }
          }
       }
    }
   \clearpage
 }
%    \end{macrocode}
%Two columns with no header.
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_two_col:
 {
   \bool_lazy_or:nnTF
     {
       \tl_if_empty_p:N \g__flowfram_two_col_i_id_tl
     }
     {
       \tl_if_empty_p:N \g__flowfram_two_col_ii_id_tl
     }
    {
       \msg_warning:nnn { flowfram } { misplaced-col-cmd } { \twocolumn }
    }
    {
      \int_step_inline:nn { \c@maxflow }
       {
%    \end{macrocode}
% Is this frame currently on or off on this page?
%    \begin{macrocode}
          \__flowfram_check_if_this_page:nn
            { \g__flowfram_pagecounter_tl } { ##1 }
         \bool_lazy_or:nnTF
           {
             \int_compare_p:nNn
               { ##1 } = { \g__flowfram_two_col_i_id_tl }
           }
           {
             \int_compare_p:nNn
               { ##1 } = { \g__flowfram_two_col_ii_id_tl }
           }
          {
            \bool_if:NT \g__flowfram_not_this_frame_bool
             {
               \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl
                 {
                    \flowsetpagelist { ##1 }
                     {
                       pages =
                        { > \int_eval:n { \g__flowfram_pagecounter_tl } }
                     }
                 }
             }
          }
          {
            \bool_if:NF \g__flowfram_not_this_frame_bool
             {
               \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl
                 {
                    \flowsetpagelist { ##1 } { pages = none }
                 }
             }
          }
       }
    }
   \clearpage
 }
%    \end{macrocode}
%Two columns with header.
%    \begin{macrocode}
\cs_new:Nn \flowfram_set_two_col_header:n
 {
   \tl_if_empty:NTF \g__flowfram_two_col_header_id_tl
    {
      \flowfram_set_two_col:
      #1
    }
    {
      \bool_lazy_and:nnTF
        {
          \tl_if_empty_p:N \g__flowfram_headed_two_col_i_id_tl
        }
        {
          \tl_if_empty_p:N \g__flowfram_headed_two_col_ii_id_tl
        }
       {
         \flowfram_set_two_col:
       }
       {
         \int_step_inline:nn { \c@maxflow }
          {
%    \end{macrocode}
% Is this frame currently on or off on this page?
%    \begin{macrocode}
             \__flowfram_check_if_this_page:nn
               { \g__flowfram_pagecounter_tl } { ##1 }
            \bool_lazy_or:nnTF
              {
                \int_compare_p:nNn
                  { ##1 } = { \g__flowfram_two_col_i_id_tl }
              }
              {
                \int_compare_p:nNn
                  { ##1 } = { \g__flowfram_two_col_ii_id_tl }
              }
             {
               \bool_if:NT \g__flowfram_not_this_frame_bool
                {
                  \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl
                    {
                       \flowsetpagelist { ##1 }
                        {
                          pages =
                           {
                             >
                              \int_eval:n
                               {
                                 \g__flowfram_pagecounter_tl
                                  + \c_one_int
                               }
                            }
                        }
                    }
                }
             }
             {
               \bool_lazy_or:nnTF
                 {
                   \int_compare_p:nNn
                     { ##1 } = { \g__flowfram_headed_two_col_i_id_tl }
                 }
                 {
                   \int_compare_p:nNn
                     { ##1 } = { \g__flowfram_headed_two_col_ii_id_tl }
                 }
                {
                  \bool_if:NT \g__flowfram_not_this_frame_bool
                   {
                     \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl
                       {
                          \flowsetpagelist { ##1 }
                           {
                             pages =
                              { \int_eval:n { \g__flowfram_pagecounter_tl } }
                           }
                       }
                   }
                }
                {
                  \bool_if:NF \g__flowfram_not_this_frame_bool
                   {
                     \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl
                       {
                          \flowsetpagelist { ##1 } { pages = none }
                       }
                   }
                }
             }
          }
         \clearpage
       }
      \cs_if_exist:cTF
           { set \g__flowfram_two_col_header_type_tl  contents }
        {
          \use:c
           { set \g__flowfram_two_col_header_type_tl  contents }
           { \g__flowfram_two_col_header_id_tl }
           { #1 }
        }
        {
          #1
        }
    }
 }
%    \end{macrocode}
%
%\subsection{Output Routine}
%
%\begin{macro}{\fftolerance}
% The \sty{flowfram} package does a check to see if text has
% flowed between frames of different widths, which will cause a
% discrepancy in the line widths of the paragraph spanning the break.
% Before version~1.14, the output routine just checked if the widths
% were different, but this means that warning messages will be
% generated even if there's only a tiny difference that can be
% caused by rounding errors (for example, if the frames were created
% using jpgfdraw). So add a tolerance and only complain if the
% difference exceeds this value.
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newlength\fftolerance
\setlength\fftolerance{2pt}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\columnheight}
%Version 2.0 removed \cs{columnheight}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\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}
%\changes{1.14}{2012-11-10}{changed check to use tolerance rather
%than testing if hsize and columnwidth are equal}
%Version 2.0 renamed \cs{@setcol}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_column:n
 {
  \bool_lazy_or:nnTF
    {
      \int_compare_p:nNn { \c@maxflow } < { #1 }
    }
    {
      \int_compare_p:nNn { #1 } < { \c_one_int }
    }
   {
    \msg_error:nne { flowfram } { cant-set-column }
      { \int_eval:n { #1 } }
   }
   {
    \exp_args:Nnee
    \__flowfram_message:nnn
      { info-switching-col }
      { \int_eval:n { #1 } }
      { \int_eval:n { \g__flowfram_pagecounter_tl } }
    \dim_gset:Nn
      \columnwidth
      { \flowfram_frame_use_dim:nnn { flow } { width } { #1 } }
    \legacy_if:nF { usedframebreak }
     {
      \dim_set_eq:NN \l__flowfram_tmpb_dim \columnwidth
      \dim_sub:Nn \l__flowfram_tmpb_dim { \hsize }
      \dim_compare:nNnT { \l__flowfram_tmpb_dim  } < { \c_zero_dim }
       {
         \dim_set:Nn \l__flowfram_tmpb_dim { - \l__flowfram_tmpb_dim }
       }
      \dim_compare:nNnT { \l__flowfram_tmpb_dim } > { \fftolerance }
       {
           \msg_warning:nnee { flowfram } { unequal-cols }
            { \dim_use:N \l__flowfram_tmpb_dim }
            { \the \fftolerance }
       }
     }
    \global \usedframebreakfalse
    \global \hsize \columnwidth
    \flowfram_gset_dim_to_frame_dim:Nnnn
      \textheight { flow } { height } { #1 }
    \global \vsize \textheight
    \global \@colht \textheight
    \global \@colroom \@colht
%    \end{macrocode}
% We may be inside an environment that has modified the line
% width, such as one of the list environments so we can't just set
% \cs{linewidth} to \cs{columnwidth}. Test if we're in a list
% environment by checking if \cs{@listdepth} is greater than 0. If
% true,  only modify \cs{linewidth} if
% it's larger than the new column width.
%\changes{1.15}{2014-05-15}{set \cs{linewidth} as well as \cs{textwidth}}
%\changes{1.17}{2014-09-30}{added check for list}
%    \begin{macrocode}
    \int_compare:nNnTF { \@listdepth } > { \c_zero_int }
     {
       \dim_compare:nNnT { \linewidth } > { \columnwidth }
        {
          \dim_gset_eq:NN \linewidth \columnwidth
        }
     }
     {
        \dim_gset_eq:NN \linewidth \columnwidth
     }
%    \end{macrocode}
%\changes{1.16}{2014-06-04}{Removed assignment of \cs{textwidth}}
%    \begin{macrocode}
    \setmargin
   }
  \stepcounter { displayedframe }
}
%    \end{macrocode}
%\end{macro}
%Version 2.0 no longer overriding \cs{output}.
%\begin{macro}{\@doclearpage}
%Version 2.0 no longer redefining \cs{@doclearpage}.
%\changes{2.0}{2025-11-24}{no longer redefining}
%\end{macro}
%
%\begin{macro}{\flowfram@header}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \flowfram@header [2]
 {
   \__flowfram_header:n 
    {
      \color@hbox
      \g__flowfram_headercolor_tl
      \hbox_to_wd:nn { #1 } { #2 }
      \color@endbox
    }
 }
%    \end{macrocode}
%\end{macro}
%Boxes may interfere with the dynamic frame settings, so provide an
%alternative. This may be redefined to \cs{flowfram@header} if
%preferred:
%\begin{macro}{\flowfram@dynamicheader}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \flowfram@dynamicheader [2]
 {
   \g__flowfram_headercolor_tl
   \__flowfram_header:n { #2 } 
 }
%    \end{macrocode}
%\end{macro}
%    \begin{macrocode}
\tl_new:N \g__flowfram_headercolor_tl 
\tl_gset:Nn \g__flowfram_headercolor_tl { \normalcolor }
\cs_new:Nn \__flowfram_header:n
 {
  \pdfannot@link@off@@
    \UseTaggingSocket
    {build/page/header}
    { }
    { #1 }
  \pdfannot@link@on@@
 }
%    \end{macrocode}
%\begin{macro}{\flowfram@footer}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \flowfram@footer [2]
 {
   \__flowfram_footer:n 
    {
      \color@hbox
      \g__flowfram_footercolor_tl 
      \hbox_to_wd:nn { #1 } { #2 } 
      \color@endbox 
    } 
 }
%    \end{macrocode}
%\end{macro}
%Boxes may interfere with the dynamic frame settings, so provide an
%alternative. This may be redefined to \cs{flowfram@footer} if
%preferred:
%\begin{macro}{\flowfram@dynamicfooter}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \flowfram@dynamicfooter [2]
 {
   \g__flowfram_footercolor_tl 
   \__flowfram_footer:n { #2 } 
 }
%    \end{macrocode}
%\end{macro}
%    \begin{macrocode}
\tl_new:N \g__flowfram_footercolor_tl 
\tl_gset:Nn \g__flowfram_footercolor_tl { \normalcolor }
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_footer:n
 {
   \pdfannot@link@off@@
   \UseTaggingSocket {build/page/footer}
     { }
     { #1 }
   \pdfannot@link@on@@
 }
%    \end{macrocode}
%
%\begin{macro}{\@dothehead}
% First define macro to do the header. This will be
% modified if it is turned into a \gls{dynamic}.
%Version 2.0 added tagging socket.
%\changes{2.0}{2025-11-24}{added tagging socket}
%    \begin{macrocode}
\newcommand{\@dothehead}{
  \vbox_to_ht:nn { \headheight }
   {
     \vfil
     \flowfram@header { \typeblockwidth }
       {
        \@thehead 
       }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dothefoot}
% Same again for the footer.
%    \begin{macrocode}
\newcommand{\@dothefoot}{
  \vbox:n 
   {
     \flowfram@footer { \typeblockwidth }
      {
       \@thefoot 
      }
   }
}
\newcommand{\@dodynamicthehead}{}
\newcommand{\@dodynamicthefoot}{}
%    \end{macrocode}
%\end{macro}
%
%Column spanning floats conflict with \sty{flowfram}'s output
%routine so make starred floats behave like unstarred floats.
%    \begin{macrocode}
\cs_set_eq:NN \__flowfram_org_dblfloat: \@dblfloat
\cs_set_eq:NN \@dblfloat \@float
\cs_set_eq:NN \__flowfram_org_enddblfloat: \end@dblfloat
\cs_set_eq:NN \end@dblfloat \end@float
%    \end{macrocode}
%
%\begin{macro}{\FlowFramRestoreOR}
%Version 2.0: provide a way of restoring the output routine.
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\cs_set_eq:NN \__flowfram_org_opcol: \@opcol
\cs_set_eq:NN \__flowfram_org_outputdblcol: \@outputdblcol
\int_new:N \g__flowfram_saved_thisframe_int
\NewDocumentCommand \FlowFramRestoreOR {  }
 {
   \__flowfram_only_document_env:Nn \FlowFramRestoreOR
    {
      \finishthispage
      \int_gset_eq:NN \g__flowfram_saved_thisframe_int \c@thisframe
      \cs_set_eq:NN \@dblfloat \__flowfram_org_dblfloat:
      \cs_set_eq:NN \end@dblfloat \__flowfram_org_enddblfloat:
      \cs_set_eq:NN \@opcol \__flowfram_org_opcol:
      \cs_set_eq:NN \@outputdblcol \__flowfram_org_outputdblcol:
      \let\@outputpage\@@flowfram@org@output@page
      \renewcommand \@flowfram@build@page@after
       {
         \stepcounter{absolutepage}%
       }
      \cs_set_eq:NN \onecolumn \__flowfram_org_onecolumn:
      \cs_set_eq:NN \twocolumn \__flowfram_org_twocolumn:
      \int_gset_eq:NN \col@number \c_one_int
      \global \@twocolumnfalse
      \global \textwidth \typeblockwidth
      \global \textheight \typeblockheight
      \global \columnwidth \textwidth
      \global \hsize \textwidth
      \global \vsize \textheight
      \global \@colht \vsize
      \global \@colroom \@colht
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FlowFramUnrestoreOR}
%And switch back again. 
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\NewDocumentCommand \FlowFramUnrestoreOR { }
 {
   \__flowfram_only_document_env:Nn \FlowFramUnrestoreOR
    {
      \clearpage
      \cs_set_eq:NN \@opcol \__flowfram_op_col:
      \cs_set_eq:NN \@outputdblcol \__flowfram_output_dbl_col:
      \let\@outputpage\@@flowfram@output@page
      \cs_set_eq:NN \@dblfloat \@float
      \cs_set_eq:NN \end@dblfloat \end@float
      \renewcommand \@flowfram@build@page@before { }
      \renewcommand \@flowfram@build@page@after { }
      \cs_set_eq:NN \onecolumn \__flowfram_doc_onecolumn:
      \RenewDocumentCommand \twocolumn { o }
       {
         \__flowfram_doc_twocolumn:n { ##1 }
       }
      \int_gzero:N \c@displayedframe
      \int_gset_eq:NN \c@thisframe \g__flowfram_saved_thisframe_int
      \int_gset_eq:NN \g__flowfram_next_frame_int \g__flowfram_saved_thisframe_int
      \__flowfram_set_column:n { \c@thisframe }
      \@flowfram@update@col@count{\c@thisframe}%
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@opcol}
%Version 2.0 ensure marks stuff is included but always use
%\cs{@outputdblcol}.
%\changes{2.0}{2025-11-24}{include mark structures}
%    \begin{macrocode}
\renewcommand * \@opcol { \__flowfram_op_col: }
%    \end{macrocode}
%\end{macro}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_op_col:
 {
  \if@twocolumn
    \@expl@@@mark@update@dblcol@structures@@
  \else
    \@expl@@@mark@update@singlecol@structures@@
  \fi
  \@outputdblcol
  \global \@mparbottom \z@
  \global \@textfloatsheight \z@
  \@flowfram@adjust@fdepth
  \@floatplacement
}
%    \end{macrocode}
%
%\begin{macro}{\@flowfram@adjust@fdepth}
%\changes{2.1}{2026-02-23}{new}
%TODO investigate why this doesn't work as expected
%    \begin{macrocode}
\newcommand\@flowfram@adjust@fdepth{%
 %\def\f@depth{1sp}%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@outputpage}
%The header and footer code need to be removed as they may be placed
%in a dynamic frame instead and repositioned.
%Version 2.0 updated.
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%Save original so that it can be restored.
%    \begin{macrocode}
\let\@@flowfram@org@output@page\@outputpage
\def\@outputpage{\@@flowfram@output@page}
%    \end{macrocode}
%Define \sty{flowfram}'s version of \cs{@outputpage}:
%    \begin{macrocode}
\newcommand \@@flowfram@output@page{%
 \UseHook {build/page/before}%
 \begingroup
 \let \protect \noexpand
 \language\document@default@language
 \@resetactivechars
 \nfss@catcodes
 \catcode`\$\thr@@
 \catcode`\_8\relax
 \catcode`\ 10\relax
 \catcode`\^^I10\relax 
 \catcode`\~13\relax
 \catcode`\^^M5\relax
 \global\let\@@if@newlist\if@newlist
 \global\@newlistfalse
 \UseHook {build/page/reset}%
 \shipout \vbox{%
  \set@typeset@protect
  \aftergroup \endgroup
  \aftergroup \set@typeset@protect
  \if@specialpage
    \global \@specialpagefalse
    \ifcsdef {ps@special\@specialstyle}%
    {\@nameuse {ps@special\@specialstyle}}%
    {\@nameuse {ps@\@specialstyle}}%
  \fi
  \if@twoside
    \ifodd\count\z@
      \let \@thehead \@oddhead
      \let \@thefoot \@oddfoot
      \let \@themargin \oddsidemargin 
    \else
      \let \@thehead \@evenhead
      \let \@thefoot \@evenfoot
      \let \@themargin \evensidemargin
    \fi
  \else
   \let \@thehead \@oddhead
   \let \@thefoot \@oddfoot
   \let \@themargin \oddsidemargin 
  \fi
%    \end{macrocode}
%Omit block relating to header, footer and margin.
%    \begin{macrocode}
  \reset@font
  \normalsize
  \normalsfcodes
  \let \label \@gobble@with@sphack@om
  \let \index \@gobble@with@sphack@som
  \let \glossary \@gobble@with@sphack@om
  \let \@@flowfram@current@pre@section@title \empty
  \baselineskip \z@skip
  \lineskip \z@skip
  \lineskiplimit \z@
    \@begindvi
    \vskip \typeblockoffsety
    \moveright\@themargin \vbox {%
%    \end{macrocode}
%Omit header.
%    \begin{macrocode}
      \box \@outputbox
%    \end{macrocode}
%Omit footer.
%    \begin{macrocode}
   }%
  }%
  \global \let \if@newlist \@@if@newlist
  \@flowfram@set@next@vsize
  \global \textwidth \hsize
  \global \textheight \vsize
  \global \@colht \vsize
  \global \@colroom \@colht
  \stepcounter{page}%
  \stepcounter{absolutepage}%
  \setcounter{displayedframe}{0}%
  \@flowfram@update@col@count{\c@thisframe}%
  \UseHook {build/page/after}%
}
\ExplSyntaxOn
%    \end{macrocode}
%If OR is restored, provide a means to still display the dynamic
%frames and update absolutepage.
%    \begin{macrocode}
\AddToHook {build/page/before}
 {
   \@flowfram@build@page@before
 }
\AddToHook {build/page/after}
 {
   \@flowfram@build@page@after
 }
%    \end{macrocode}
%No extra action unless OR is restored.
%    \begin{macrocode}
\newcommand\@flowfram@build@page@before{}
\newcommand\@flowfram@build@page@after{}
%    \end{macrocode}
%Set \cs{vsize} for next frame.
%    \begin{macrocode}
\newcommand\@flowfram@set@next@vsize
 {
   \flowfram_gset_dim_to_frame_dim:Nnnn \vsize
      { flow } { height } { \g__flowfram_next_frame_int }
 }
%    \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".
%\changes{2.0}{2025-11-24}{changed to document command}
%
%Keep track of which frames have the header and footer. These will
%be zero if feature not implemented. NB the even IDs are only set by
%\sty{flowframtkutils}.
%    \begin{macrocode}
\int_new:N \g__flowfram_dynamic_header_int
\int_new:N \g__flowfram_dynamic_even_header_int
\int_new:N \g__flowfram_dynamic_footer_int
\int_new:N \g__flowfram_dynamic_even_footer_int
%    \end{macrocode}
% Create dynamic frames for the header and footer.
%    \begin{macrocode}
\NewDocumentCommand \makedfheaderfooter { }
 {
%    \end{macrocode}
% Create dynamic frames at the standard location:
%    \begin{macrocode}
   \__flowfram_new_dynamic:nnnnnn
    { all } { \typeblockwidth } { \headheight }
    { 0pt } { \typeblockheight + \headsep } { header }
   \int_set_eq:NN \g__flowfram_dynamic_header_int
     \c@maxdynamic 
   \__flowfram_set_dynamic_by_idn:nn { \c@maxdynamic } { valign=c }
   \__flowfram_new_dynamic:nnnnnn
    { all } { \typeblockwidth } { \headheight }
    { 0pt } { -\footskip } { footer }
   \int_set_eq:NN \g__flowfram_dynamic_footer_int
     \c@maxdynamic 
   \__flowfram_set_dynamic_by_idn:nn { \c@maxdynamic } { valign=c }
   \gdef \@dothehead { }
   \gdef \@dothefoot { }
   \gdef \@dodynamicthehead
    {
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_header_int }
       {
         \flowfram_dynamic_header:n
           { \g__flowfram_dynamic_header_int }
       }
    }
   \gdef \@dodynamicthefoot
    {
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_footer_int } 
       {
          \flowfram_dynamic_footer:n
           { \g__flowfram_dynamic_footer_int }
       }
   }
  \tl_clear:N \g__flowfram_headercolor_tl 
  \tl_clear:N \g__flowfram_footercolor_tl 
  \__flowfram_adjust_page_styles:n
   {
      \let \ps@myheadings \ps@ffmyheadings
      \let \ps@headings \ps@ffheadings
      \let \ps@plain \ps@ffplain
      \let \ps@empty \ps@ffempty
   }
  \pagestyle { ffheadings }
  \cs_set:Nn \__flowfram_only_pre_makedfheaderfooter:nn
   {
     \msg_error:nnn { flowfram } { option-too-late } { ##1 } { \makedfheaderfooter }
   }
 }
%    \end{macrocode}
%
% This should only be done in the preamble.
%    \begin{macrocode}
\@onlypreamble{\makedfheaderfooter}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FlowFramSetDynamicHeadFootAttributes}
%\changes{2.0}{2025-11-24}{new}
%Set dynamic header and footer frame attributes if they have been defined.
%Does nothing otherwise.
%    \begin{macrocode}
\NewDocumentCommand \FlowFramSetDynamicHeadFootAttributes { m }
 {
   \int_compare:nNnT
     { \g__flowfram_dynamic_header_int } > { \c_zero_int }
    {
      \__flowfram_set_dynamic_by_idn:nn
        { \g__flowfram_dynamic_header_int } { #1 }
    }
   \int_compare:nNnT
     { \g__flowfram_dynamic_even_header_int } > { \c_zero_int }
    {
      \__flowfram_set_dynamic_by_idn:nn
        { \g__flowfram_dynamic_even_header_int } { #1 }
    }
   \int_compare:nNnT
     { \g__flowfram_dynamic_footer_int } > { \c_zero_int }
    {
      \__flowfram_set_dynamic_by_idn:nn
        { \g__flowfram_dynamic_footer_int } { #1 }
    }
   \int_compare:nNnT
     { \g__flowfram_dynamic_even_footer_int } > { \c_zero_int }
    {
      \__flowfram_set_dynamic_by_idn:nn
        { \g__flowfram_dynamic_even_footer_int } { #1 }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%The argument is the dynamic frame's IDN.
%The box is added because in some cases without it an infinite
%shrinkage error occurs.
%    \begin{macrocode}
\cs_new:Nn \flowfram_dynamic_header:n
 {
   \flowfram_set_dim_to_frame_dim:Nnnn
      \l__flowfram_sfdf_width_dim
       { dynamic } { width } { #1 }
  \if@twoside
    \ifodd\c@page
     \flowfram@dynamicheader
       { \l__flowfram_sfdf_width_dim }
       { \@oddhead }
    \else
     \flowfram@dynamicheader
       { \l__flowfram_sfdf_width_dim }
       { \@evenhead }
    \fi
  \else
    \flowfram@dynamicheader
      { \l__flowfram_sfdf_width_dim }
      { \@thehead }
  \fi
 }
%    \end{macrocode}
%For the benefit of \sty{flowframtkutils}, where there may be
%separate odd and even header dynamic frames:
%    \begin{macrocode}
\cs_new:Nn \flowfram_dynamic_odd_header:n
 {
   \flowfram_set_dim_to_frame_dim:Nnnn
      \l__flowfram_sfdf_width_dim
       { dynamic } { width } { #1 }
  \if@twoside
    \ifodd\c@page
     \flowfram@dynamicheader
       { \l__flowfram_sfdf_width_dim }
       { \@oddhead }
    \else
     \flowfram@dynamicheader
       { \l__flowfram_sfdf_width_dim }
       { }
    \fi
  \else
    \flowfram@dynamicheader
      { \l__flowfram_sfdf_width_dim }
      { \@thehead }
  \fi
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_dynamic_even_header:n
 {
   \flowfram_set_dim_to_frame_dim:Nnnn
      \l__flowfram_sfdf_width_dim
       { dynamic } { width } { #1 }
  \if@twoside
    \ifodd\c@page
     \flowfram@dynamicheader
       { \l__flowfram_sfdf_width_dim }
       { }
    \else
     \flowfram@dynamicheader
       { \l__flowfram_sfdf_width_dim }
       { \@evenhead }
    \fi
  \else
    \flowfram@dynamicheader
      { \l__flowfram_sfdf_width_dim }
      { }
  \fi
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_dynamic_footer:n
 {
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_sfdf_width_dim
     { dynamic } { width } { #1 }
  \if@twoside
    \ifodd\c@page
      \flowfram@dynamicfooter
       { \l__flowfram_sfdf_width_dim } { \@oddfoot }
    \else
      \flowfram@dynamicfooter
       { \l__flowfram_sfdf_width_dim } { \@evenfoot }
    \fi
  \else
    \flowfram@dynamicfooter
     { \l__flowfram_sfdf_width_dim } { \@thefoot }
  \fi
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_dynamic_odd_footer:n
 {
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_sfdf_width_dim
     { dynamic } { width } { #1 }
  \if@twoside
    \ifodd\c@page
      \flowfram@dynamicfooter
       { \l__flowfram_sfdf_width_dim } { \@oddfoot }
    \else
      \flowfram@dynamicfooter
       { \l__flowfram_sfdf_width_dim } { }
    \fi
  \else
    \flowfram@dynamicfooter
     { \l__flowfram_sfdf_width_dim } { \@thefoot }
  \fi
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowfram_dynamic_even_footer:n
 {
   \flowfram_set_dim_to_frame_dim:Nnnn
     \l__flowfram_sfdf_width_dim
     { dynamic } { width } { #1 }
  \if@twoside
    \ifodd\c@page
      \flowfram@dynamicfooter
       { \l__flowfram_sfdf_width_dim } { }
    \else
      \flowfram@dynamicfooter
       { \l__flowfram_sfdf_width_dim } { \@evenfoot }
    \fi
  \else
    \flowfram@dynamicfooter
     { \l__flowfram_sfdf_width_dim } { }
  \fi
 }
%    \end{macrocode}
%
%
%\begin{macro}{\dfOddHeaderStyle}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \dfOddHeaderStyle [ 1 ] { \hfill #1 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dfEvenHeaderStyle}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \dfEvenHeaderStyle [ 1 ] { #1 \hfill }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dfOddFooterStyle}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \dfOddFooterStyle [ 1 ] { \hfill #1 \hfill }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dfEvenFooterStyle}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \dfEvenFooterStyle [ 1 ] { \hfill #1 \hfill }
%    \end{macrocode}
%\end{macro}
%Some classes have page styles that cause a problem with the dynamic
%header and footer so provide a simple page style. The dynamic
%frame's attributes can be adjusted to changing the formatting.
%    \begin{macrocode}
\cs_if_exist:NTF \chapter
 {
   \cs_new:Nn \__flowfram_ps_myheadings:
    {
      \def \@oddfoot { \dfOddFooterStyle { \thepage } }
      \def \@evenfoot { \dfEvenFooterStyle { \thepage } }
      \def \@oddhead { \dfOddHeaderStyle { \rightmark } }
      \def \@evenhead { \dfEvenHeaderStyle { \leftmark } }
      \let \@mkboth \@gobbletwo
      \let \chaptermark \@gobble
      \let \sectionmark \@gobble
    }
   \cs_new:Nn \__flowfram_ps_headings:
    {
      \def \@oddfoot { \dfOddFooterStyle { \thepage } }
      \def \@evenfoot { \dfEvenFooterStyle { \thepage } }
      \def \@oddhead { \dfOddHeaderStyle { \rightmark } }
      \def \@evenhead { \dfEvenHeaderStyle { \leftmark } }
      \let \@mkboth \markboth
      \def \chaptermark ##1
       {
         \markboth
          {
            \flowframchapterheader { ##1 }
          }
          {
            \flowfram_initial_right_mark:n
             {
               \flowframchapterheader { ##1 }
             }
          }
       }
      \def \sectionmark ##1
       {
         \markright
          {
            \flowframsectionheader { ##1 }
          }
       }
    }
   \newcommand \flowframchapterheader [ 1 ]
    {
      \flowfram_header_font:n
       {
        \flowfram_header_case:n
          {
            \ifnum \c@secnumdepth >\m@ne
              \if@mainmatter
                \flowframheaderchapprefix
                \thechapter 
                \flowframheadersep
              \fi
            \fi
            #1
          }
       }
    }
   \newcommand \flowframsectionheader [ 1 ]
    {
      \flowfram_subheader_font:n
       {
         \flowfram_subheader_case:n
          {
            \ifnum \c@secnumdepth >\z@
               \thesection
               \flowframheadersep
            \fi
            #1
          }
       }
    }
 }
 {
   \cs_new:Nn \__flowfram_ps_myheadings:
    {
      \def \@oddfoot { \dfOddFooterStyle { \thepage } }
      \def \@evenfoot { \dfEvenFooterStyle { \thepage } }
      \def \@oddhead { \dfOddHeaderStyle { \rightmark } }
      \def \@evenhead { \dfEvenHeaderStyle { \leftmark } }
      \let \@mkboth \@gobbletwo
      \let \sectionmark \@gobble
      \let \subsectionmark \@gobble
    }
   \cs_new:Nn \__flowfram_ps_headings:
    {
      \def \@oddfoot { \dfOddFooterStyle { \thepage } }
      \def \@evenfoot { \dfEvenFooterStyle { \thepage } }
      \def \@oddhead { \dfOddHeaderStyle { \rightmark } }
      \def \@evenhead { \dfEvenHeaderStyle { \leftmark } }
      \let \@mkboth \markboth
      \def \sectionmark ##1
        {
          \markboth
           {
             \flowframsectionheader { ##1 }
           }
           {
            \flowfram_initial_right_mark:n
             {
               \flowframsectionheader { ##1 }
             }
           }
        }
      \def \subsectionmark ##1
       {
         \markright
          {
            \flowframsubsectionheader { ##1 }
          }
       }
    }
   \newcommand \flowframsectionheader [ 1 ]
    {
      \flowfram_header_font:n
       {
         \flowfram_header_case:n
          {
            \ifnum \c@secnumdepth >\m@ne
              \thesection
              \flowframheadersep
            \fi
            #1
          }
       }
    }
   \newcommand \flowframsubsectionheader [ 1 ]
    {
      \flowfram_subheader_font:n
       {
         \flowfram_subheader_case:n
          {
            \int_compare:nNnT { \c@secnumdepth } > { 2 }
             {
              \thesubsection
              \flowframheadersep
             }
            #1
          }
       }
    }
 }
%    \end{macrocode}
%At the start of a chapter/section the following governs whether or
%not to initialise the right mark to the same as the left mark.
%    \begin{macrocode}
\cs_new:Nn \flowfram_initial_right_mark:n { #1 }
%    \end{macrocode}
%\begin{macro}{\ps@ffmyheadings}
%    \begin{macrocode}
\newcommand \ps@ffmyheadings
 {
   \__flowfram_ps_myheadings:
   \bool_if:NT \l__flowfram_ps_ffempty_hides_bool
    {
      \FlowFramSetDynamicHeadFootAttributes
        { hide = false , hidethis = false }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ps@ffheadings}
%    \begin{macrocode}
\newcommand \ps@ffheadings
 {
   \__flowfram_ps_headings:
   \bool_if:NT \l__flowfram_ps_ffempty_hides_bool
    {
      \FlowFramSetDynamicHeadFootAttributes 
        { hide = false , hidethis = false }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ps@ffplain}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ps@ffplain
 {
   \__flowfram_ps_plain:
   \bool_if:NT \l__flowfram_ps_ffempty_hides_bool
    {
      \FlowFramSetDynamicHeadFootAttributes
        { hide = false , hidethis = false }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_ps_plain:
 {
   \def \@oddfoot { \dfOddFooterStyle { \thepage } }
   \def \@evenfoot { \dfEvenFooterStyle { \thepage } }
   \def \@oddhead { }
   \def \@evenhead { }
   \let \@mkboth \@gobbletwo
   \let \sectionmark \@gobble
   \let \subsectionmark \@gobble
 }
%    \end{macrocode}
%
%\begin{macro}{\ps@ffempty}
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ps@ffempty
 {
   \l__flowfram_ffempty_style_tl
   \bool_if:NT \l__flowfram_ps_ffempty_hides_bool
    {
      \FlowFramSetDynamicHeadFootAttributes { hide }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_ps_empty:
 {
   \def \@oddfoot { }
   \def \@evenfoot { }
   \def \@oddhead { }
   \def \@evenhead { }
   \let \@mkboth \@gobbletwo
   \let \sectionmark \@gobble
   \let \subsectionmark \@gobble
 }
%    \end{macrocode}
%
%\begin{macro}{\ps@specialffempty}
%Used with \cs{thispagestyle}:
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\newcommand \ps@specialffempty
 {
   \l__flowfram_ffempty_style_tl
   \bool_if:NT \l__flowfram_ps_ffempty_hides_bool
    {
      \FlowFramSetDynamicHeadFootAttributes { hidethis }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ps@specialempty}
%Used with \cs{thispagestyle}:
%    \begin{macrocode}
\newcommand \ps@specialempty { \ps@empty }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\footnotecolor}
%\changes{2.0}{2025-11-24}{deprecated}
%Does nothing now. Marked for removal.
%    \begin{macrocode}
\newcommand \footnotecolor { }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@makecol}
%Version 2.0 removed redefinition of \cs{@makecol}.
%\changes{2.0}{2025-11-24}{removed redefinition}
%This means that footnotes will now be the default colour rather
%than the text colour associated with the current flow frame.
%Use \cs{color} in the preamble to set the default colour.
%\end{macro}
%
%\begin{macro}{\if@ff@moreframes}
%Version 2.0 replaced legacy conditional \cs{if@ff@moreframes} with
%l3bool.
%    \begin{macrocode}
\bool_new:N \g__flowfram_more_frames_bool
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checkifmoreframes}
% Check to see if there are more \glspl{flow} defined, and
% set "\g__flowfram_more_frames_bool" as appropriate. This involves
% iterating through all \glspl{flow}, and through each 
% frame's \gls{pglist}.
% Version 2.0 renamed \cs{@ff@checkifmoreframes}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_check_if_more_frames:n
 {
  \bool_gset_false:N \g__flowfram_more_frames_bool
  \int_set:Nn \l__flowfram_col_int { #1 }
  \bool_while_do:nn
   {
     \bool_lazy_and_p:nn
      {
        \int_compare_p:nNn { \l__flowfram_col_int } < { \c@maxflow }
      }
      {
        \bool_not_p:n 
          {
            \bool_if_p:N \g__flowfram_more_frames_bool
          }
      }
   }
  {
    \int_incr:N \l__flowfram_col_int
%    \end{macrocode}
% Skip if this page is in this frame's exclusion list.
%\changes{1.14}{2012-11-10}{added check for exclusion list}
%    \begin{macrocode}
    \exp_args:Ne
    \flowfram_if_in_frame_clist:nnnnF
       { \int_eval:n { \g__flowfram_pagecounter_tl } }
       { flow } { excludelist } { \l__flowfram_col_int }
     {
%    \end{macrocode}
% This page is in this not in frame's exclusion list so now check if
% in frame's page list.
%    \begin{macrocode}
       \exp_args:Ne
       \flowfram_if_frame_has_morepages:nnnT
         { \int_eval:n { \g__flowfram_pagecounter_tl } }
         { flow } { \l__flowfram_col_int }
       {
         \bool_gset_true:N \g__flowfram_more_frames_bool
       }
%    \end{macrocode}
% If found a frame, break out of loop.
%    \begin{macrocode}
     }
  }
 \bool_if:NF \g__flowfram_more_frames_bool
  {
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
    \int_set:Nn \l__flowfram_tmpa_int
      { \g__flowfram_pagecounter_tl }
%    \end{macrocode}
% Look ahead up to a maximum of 4 pages.
%    \begin{macrocode}
    \int_zero:N \l__flowfram_tmpb_int
    \bool_do_while:nn
     {
       \int_compare_p:nNn { \l__flowfram_tmpb_int } < { 4 }
     }
    {
      \int_incr:N \l__flowfram_tmpa_int
      \int_zero:N \l__flowfram_col_int
      \bool_while_do:nn
        {
          \int_compare_p:nNn { \l__flowfram_col_int } < { \c@maxflow }
        }
       {
        \int_incr:N \l__flowfram_col_int
%    \end{macrocode}
% Skip if page is in this frame's exclusion list.
%    \begin{macrocode}
       \exp_args:NV \flowfram_if_frame_excludedpage:nnnF
          \l__flowfram_tmpa_int
          { flow } { \l__flowfram_col_int }
         {
%    \end{macrocode}
% This page is not in this frame's exclusion list.
%    \begin{macrocode}
         \exp_args:NV
         \flowfram_if_frame_has_morepages:nnnT
           \l__flowfram_tmpa_int
            { flow } { \l__flowfram_col_int }
           {
             \bool_gset_true:N \g__flowfram_more_frames_bool
           }
%    \end{macrocode}
% If found a frame, break out of loop.
%    \begin{macrocode}
          \bool_if:NT \g__flowfram_more_frames_bool
           {
             \int_set_eq:NN \l__flowfram_col_int \c@maxflow
           }
         }
       }
      \bool_if:NTF \g__flowfram_more_frames_bool
       {
         \int_set:Nn \l__flowfram_tmpb_int { 4 }
       }
       {
         \int_incr:N \l__flowfram_tmpb_int
       }
    }
  }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checkpages}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ff@checkpages}
%
% 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.
%\end{macro}
%
%\begin{macro}{\@ff@checkthispage}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ff@checkthispage}
%\end{macro}
%\begin{macro}{\@ff@checknumrange}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ff@checknumrange}.
%\end{macro}
%
%\begin{macro}{\c@ffrangenum}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{ffrangenum}.
%\end{macro}
%\begin{macro}{\@ff@getrangeless}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ff@getrangeless}.
%\end{macro}
%\begin{macro}{\@ff@getrangegreater}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ff@getrangegreater}.
%\end{macro}
%\begin{macro}{\@@ff@getrange}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ff@getrange}.
%\end{macro}
%\begin{macro}{\@@@ff@getrange}
%\changes{2.0}{2025-11-24}{removed}
%Version 2.0 removed \cs{@ff@getrange}.
%\end{macro}
%
%\begin{macro}{\@ff@output@adjustframes}
%\changes{1.14}{2012-11-10}{new}
% Provide a hook to adjust frame settings in the output routine.
% Version 2.0 renamed \cs{@ff@output@adjustframes}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\tl_new:N \g__flowfram_output_adjust_frames_tl
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffaddtoadjustframeshook}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Add stuff to the output hook.
%    \begin{macrocode}
\NewDocumentCommand \ffaddtoadjustframeshook { m }
 {
   \tl_gput_right:Nn \g__flowfram_output_adjust_frames_tl { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\if@ff@nwpg}
%Conditional to keep track of whether or not a new page is required.
%\changes{2.0}{2025-11-24}{replace}
%Version 2.0 replaced legacy conditional with l3bool.
%    \begin{macrocode}
%\newif\if@ff@nwpg
\bool_new:N \g__flowfram_new_page_bool
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\if@notthiscol}
%Version 2.0 replaced legacy conditional \cs{if@notthiscol} with
%l3bool.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\bool_new:N \g__flowfram_not_this_frame_bool
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\c@curpg}
%Keep track of current page.
%Version 2.0 renamed \cs{c@curpg}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\int_new:N \g__flowfram_current_page_int
%    \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.)
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed \cs{@g@tnextcol}.
%Get the next available column, which may be on this page or the
%next. The integer variable is the current frame index which will be
%updated. Also, "\g__flowfram_current_page_int" will be updated
%if there are no further frames available on the current page.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_get_next_column:N
 {
%    \end{macrocode}
% Do any frame adjustments:
%    \begin{macrocode}
  \g__flowfram_output_adjust_frames_tl
%    \end{macrocode}
% Now clear the hook:
%    \begin{macrocode}
  \tl_gclear:N \g__flowfram_output_adjust_frames_tl
%    \end{macrocode}
% Now check for any more frames.
%    \begin{macrocode}
  \__flowfram_check_if_more_frames:n { \c@thisframe }
  \bool_if:NF \g__flowfram_more_frames_bool
   {
%    \end{macrocode}
% No more frames, add new frame
%    \begin{macrocode}
    \msg_warning:nne { flowfram } { no-more-cols-on-page }
     { \int_eval:n { \g__flowfram_pagecounter_tl } }
    \flf@doifverbose
     {
      \tl_clear:N \l__flowfram_tmpa_tl
      \seq_map_indexed_inline:nn \g__flowfram_flowlabels_seq
       {
         \tl_put_right:Ne \l__flowfram_tmpa_tl
          {
            \exp_not:N \MessageBreak
              ##1 ( ##2 )
             Pages: ~
              \flowfram_frame_use_clist:nnn
                { flow } { pagelist } { ##1 }
             Exclusions: ~ 
              \flowfram_frame_use_clist:nnn
                { flow } { excludelist } { ##1 }
          }
       }
      \msg_info:nnV { flowfram } { info-col-list }
        \l__flowfram_tmpa_tl
     }
%    \end{macrocode}
%No flow frames available. Create a single flow frame.
%    \begin{macrocode}
    \__flowfram_one_column:n { all }
    \int_gset_eq:NN #1 \c@maxflow
   }
  \bool_gset_true:N \g__flowfram_not_this_frame_bool
  \bool_gset_false:N \g__flowfram_new_page_bool
  \int_set_eq:NN \l__flowfram_col_int #1
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \int_gset:Nn \g__flowfram_current_page_int
    { \g__flowfram_pagecounter_tl }
  \bool_while_do:Nn \g__flowfram_not_this_frame_bool
   {
    \int_compare:nNnTF 
       { \l__flowfram_col_int } = { \c@maxflow }
     {
%    \end{macrocode}
% Reached the end of the page. Try the next one.
%    \begin{macrocode}
       \int_set_eq:NN \l__flowfram_col_int \c_one_int
       \bool_gset_true:N \g__flowfram_new_page_bool
       \int_gincr:N \g__flowfram_current_page_int
     }
     {
%    \end{macrocode}
% Move on to the next flow frame on this page.
%    \begin{macrocode}
       \int_incr:N \l__flowfram_col_int
     }
    \__flowfram_check_if_this_page:nn
     { \g__flowfram_current_page_int } { \l__flowfram_col_int }
   }
  \int_gset_eq:NN #1 \l__flowfram_col_int
}
%    \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".
%Version 2.0 renamed \cs{@ff@chckifthispg}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_check_if_this_page:nn
 {
%    \end{macrocode}
% First set up some variables.
%    \begin{macrocode}
  \bool_gset_false:N \g__flowfram_not_this_frame_bool
  \flowfram_set_clist_to_frame_clist:Nnnn
   \l__flowfram_exclude_pages_clist
   { flow } { excludelist } { #2 }
%    \end{macrocode}
% Iterate over exclusion list.
%    \begin{macrocode}
  \clist_map_inline:Nn
    \l__flowfram_exclude_pages_clist
   {
     \int_compare:nNnT { ##1 } = { #1 }
      {
        \bool_gset_true:N \g__flowfram_not_this_frame_bool
        \clist_map_break:
      }
   }
  \bool_if:NF \g__flowfram_not_this_frame_bool
   {
%    \end{macrocode}
% Not in the excluded list. Now check if in the page list range.
%    \begin{macrocode}
    \bool_gset_true:N \g__flowfram_not_this_frame_bool
    \flowfram_set_clist_to_frame_clist:Nnnn
      \l__flowfram_pages_clist
      { flow } { pagelist } { #2 }
    \__flowfram_check_if_this_page:n { #1 }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@ff@chckifthispg}
% Now go ahead and check.
% Version 2.0 renamed \cs{@@ff@chckifthispg}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_check_if_this_page:n
 {
  \tl_if_eq:NNF \l__flowfram_pages_clist \c_flowfram_none_tl
   {
    \tl_if_eq:NNTF \l__flowfram_pages_clist \c_flowfram_all_tl
     {
       \bool_gset_false:N \g__flowfram_not_this_frame_bool
     }
     {
      \tl_if_eq:NNTF \l__flowfram_pages_clist \c_flowfram_odd_tl
       {
        \int_if_odd:nT { #1 }
         {
           \bool_gset_false:N \g__flowfram_not_this_frame_bool
         }
       }
       {
        \tl_if_eq:NNTF \l__flowfram_pages_clist \c_flowfram_even_tl
         {
          \int_if_even:nT { #1 }
           {
             \bool_gset_false:N \g__flowfram_not_this_frame_bool
           }
         }
         {
%    \end{macrocode}
% check through list of page numbers
%    \begin{macrocode}
          \clist_map_inline:Nn \l__flowfram_pages_clist
           {
             \flowfram_if_in_pagerange:nnT { #1 } { ##1 }
              {
                \bool_gset_false:N \g__flowfram_not_this_frame_bool
                \clist_map_break:
              }
           }
         }
       }
     }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sf@chckifthispg}
% Checks to see if \gls{static} "#1" is defined on the
% current page (or the page given by the optional argument).
%\changes{1.14}{2012-11-10}{added optional argument}
%Version 2.0 replaced \cs{@sf@chckifthispg}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_check_if_this_page:n
 {
   \__flowfram_static_check_if_this_page:nn
    { \g__flowfram_pagecounter_tl } { #1 }
 }
\cs_new:Nn \__flowfram_static_check_if_this_page:nn
 {
   \bool_gset_true:N \g__flowfram_not_this_frame_bool
   \flowfram_set_clist_to_frame_clist:Nnnn
    \l__flowfram_pages_clist
    { static } { pagelist } { #2 }
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
   \__flowfram_check_if_this_page:n { #1 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@df@chckifthispg}
% Checks to see if \gls{dynamic} "#1" is defined on the
% current page (or the page given by the optional argument).
%\changes{1.14}{2012-11-10}{added optional argument}
%Version 2.0 replaced \cs{@df@chckifthispg}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_check_if_this_page:n
 {
   \__flowfram_dynamic_check_if_this_page:nn
    { \g__flowfram_pagecounter_tl } { #1 }
 }
\cs_new:Nn \__flowfram_dynamic_check_if_this_page:nn
 {
  \bool_gset_true:N \g__flowfram_not_this_frame_bool
  \flowfram_set_clist_to_frame_clist:Nnnn
   \l__flowfram_pages_clist
   { dynamic } { pagelist } { #2 }
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \__flowfram_check_if_this_page:n { #1 }
 }
%    \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.
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed \cs{@setcolbox}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_column_box:n
 {
   \exp_args:Nne \__flowfram_message:nn
      { info-setting-col } { \int_eval:n { #1 } }
   \flowfram_frame_set_box_eq:nnnN
      { flow } { column } { #1 } \@outputbox
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\rotateframe}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \rotateframe { m m }
{
  \int_if_zero:nTF { #1 }
  { #2 }
  {
    \rotatebox { #1 } { #2 }
  }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@docolbox}
% Put \gls{flow} on the page with the correct border, if it
% has one.
%Version 2.0 renamed \cs{@docolbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_flow_box:n 
 {
  \exp_args:Nnee
  \__flowfram_message:nnn
     { info-doing-col}
     { \int_eval:n { #1 } }
     { \int_eval:n { \g__flowfram_pagecounter_tl} }
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_frametype_tl
    { flow } { frametype } { #1 }
%    \end{macrocode}
% Frame colour
%    \begin{macrocode}
   \flowfram_set_tl_to_frame_tl:Nnnn
      \l__flowfram_bordercolor_tl
      { flow } { bordercolor } { #1 }
%    \end{macrocode}
% Text colour
%    \begin{macrocode}
   \flowfram_set_tl_to_frame_tl:Nnnn
      \l__flowfram_textcolor_tl
      { flow } { textcolor } { #1 }
%    \end{macrocode}
% Background colour
%    \begin{macrocode}
   \flowfram_set_tl_to_frame_tl:Nnnn
      \l__flowfram_backcolor_tl
      { flow } { backcolor } { #1 }
%    \end{macrocode}
% Compute offset for this frame
%    \begin{macrocode}
  \__flowfram_flow_calc_offset:n {#1}%
%    \end{macrocode}
% Rotate frame if required
%    \begin{macrocode}
  \exp_args:Ne \rotateframe
   {
     \flowfram_frame_use_tl:nnn { flow } { angle } { #1 }
   }
   {
%    \end{macrocode}
% Check if frame has a border
%    \begin{macrocode}
    \flowfram_if_frame_bool:nnnTF
      { flow } { hasframe } { #1 }
    {
%    \end{macrocode}
% Put the required border around the frame
%    \begin{macrocode}
       \__flowfram_bordered_box:nnnn 
         {
          \flowfram_frame_use_dim:nnn { flow } { width } { #1 }
         }
         {
          \flowfram_frame_use_dim:nnn { flow } { height } { #1 }
         }
         {
           \flowfram_frame_use_drop_box:nnn
             { flow } { column } { #1 }
         }
         {
           \use:c { \l__flowfram_frametype_tl }
         }
    }
    {
%    \end{macrocode}
% Do the frame without a border
%    \begin{macrocode}
      \__flowfram_noborder_box:nnn 
        {
          \flowfram_frame_use_dim:nnn { flow } { width } { #1 }
        }
        {
          \flowfram_frame_use_dim:nnn { flow } { height } { #1 }
        }
        {
          \flowfram_frame_use_drop_box:nnn { flow } { column } { #1 }
        }
    }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@docolbbox}
% Do the \gls{bbox} for given \gls{flow}.
%Version 2.0 renamed \cs{@docolbbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_flow_bounding_box:n
 {
  \__flowfram_flow_calc_offset:n { #1 }
  \tl_clear:N \l__flowfram_bordercolor_tl
  \tl_clear:N \l__flowfram_textcolor_tl
  \__flowfram_do_if_draft:nn
   {
    \__flowfram_noborder_box:nnn 
      {
       \flowfram_frame_use_dim:nnn { flow } { width } { #1 }
      }
      {
       \flowfram_frame_use_dim:nnn { flow } { height } { #1 }
      }
      {
        \flowfram_frame_use_drop_box:nnn { flow } { column } { #1 }
      }
   }
   {
    \flowfram_draft_annote:nnn
     { F } { \int_eval:n { #1 } } { \getflowlabel { #1 } }
   }
 }
%    \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".
%Version 2.0 renamed \cs{@ff@fbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_bordered_box:nnnn 
 {
   \group_begin:
     \dim_set_eq:NN \fboxsep \flowframesep
     \dim_set_eq:NN \fboxrule \flowframerule
     \__flowfram_set_border_color: 
     \kern \l__flowfram_offset_dim
     #4 { \__flowfram_noborder_box:nnn { #1 } { #2 } { #3 } }
   \group_end:
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@box}
% Put the \TeX\ box "#3" of width "#1" and height "#2" on
% the page.
%Version 2.0 renamed \cs{@ff@box}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_noborder_box:nnn 
 {
   \group_begin:
    \__flowfram_background_box:n
     {
       \vbox_to_ht:nn { #2 }
        {
          \hbox_to_wd:nn { #1 }
            { \hss { \__flowfram_set_text_color: #3 } \hss }
          \vss
          \kern\z@
        }
     }
   \group_end:
 }
%    \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.
% Version 2.0 renamed \cs{@putcolbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_put_flow_box:n
 {
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \__flowfram_check_if_this_page:nn
   { \g__flowfram_pagecounter_tl } { #1 }
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{added check for non-void box}
%    \begin{macrocode}
  \bool_if:NT \g__flowfram_not_this_frame_bool
   {
    \flowfram_frame_if_box_empty:nnnF
      { flow } { column } { #1 }
     {
       \msg_warning:nneeee
         { flowfram } { non-void-box }
         { \int_eval:n { #1 } }
         { \int_use:N \g__flowfram_pagecounter_tl }
         { \flowfram_frame_use_clist:nnn { flow } { pagelist } { #1 } }
         { \flowfram_frame_use_clist:nnn { flow } { excludelist } { #1 } }
       \bool_gset_false:N \g__flowfram_not_this_frame_bool
     }
   }
  \bool_if:NTF \g__flowfram_not_this_frame_bool
   {
     \exp_args:Nnee
     \__flowfram_message:nnn
       { info-col-not-required }
       { \int_eval:n { #1 } }
       { \int_eval:n { \g__flowfram_pagecounter_tl } }
   }
   {
    \@killglue
    \legacy_if:nTF { @twoside }
     {
      \int_if_odd:nTF { \c@page }
       {
        \box_move_up:nn
          {
            \flowfram_frame_use_dim:nnn { flow } { posy } { #1 }
          }
          {
            \hbox_to_zero:n
             {
               \kern
                 \flowfram_frame_use_dim:nnn { flow } { posx } { #1 }
               \__flowfram_do_flow_box:n { #1 }
               \hss
             }
          }
       }
       {
        \box_move_up:nn
          {
            \flowfram_frame_use_dim:nnn { flow } { eveny } { #1 }
          }
          {
            \hbox_to_zero:n
             {
              \kern
                \flowfram_frame_use_dim:nnn { flow } { evenx } { #1 }
              \__flowfram_do_flow_box:n { #1 }
              \hss
             }
          }
       }
     }
     {
      \box_move_up:nn
        {
          \flowfram_frame_use_dim:nnn { flow } { posy } { #1 }
        }
        {
          \hbox_to_zero:n
           {
            \kern
              \flowfram_frame_use_dim:nnn { flow } { posx } { #1 }
            \__flowfram_do_flow_box:n { #1 }
            \hss
           }
        }
     }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putcolbbox}
% Same for \gls{flow} \gls{bbox}:
%Version 2.0 renamed \cs{@putcolbbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_put_flow_bounding_box:n
 {
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with \cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \__flowfram_check_if_this_page:nn
    { \g__flowfram_pagecounter_tl } { #1 }
  \bool_if:NF \g__flowfram_not_this_frame_bool
   {
    \@killglue
    \legacy_if:nTF { @twoside }
     {
      \int_if_odd:nTF { \c@page }
       {
         \box_move_up:nn
           {
             \flowfram_frame_use_dim:nnn { flow } { posy } { #1 }
           }
           {
             \hbox_to_zero:n
             {
               \kern
                 \flowfram_frame_use_dim:nnn { flow } { posx } { #1 }
               \__flowfram_do_flow_bounding_box:n { #1 }
               \hss
             }
           }
       }
       {
        \box_move_up:nn
         {
           \flowfram_frame_use_dim:nnn { flow } { eveny } { #1 }
         }
         {
           \hbox_to_zero:n
            {
              \kern
                \flowfram_frame_use_dim:nnn { flow } { evenx } { #1 }
              \__flowfram_do_flow_bounding_box:n {#1}
              \hss
            }
         }
       }
     }
     {
       \box_move_up:nn
        {
          \flowfram_frame_use_dim:nnn { flow } { posy } { #1 }
        }
        {
          \hbox_to_zero:n
           {
            \kern
              \flowfram_frame_use_dim:nnn { flow } { posx } { #1 }
            \__flowfram_do_flow_bounding_box:n {#1}
            \hss
           }
        }
     }
   }
 }
%    \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".
%Version 2.0 renamed \cs{ff@s@t@doubleboxoffset}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_doublebox_offset:
 {
   \dim_set:Nn \l__flowfram_offset_dim
    {
       - \flowframesep
       -3.75 \flowframerule
       - 0.5pt
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@s@t@ovalboxoffset}
% Compute offset for "\ovalbox".
%Version 2.0 renamed \cs{ff@s@t@ovalboxoffset}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_ovalbox_offset:
 {
   \dim_set:Nn \l__flowfram_offset_dim
    {
      - \flowframesep
      - \fontdimen 8 \tenln
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@s@t@Ovalboxoffset}
% Compute offset for "\Ovalbox":
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed \cs{ff@s@t@Ovalboxoffset}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_Ovalbox_offset:
 {
   \dim_set:Nn \l__flowfram_offset_dim
    {
      - \flowframesep
      - \fontdimen 8 \tenlnw
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@s@t@defaultoffset}
% Compute default offset:
%\changes{2.0}{2025-11-24}{renamed}
%Version 2.0 renamed \cs{ff@s@t@defaultoffset}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_default_offset:
 {
   \dim_set:Nn \l__flowfram_offset_dim
    {
      - \flowframesep
      - \flowframerule
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@setoffset}
% Compute offset for \gls{flow} "#1". Stores offset value
% in "\l__flowfram_offset_tl".
% Version 2.0 renamed \cs{@ff@setoffset}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_calc_offset:n 
{
  \flowfram_if_tl_eq_frame_tl:NnnnTF
    \c_flowfram_compute_tl
    { flow } { offset } { #1 }
   {
     \flowfram_if_frame_bool:nnnTF { flow } { hasframe } { #1 }
      {
        \flowfram_set_tl_to_frame_tl:Nnnn
           \l__flowfram_frametype_tl
           { flow } { frametype } { #1 }
        \cs_if_exist_use:cF
          { __flowfram_set_ \l__flowfram_frametype_tl  _offset: }
          {
            \__flowfram_set_default_offset:
          }
      }
      {
        \dim_zero:N \l__flowfram_offset_dim
      }
   }
   {
     \flowfram_set_dim_to_frame_tl:Nnnn
      \l__flowfram_offset_dim
      { flow } { offset } { #1 }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sf@setoffset}
% Compute offset for \gls{static} "#1". Stores offset value
% in "\l__flowfram_offset_tl".
% Version 2.0 renamed \cs{@sf@setoffset}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_calc_offset:n
 {
  \flowfram_if_tl_eq_frame_tl:NnnnTF
    \c_flowfram_compute_tl
    { static } { offset } { #1 }
  {
    \flowfram_if_frame_bool:nnnTF { static } { hasframe } { #1 }
    {
      \flowfram_set_tl_to_frame_tl:Nnnn
          \l__flowfram_frametype_tl
          { static } { frametype } { #1 }
      \cs_if_exist_use:cF
       { __flowfram_set_ \l__flowfram_frametype_tl  _offset: }
       {
         \__flowfram_set_default_offset:
       }
    }
    {
      \dim_zero:N \l__flowfram_offset_dim
    }
  }
  {
    \flowfram_set_dim_to_frame_tl:Nnnn
     \l__flowfram_offset_dim
     { static } { offset } { #1 }
  }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@df@setoffset}
% Compute offset for \gls{dynamic} "#1". Stores offset value
% in "\l__flowfram_offset_tl".
% Version 2.0 renamed \cs{@sf@setoffset}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_calc_offset:n
 {
  \flowfram_if_tl_eq_frame_tl:NnnnTF
    \c_flowfram_compute_tl
    { dynamic } { offset } { #1 }
  {
    \flowfram_if_frame_bool:nnnTF { dynamic } { hasframe } { #1 }
    {
      \flowfram_set_tl_to_frame_tl:Nnnn
          \l__flowfram_frametype_tl
          { dynamic } { frametype } { #1 }
      \cs_if_exist_use:cF
       { __flowfram_set_ \l__flowfram_frametype_tl  _offset: }
       {
         \__flowfram_set_default_offset:
       }
    }
    {
      \dim_zero:N \l__flowfram_offset_dim
    }
  }
  {
    \flowfram_set_dim_to_frame_tl:Nnnn
     \l__flowfram_offset_dim
     { dynamic } { offset } { #1 }
  }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putmarginbox}
% Draw box representing the margin for \gls{flow} "#1".
%Version 2.0 renamed \cs{@putmarginbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowframe_put_margin_box:n 
{
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \__flowfram_check_if_this_page:nn
    { \g__flowfram_pagecounter_tl } { #1 }
  \bool_if:NF \g__flowfram_not_this_frame_bool
   {
    \@killglue
    \legacy_if:nTF { @twoside }
     {
      \int_if_odd:nTF { \c@page }
       {
         \flowfram_set_dim_to_frame_dim:Nnnn
            \l__flowfram_x_dim
            { flow } { posx } { #1 }
         \flowfram_set_dim_to_frame_dim:Nnnn
            \l__flowfram_y_dim
            { flow } { posy } { #1 }
       }
       {
         \flowfram_set_dim_to_frame_dim:Nnnn
            \l__flowfram_x_dim
            { flow } { evenx } { #1 }
         \flowfram_set_dim_to_frame_dim:Nnnn
            \l__flowfram_y_dim
            { flow } { eveny } { #1 }
       }
     }
     {
       \flowfram_set_dim_to_frame_dim:Nnnn
          \l__flowfram_x_dim
          { flow } { posx } { #1 }
       \flowfram_set_dim_to_frame_dim:Nnnn
          \l__flowfram_y_dim
          { flow } { posy } { #1 }
     }
    \__flowfram_get_margin_pos:e
     {
       \flowfram_frame_use_tl:nnn { flow } { margin } { #1 }
     }
    \tl_if_eq:NNTF \l__flowfram_margin_tl \c_flowfram_left_tl
    {
      \dim_add:Nn \l__flowfram_x_dim
        {
           - \marginparwidth
           - \marginparsep
        }
    }
    {
      \dim_add:Nn \l__flowfram_x_dim 
       {
          \flowfram_frame_use_dim:nnn { flow } { width } { #1 }
          + \marginparsep
       }
    }
    \box_move_up:nn { \l__flowfram_y_dim  }
     {
       \hbox_to_zero:n 
       {
         \kern \l__flowfram_x_dim 
         \__flowfram_do_if_draft:nn
          {
            \__flowfram_noborder_box:nnn { \marginparwidth }
             {
               \flowfram_frame_use_dim:nnn { flow } { height } { #1 }
             }
             { }
          }
          {
            \flowfram_draft_annote:nn { M } { \int_eval:n { #1 } }
          }
          \hss
       }
     }
   }
  \ignorespaces
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@drawmargins}
% Draw all the margins associated with the \glspl{flow} defined
% on the current page.
%Version 2.0 renamed \cs{@ff@drawmargins}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_draw_margins:
 {
   \int_step_inline:nn { \c@maxflow }
    {
      \makebox [ \c_zero_dim ] [ l ]
       {
         \__flowframe_put_margin_box:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@getstaticpos}
%Version 2.0 removed \cs{@ff@getstaticpos}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@dostaticbox}
% Display the savebox associated with \gls{static} "#1"
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_static_box:n
 {
  \int_set:Nn \l__flowfram_current_static_int { #1 }
%    \end{macrocode}
%Get the frame border type.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_frametype_tl
    { static } { frametype } { #1 }
%    \end{macrocode}
%Get the frame border colour.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_bordercolor_tl
    { static } { bordercolor } { #1 }
%    \end{macrocode}
%Note that it's too late to apply the text colour as that's set when
%the contents are set.
%Get the background colour.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_backcolor_tl
    { static } { backcolor } { #1 }
%    \end{macrocode}
%Calculate the offset to take into account the border.
%    \begin{macrocode}
  \__flowfram_static_calc_offset:n {#1}%
%    \end{macrocode}
%Rotate the frame by the designated angle.
%    \begin{macrocode}
  \exp_args:Ne \rotateframe
    {
     \flowfram_frame_use_tl:nnn { static } { angle } { #1 }
    }
    {
       \flowfram_if_frame_bool:nnnTF
        { static } { hasframe } { #1 }
       {
          \__flowfram_bordered_box:nnnn
           {
              \flowfram_frame_use_dim:nnn { static } { width } { #1 }
           }
           {
             \flowfram_frame_use_dim:nnn { static } { height } { #1 }
           }
           {
             \flowfram_frame_use_box:nnn
              { static } { content } { #1 }
           }
           {
             \use:c { \l__flowfram_frametype_tl }
           }
       }
       {
        \__flowfram_noborder_box:nnn
         {
            \flowfram_frame_use_dim:nnn { static } { width } { #1 }
         }
         {
           \flowfram_frame_use_dim:nnn { static } { height } { #1 }
         }
         {
           \flowfram_frame_use_box:nnn
            { static } { content } { #1 }
         }
       }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dostaticbbox}
% Now for the \gls{bbox}:
% Version 2.0 renamed \cs{@dostaticbbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_static_bounding_box:n
 {
  \tl_clear:N \l__flowfram_bordercolor_tl
  \__flowfram_static_calc_offset:n { #1 }
  \__flowfram_do_if_draft:nn
   {
     \__flowfram_noborder_box:nnn
      {
        \flowfram_frame_use_dim:nnn { static } { width } { #1 }
      }
      {
        \flowfram_frame_use_dim:nnn { static } { height } { #1 }
      }
      {
        \flowfram_frame_use_box:nnn
          { static } { content } { #1 }
      }
   }
   {
     \flowfram_draft_annote:nnn
      { S } { \int_eval:n { #1 } }
      {
        \flowfram_frame_use_tl:nnn { static } { label } { #1 }
      }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putstaticbox}
% Put the static box "#1" at its given position, with its
% associated border.
% Version 2.0 renamed \cs{@putstaticbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_put_static_box:n
 {
%    \end{macrocode}
%\changes{2014-06-04}{1.16}{added check for `hide' and `hidethis'
%attributes}
% Check the `hide' and `hidethis' attributes
%    \begin{macrocode}
  \flowfram_if_frame_bool:nnnTF
    { static } { hidethis } { #1 }
   {
     \__flowfram_message:nen
       { info-static-frame-hidden } { \int_eval:n { #1 } } { hidethis }
     \bool_gset_true:N \g__flowfram_not_this_frame_bool
     \flowfram_frame_set_bool_false:nnn
       { static } { hidethis } { #1 }
   }
   {
     \flowfram_if_frame_bool:nnnTF
       { static } { hide } { #1 }
      {
        \__flowfram_message:nen
          { info-static-frame-hidden } { \int_eval:n { #1 } } { hide }
        \bool_gset_true:N \g__flowfram_not_this_frame_bool
      }
      {
%    \end{macrocode}
% Neither `hide' nor `hidethis' have been set so check the page
% list.
%    \begin{macrocode}
        \__flowfram_static_check_if_this_page:n { #1 }
      }
   }
  \bool_if:NF \g__flowfram_not_this_frame_bool
   {
    \@killglue
    \legacy_if:nTF { @twoside }
     {
      \int_if_odd:nTF { \c@page }
       {
        \box_move_up:nn
         {
           \flowfram_frame_use_dim:nnn { static } { posy } { #1 }
         }
         {
           \hbox_to_zero:n 
            {
              \kern 
                \flowfram_frame_use_dim:nnn { static } { posx } { #1 }
              \__flowfram_do_static_box:n { #1 }
              \hss
            }
         }
       }
       {
        \box_move_up:nn
         {
           \flowfram_frame_use_dim:nnn { static } { eveny } { #1 }
         }
         {
           \hbox_to_zero:n 
            {
              \kern
                \flowfram_frame_use_dim:nnn { static } { evenx } { #1 }
              \__flowfram_do_static_box:n { #1 }
              \hss
            }
         }
       }
     }
     {
      \box_move_up:nn
        {
          \flowfram_frame_use_dim:nnn { static } { posy } { #1 }
        }
        {
          \hbox_to_zero:n 
           {
             \kern
               \flowfram_frame_use_dim:nnn { static } { posx } { #1 }
             \__flowfram_do_static_box:n { #1 }
             \hss
           }
        }
     }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putstaticbbox}
% Now for the \gls{bbox}:
% Version 2.0 renamed \cs{@putstaticbbox}
%\changes{2.0}{2025-11-24}{removed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_put_static_bounding_box:n
{
  \flowfram_if_frame_bool:nnnTF
    { static } { hidethis } { #1 }
   {
     \bool_gset_true:N \g__flowfram_not_this_frame_bool
     \flowfram_frame_set_bool_false:nnn
       { static } { hidethis } { #1 }
   }
   {
     \flowfram_if_frame_bool:nnnTF
       { static } { hide } { #1 }
      {
        \bool_gset_true:N \g__flowfram_not_this_frame_bool
      }
      {
%    \end{macrocode}
% Neither `hide' nor `hidethis' have been set so check the page
% list.
%    \begin{macrocode}
        \__flowfram_static_check_if_this_page:n { #1 }
      }
   }
  \bool_if:NF \g__flowfram_not_this_frame_bool
   {
    \@killglue
    \legacy_if:nTF { @twoside }
     {
      \int_if_odd:nTF { \c@page }
       {
        \box_move_up:nn
          {
            \flowfram_frame_use_dim:nnn { static } { posy } { #1 }
          }
          {
            \hbox_to_zero:n
             {
              \kern
                 \flowfram_frame_use_dim:nnn { static } { posx } { #1 }
              \__flowfram_do_static_bounding_box:n { #1 }
              \hss
             }
          }
       }
       {
         \box_move_up:nn
          {
            \flowfram_frame_use_dim:nnn { static } { eveny } { #1 }
          }
          {
            \hbox_to_zero:n 
             {
               \kern
                 \flowfram_frame_use_dim:nnn { static } { evenx } { #1 }
               \__flowfram_do_static_bounding_box:n { #1 }
               \hss
             }
          }
       }
     }
     {
      \box_move_up:nn
       {
         \flowfram_frame_use_dim:nnn { static } { posy } { #1 }
       }
       {
         \hbox_to_zero:n 
          {
            \kern
             \flowfram_frame_use_dim:nnn { static } { posx } { #1 }
            \__flowfram_do_static_bounding_box:n { #1 }
            \hss
          }
       }
     }
    \ignorespaces
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@resetst@tics}
% Clear the contents of all the \glspl{static} that have
% the "clear" option set.
% Version 2.0 renamed \cs{@resetst@tics}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_reset_statics:
 {
   \int_step_inline:nn { \c@maxstatic }
    {
%    \end{macrocode}
% Has the clear flag been set?
%    \begin{macrocode}
      \flowfram_if_frame_bool:nnnT
         { static } { clear } { ##1 }
       {
%    \end{macrocode}
% Set the contents of the box to empty
%    \begin{macrocode}
          \flowfram_frame_clear_box:nnn
           { static } { content } { ##1 }
       }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@resetdyn@mics}
% Clear the contents of the \glspl{dynamic} that have the "clear" option
% set.
% Version 2.0 renamed \cs{@resetdyn@mics}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_reset_dynamics:
 {
   \int_step_inline:nn { \c@maxdynamic }
    {
%    \end{macrocode}
% Has the clear flag been set?
%    \begin{macrocode}
      \flowfram_if_frame_bool:nnnT
         { dynamic } { clear } { ##1 }
       {
%    \end{macrocode}
% Clear the contents.
%    \begin{macrocode}
          \flowfram_frame_clear_tl:nnn
           { dynamic } { content } { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%Dynamic frame content is now put inside a \env{minipage} instead of
%a \cs{parbox} (\cs{shapepar} has problems in a \cs{parbox}).
%    \begin{macrocode}
\cs_new:Nn \__flowfram_parbox:nnnn
 {
   \begin { minipage }  [ c ] [ #1 ] [ #2 ] { #3 }
   #4 
   \end { minipage }
 }
\cs_generate_variant:Nn \__flowfram_parbox:nnnn { eeen }
%    \end{macrocode}
%\begin{macro}{\@dodfparbox}
% Display contents of dynamic box (contents stored in
% "\l__flowfram_contents_tl ", style given by "\l__flowfram_style_tl"):
% Version 2.0 renamed \cs{@dodfparbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_dynamic_content:n
 {
   \flowfram_set_tl_to_frame_tl:Nnnn
     \l__flowfram_parindent_tl
     { dynamic } { parindent } { #1 }
   \flowfram_set_tl_to_frame_tl:Nnnn
     \l__flowfram_parshape_tl
     { dynamic } { shape } { #1 }
   \__flowfram_get_shape:V \l__flowfram_parshape_tl
  \int_case:nnF { \l__flowfram_shape_int }
   {
      { \c_flowfram_shape_type_parshape_int }
       {
%    \end{macrocode}
% \cs{parshape}
%    \begin{macrocode}
          \__flowfram_parbox:eeen
           {
             \dynamicframeheight { #1 }
           }
           {
             \flowfram_frame_use_tl:nnn
              { dynamic } { valign } { #1 }
           }
           {
             \dynamicframewidth { #1 }
           }
          {
            \dim_set:Nn \parindent { \l__flowfram_parindent_tl }
            \use:c { \l__flowfram_style_tl }
              {
                 \__flowfram_set_shaped_section_headings: 
                 \let \par \FLFsimpar
                 \l__flowfram_parshape_tl
                 \l__flowfram_contents_tl 
                 \endgraf
              }
          }
       }
      { \c_flowfram_shape_type_shapepar_int }
        {
%    \end{macrocode}
% \cs{shapepar} or \cs{Shapepar}
%    \begin{macrocode}
          \__flowfram_parbox:eeen
           {
             \dynamicframeheight { #1 }
           }
           {
             \flowfram_frame_use_tl:nnn
              { dynamic } { valign } { #1 }
           }
           {
             \dynamicframewidth { #1 }
           }
           {
             \dim_set:Nn \parindent { \l__flowfram_parindent_tl }
             \use:c { \l__flowfram_style_tl }
             {
               \@ff@disablesec
               \let \par \FLFsimpar
               \l__flowfram_parshape_tl
               \l__flowfram_contents_tl
               \endgraf
             }
           }
        }
   }
   {
%    \end{macrocode}
% no shape
%    \begin{macrocode}
      \__flowfram_parbox:eeen
       {
         \dynamicframeheight { #1 }
       }
       {
         \flowfram_frame_use_tl:nnn
          { dynamic } { valign } { #1 }
       }
       {
         \dynamicframewidth { #1 }
       }
       {
         \dim_set:Nn \parindent { \l__flowfram_parindent_tl }
         \use:c { \l__flowfram_style_tl }
%    \end{macrocode}
%This will be picked up as an argument if the style is a text-block
%command but won't add extra grouping otherwise:
%    \begin{macrocode}
             \l__flowfram_contents_tl 
       }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dodynamicbox}
% Typeset the dynamic box with its associated border.
% Version 2.0 renamed \cs{@dodynamicbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_dynamic_box:n
 {
  \int_set:Nn \l__flowfram_current_dynamic_int { #1 }
%    \end{macrocode}
%Get the frame border type.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_frametype_tl
    { dynamic } { frametype } { #1 }
%    \end{macrocode}
%Get the frame border colour.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_bordercolor_tl
    { dynamic } { bordercolor } { #1 }
%    \end{macrocode}
%Get the text colour.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_textcolor_tl
    { dynamic } { textcolor } { #1 }
%    \end{macrocode}
%Get the background colour.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_backcolor_tl
    { dynamic } { backcolor } { #1 }
%    \end{macrocode}
%Get the style (csname to apply to the content).
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_style_tl
    { dynamic } { style } { #1 }
%    \end{macrocode}
%Get the content.
%    \begin{macrocode}
  \flowfram_set_tl_to_frame_tl:Nnnn
    \l__flowfram_contents_tl
    { dynamic } { content } { #1 }
%    \end{macrocode}
%Calculate the offset to take into account the border.
%    \begin{macrocode}
  \__flowfram_dynamic_calc_offset:n {#1}%
  \exp_args:Ne \rotateframe
    {
      \flowfram_frame_use_tl:nnn { dynamic } { angle } { #1 }
    }
    {
       \flowfram_if_frame_bool:nnnTF
        { dynamic } { hasframe } { #1 }
       {
          \__flowfram_bordered_box:nnnn
           {
              \flowfram_frame_use_dim:nnn { dynamic } { width } { #1 }
           }
           {
              \flowfram_frame_use_dim:nnn { dynamic } { height } { #1 }
           }
           {
              \__flowfram_do_dynamic_content:n { #1 }
           }
           {
             \use:c { \l__flowfram_frametype_tl }
           }
       }
       {
         \__flowfram_noborder_box:nnn
          {
             \flowfram_frame_use_dim:nnn { dynamic } { width } { #1 }
          }
          {
             \flowfram_frame_use_dim:nnn { dynamic } { height } { #1 }
          }
          {
             \__flowfram_do_dynamic_content:n { #1 }
          }
       }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dodynamicbbox}
% Now for the \gls{bbox}.
% Version 2.0 renamed \cs{@dodynamicbbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_dynamic_bounding_box:n
 {
   \tl_clear:N \l__flowfram_bordercolor_tl
%    \end{macrocode}
%Calculate the offset to take into account the border.
%    \begin{macrocode}
   \__flowfram_dynamic_calc_offset:n { #1 }
   \__flowfram_do_if_draft:nn
     {
       \__flowfram_noborder_box:nnn
        {
           \flowfram_frame_use_dim:nnn { dynamic } { width } { #1 }
        }
        {
           \flowfram_frame_use_dim:nnn { dynamic } { height } { #1 }
        }
        {
          \__flowfram_parbox:eeen
           {
             \dynamicframeheight { #1 }
           }
           {
             \flowfram_frame_use_tl:nnn
              { dynamic } { valign } { #1 }
           }
           {
             \dynamicframewidth { #1 }
           }
           { }
        }
    }
    {
      \flowfram_draft_annote:nnn
       { D } { \int_eval:n { #1 } }
       {
         \flowfram_frame_use_tl:nnn { dynamic } { label } { #1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@putdynamicbox}
% Put the \gls{dynamic} "#1" at its given position.
% Version 2.0 renamed \cs{@putdynamicbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_put_dynamic_box:n
 {
%    \end{macrocode}
%\changes{2014-06-04}{1.16}{added check for `hide' and `hidethis'
%attributes}
% Check the `hide' and `hidethis' attributes
%    \begin{macrocode}
  \flowfram_if_frame_bool:nnnTF
    { dynamic } { hidethis } { #1 }
   {
     \__flowfram_message:nen
       { info-dynamic-frame-hidden } { \int_eval:n { #1 } } { hidethis }
     \bool_gset_true:N \g__flowfram_not_this_frame_bool
     \flowfram_frame_set_bool_false:nnn
       { dynamic } { hidethis } { #1 }
   }
   {
     \flowfram_if_frame_bool:nnnTF
       { dynamic } { hide } { #1 }
      {
        \__flowfram_message:nen
          { info-dynamic-frame-hidden } { \int_eval:n { #1 } } { hide }
        \bool_gset_true:N \g__flowfram_not_this_frame_bool
      }
      {
%    \end{macrocode}
% Neither `hide' nor `hidethis' have been set so check the page
% list.
%    \begin{macrocode}
        \__flowfram_dynamic_check_if_this_page:n { #1 }
      }
   }
  \bool_if:NF \g__flowfram_not_this_frame_bool
   {
    \@killglue
    \legacy_if:nTF { @twoside }
     {
      \int_if_odd:nTF { \c@page }
       {
         \box_move_up:nn
          {
            \flowfram_frame_use_dim:nnn { dynamic } { posy } { #1 }
          }
          {
            \hbox_to_zero:n 
             {
               \kern
                \flowfram_frame_use_dim:nnn { dynamic } { posx } { #1 }
               \__flowfram_do_dynamic_box:n { #1 }
               \hss
             }
          }
       }
       {
        \box_move_up:nn
         {
           \flowfram_frame_use_dim:nnn { dynamic } { eveny } { #1 }
         }
         {
           \hbox_to_zero:n 
            {
              \kern
               \flowfram_frame_use_dim:nnn { dynamic } { evenx } { #1 }
              \__flowfram_do_dynamic_box:n { #1 }
              \hss
            }
         }
       }
     }
     {
      \box_move_up:nn
       {
         \flowfram_frame_use_dim:nnn { dynamic } { posy } { #1 }
       }
       {
         \hbox_to_zero:n
          {
            \kern
              \flowfram_frame_use_dim:nnn { dynamic } { posx } { #1 }
            \__flowfram_do_dynamic_box:n { #1 }
            \hss
          }
       }
     }
    \ignorespaces
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@putdynamicbbox}
% Bounding box.
% Version 2.0 renamed \cs{@putdynamicbbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_put_dynamic_bounding_box:n
 {
  \flowfram_if_frame_bool:nnnTF
    { dynamic } { hidethis } { #1 }
   {
     \bool_gset_true:N \g__flowfram_not_this_frame_bool
     \flowfram_frame_set_bool_false:nnn
       { dynamic } { hidethis } { #1 }
   }
   {
     \flowfram_if_frame_bool:nnnTF
       { dynamic } { hide } { #1 }
      {
        \bool_gset_true:N \g__flowfram_not_this_frame_bool
      }
      {
%    \end{macrocode}
% Neither `hide' nor `hidethis' have been set so check the page
% list.
%    \begin{macrocode}
        \__flowfram_dynamic_check_if_this_page:n { #1 }
      }
   }
  \bool_if:NF \g__flowfram_not_this_frame_bool
   {
    \@killglue
    \legacy_if:nTF { @twoside }
     {
      \int_if_odd:nTF { \c@page }
       {
        \box_move_up:nn
         {
           \flowfram_frame_use_dim:nnn { dynamic } { posy } { #1 }
         }
         {
           \hbox_to_zero:n
            {
              \kern
                \flowfram_frame_use_dim:nnn { dynamic } { posx } { #1 }
              \__flowfram_do_dynamic_bounding_box:n { #1 }
              \hss
            }
         }
       }
       {
        \box_move_up:nn
         {
           \flowfram_frame_use_dim:nnn { dynamic } { eveny } { #1 }
         }
         {
           \hbox_to_zero:n
            {
              \kern
                \flowfram_frame_use_dim:nnn { dynamic } { evenx } { #1 }
              \__flowfram_do_dynamic_bounding_box:n { #1 }
              \hss
            }
         }
       }
     }
     {
      \box_move_up:nn
       {
         \flowfram_frame_use_dim:nnn { dynamic } { posy } { #1 }
       }
       {
         \hbox_to_zero:n
          {
            \kern
              \flowfram_frame_use_dim:nnn { dynamic } { posx } { #1 }
            \__flowfram_do_dynamic_bounding_box:n { #1 }
            \hss
          }
       }
     }
    \ignorespaces
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@doheader}
% Do standard header in the standard place.
% Version 2.0 renamed \cs{@@doheader}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_standard_header:
 {
   \box_move_up:nn
     { 
       \typeblockheight + \headsep
     }
     {
       \vbox_to_ht:nn { \headheight }
        {
          \hbox_to_zero:n
           {
             \@dothehead \hss
           }
          \vss
        }
     }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@dofooter}
% Do standard footer in the standard place.
% Version 2.0 renamed \cs{@@dofooter}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_standard_footer:
 {
   \box_move_down:nn
     { \footskip }
     {
       \hbox_to_zero:n
        {
          \@dothefoot \hss
        }
     }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@s@tfr@mes}
% Version 2.0 renamed \cs{@s@tfr@mes}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\box_new:N \l__all_content_box
\dim_new:N \l__all_content_height_dim
\cs_new:Nn \__flowfram_set_frames:n
 {
   \group_begin:
     \dim_set_eq:NN \l__all_content_height_dim \typeblockheight
     \setbox
        \l__all_content_box
        \hbox_to_wd:nn
          { \typeblockwidth }
          {
            \hbox:n { #1 }
            \hss
          } 
     \ht \l__all_content_box
         \l__all_content_height_dim
     \dp \l__all_content_box \c_zero_dim
     \mbox
      {
        \box_use_drop:N \l__all_content_box
      }
   \group_end:
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doallflowframes}
% Puts all the \glspl{flow} defined on the current page.
% Version 2.0 renamed \cs{@ff@doallflowframes}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_all_flow_frames:
 {
   \int_step_function:nN { \c@maxflow }
      \__flowfram_put_flow_box:n
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@doallflowframesbbox}
% Flow frame \glspl{bbox}.
% Version 2.0 renamed \cs{@ff@doallflowframesbbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_all_flow_bounding_boxes:
 {
   \int_step_function:nN { \c@maxflow }
     \__flowfram_put_flow_bounding_box:n
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doallstatics}
% Puts all \glspl{static} defined on the current page.
% Version 2.0 renamed \cs{@ff@doallstatics}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_all_static_frames:
 {
   \int_step_function:nN { \c@maxstatic }
    \__flowfram_put_static_box:n
   \int_zero:N \l__flowfram_current_static_int
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@doallstaticsbbox}
% Static frame \glspl{bbox}.
% Version 2.0 renamed \cs{@ff@doallstaticsbbox}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_all_static_bounding_boxes:
 {
   \int_step_function:nN { \c@maxstatic }
    \__flowfram_put_static_bounding_box:n
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doalldynamics}
% Puts all the \glspl{dynamic} defined on the current page.
% Version 2.0 renamed \cs{@ff@doalldynamics}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_all_dynamic_frames:
 {
   \int_step_function:nN { \c@maxdynamic }
    \__flowfram_put_dynamic_box:n
   \int_zero:N \l__flowfram_current_dynamic_int
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@doalldynamicsbbox}
% Dynamic frame \glspl{bbox}.
% Version 2.0 renamed \cs{@ff@doalldynamicsbbox}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_all_dynamic_bounding_boxes:
 {
   \int_step_function:nN { \c@maxdynamic }
    \__flowfram_put_dynamic_bounding_box:n
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@dotypeblock}
% Draw \gls{typeblock} frame if draft.
% Version 2.0 renamed \cs{@ff@dotypeblock}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_typeblock:
 {
  \makebox [ \c_zero_dim ] [ l ]
   {
     \__flowfram_do_if_draft:nnn
      { \setffdrafttypeblockcolor }
      {
        \vbox_to_ht:nn { \typeblockheight }
         {
           \hbox_to_wd:nn \typeblockwidth { }
         }
      }
      { }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffevenoffset}
% Version 2.0 removed \cs{ffevenoffset}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@ff@do@allframes}
% Put all frames defined on the current page.
% Version 2.0 renamed \cs{@ff@do@allframes}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_do_all_frames:
 {
   \hbox_to_wd:nn { \typeblockwidth }
    {
      \__flowfram_set_frames:n 
       {
         \__flowfram_do_all_static_frames: 
         \__flowfram_do_standard_header: 
         \__flowfram_do_standard_footer: 
         \__flowfram_do_all_flow_frames: 
         \__flowfram_do_all_dynamic_frames: 
         \ifshowtypeblock
           \__flowfram_do_typeblock: 
         \fi
         \ifshowframebbox
           \__flowfram_do_all_static_bounding_boxes: 
           \__flowfram_do_all_flow_bounding_boxes: 
           \__flowfram_do_all_dynamic_bounding_boxes: 
         \fi
         \ifshowmargins
           \__flowfram_draw_margins: 
         \fi
       }
      \hss
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@outputdblcol}
% This was modified from the output routine for standard
% two column format. After "\__flowfram_get_next_column:N" has
% finished, the register  "\g__flowfram_current_page_int"
% contains the page that the next \gls{flow}
% is on. If "\g__flowfram_current_page_int" 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}
\int_new:N \g__flowfram_next_frame_int
\renewcommand*\@outputdblcol
 {
   \__flowfram_output_dbl_col:
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_output_dbl_col:
 {
  \int_gset_eq:NN \g__flowfram_next_frame_int \c@thisframe
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \int_gset:Nn \g__flowfram_current_page_int
     { \g__flowfram_pagecounter_tl }
  \__flowfram_get_next_column:N \g__flowfram_next_frame_int 
  \bool_if:NTF \g__flowfram_new_page_bool
   {
%    \end{macrocode}
% Next flow frame starts on new page.
%    \begin{macrocode}
    \global \@firstcolumntrue
    \__flowfram_set_column_box:n { \c@thisframe }
    \legacy_if:nT { @specialpage }
     {
      \global \@specialpagefalse
      \@nameuse { ps@ \@specialstyle }
      \relax
     }
    \@dodynamicthehead
    \@dodynamicthefoot
    \vbadness=\@M
    \setbox \@outputbox
       \vbox_to_ht:nn { \typeblockheight }
         {
           \__flowfram_do_all_frames: 
         }
    \@combinedblfloats
    \@outputpage
%    \end{macrocode}
% Shipout pages without flow frames. Any static or dynamic frames on
% those pages should be included.
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
    \int_gadd:Nn \g__flowfram_current_page_int
      { - \g__flowfram_pagecounter_tl }
    \bool_while_do:nn
     {
       \int_compare_p:nNn
          { \g__flowfram_current_page_int } > { \c_zero_int }
     }
    {
      \int_gdecr:N \g__flowfram_current_page_int 
      \setbox \@outputbox
       \vbox_to_ht:nn { \typeblockheight }
         {
           \__flowfram_do_all_frames: 
         }
      \@outputpage
    } 
    \begingroup
      \@dblfloatplacement
      \@startdblcolumn
      \@whilesw \if@fcolmade \fi
         {\@outputpage \@startdblcolumn }%
    \endgroup
    \__flowfram_reset_statics: 
    \__flowfram_reset_dynamics: 
  }
  {
%    \end{macrocode}
% Still on same page, save contents of box255
%    \begin{macrocode}
    \global \@firstcolumnfalse
%    \end{macrocode}
%Set this frame's column box to the output box.
%    \begin{macrocode}
    \__flowfram_set_column_box:n { \c@thisframe }
  }
  \int_gset_eq:NN \c@thisframe \g__flowfram_next_frame_int
  \__flowfram_set_column:n { \c@thisframe }
}
%    \end{macrocode}
%
%    \begin{macrocode}
\newcommand \@flowfram@update@col@count [ 1 ]
 {
   \int_gset_eq:NN \col@number \c_one_int
   \int_step_inline:nnn
      { #1 + \c_one_int } { \c@maxflow }
    {
       \exp_args:Ne
       \flowfram_if_in_frame_clist:nnnnF
          { \int_eval:n { \g__flowfram_pagecounter_tl } }
          { flow } { excludelist } { ##1 }
        {
%    \end{macrocode}
% This page is in this not in frame's exclusion list so now check if
% in frame's page list.
%    \begin{macrocode}
          \exp_args:Ne
          \flowfram_if_frame_has_morepages:nnnT
            { \int_eval:n { \g__flowfram_pagecounter_tl } }
            { flow } { ##1 }
          {
            \int_gincr:N \col@number
          }
        }
    }
   \int_compare:nNnT
      { \col@number } > { \c_one_int }
    {
      \global\@twocolumntrue
    }
 }
%    \end{macrocode}
%\begin{macro}{\@dblfloatplacement}
% Version 2.0 no longer redefining \cs{@dblfloatplacement}
%(no support for column spanning floats).
%\changes{2.0}{2025-11-24}{removed redefinition}
%\end{macro}
%
%\subsection{Switching Frames On and Off For Subsequent Pages}
%
%\begin{macro}{\flowswitchonnext}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed flow frames from the next page onwards
%    \begin{macrocode}
\NewDocumentCommand \flowswitchonnext { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
         \__flowfram_get_flow_id:n { ##1 }
         \__flowfram_flow_switch_on_next:n { \l__flowfram_id_int }
       }
    }
    {
      \clist_map_inline:nn { #2 }
       {
         \__flowfram_flow_switch_on_next:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchonnext}
% Version 2.0 removed \cs{@sflowswitchonnext}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnext}
% The unstarred version uses \glspl{idn}.
% Version 2.0 removed \cs{@flowswitchonnext}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%Switch on a given frame by its \gls{idn}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_on_next:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_check_if_this_page:nn
       { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
      \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
       {
         \exp_not:N \flowsetpagelist
          { \int_eval:n { #1 } }
          { > \int_eval:n { \g__flowfram_pagecounter_tl } }
       }
     }
     {
      \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
       {
         \exp_not:N \flowsetpagelist
           { \int_eval:n { #1 } }
           { \int_eval:n { \g__flowfram_pagecounter_tl } ,
             > \int_eval:n { \g__flowfram_pagecounter_tl }
           }
       }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\flowswitchonnextodd}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed flow frames from the next odd page onwards
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \flowswitchonnextodd { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl }
   \int_if_odd:nT { \l__flowfram_tmpb_int }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_flow_id:n { ##1 }
          \__flowfram_flow_switch_on_next_odd:n { \l__flowfram_id_int }
       }
    }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_flow_switch_on_next_odd:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_on_next_odd:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_check_if_this_page:nn
       { \g__flowfram_pagecounter_tl } { #1 }
    \clist_clear:N \l__flowfram_pages_clist
    \bool_if:NF \g__flowfram_not_this_frame_bool
     {
       \clist_put_right:Ne \l__flowfram_pages_clist
         { \int_eval:n { \g__flowfram_pagecounter_tl } }
     }
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \__flowfram_check_if_this_page:nn { \l__flowfram_tmpb_int } { #1 }
    \int_compare:nNnF 
        { \l__flowfram_tmpb_int } { \g__flowfram_pagecounter_tl }
      {
        \bool_if:NF \g__flowfram_not_this_frame_bool
         {
           \clist_put_right:Ne \l__flowfram_pages_clist
             { \int_eval:n { \l__flowfram_tmpb_int } }
         }
      }
    \clist_put_right:Ne \l__flowfram_pages_clist
        { > \int_eval:n { \l__flowfram_tmpb_int } }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
      {
        \exp_not:N \flowsetpagelist
          { \int_eval:n { #1 } }
          { \clist_use:Nn \l__flowfram_pages_clist { , } }
      }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sflowswitchonnextodd}
%Version 2.0 removed \cs{@sflowswitchonnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnextodd}
%Version 2.0 removed \cs{@flowswitchonnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\flowswitchoffnext}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed flow frames from the next page onwards
%    \begin{macrocode}
\NewDocumentCommand \flowswitchoffnext { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_flow_id:n { ##1 }
          \__flowfram_flow_switch_off_next:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_flow_switch_off_next:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_off_next:n
 {
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \__flowfram_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
       \clist_set:Nn \l__flowfram_pages_clist { none }
     }
     {
       \tl_set:Ne \l__flowfram_pages_clist 
         {
           \int_eval:n { \g__flowfram_pagecounter_tl }
         }
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
      {
        \exp_not:N \flowsetpagelist
          { \int_eval:n { #1 } }
          { \l__flowfram_pages_clist }
      }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sflowswitchoffnext}
%Version 2.0 removed \cs{@sflowswitchoffnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnext}
%Version 2.0 removed \cs{@flowswitchoffnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\flowswitchoffnextodd}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed flow frames from the next odd page onwards
%    \begin{macrocode}
\NewDocumentCommand \flowswitchoffnextodd { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
      { \g__flowfram_pagecounter_tl }
   \int_if_odd:nT { \g__flowfram_pagecounter_tl }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_flow_id:n { ##1 }
          \__flowfram_flow_switch_off_next_odd:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_flow_switch_off_next_odd:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_off_next_odd:n
 {
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \__flowfram_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \int_compare:nNnTF 
        { \g__flowfram_pagecounter_tl } = { \l__flowfram_tmpb_int }
       {
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
         \tl_set:Nn \l__flowfram_next_pages_tl { none }
       }
       {
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \__flowfram_check_if_this_page:nn
          { \l__flowfram_tmpb_int } { #1 }
        \bool_if:NTF \g__flowfram_not_this_frame_bool
         {
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
           \tl_set:Nn \l__flowfram_next_pages_tl { none }
         }
         {
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
           \tl_set:Ne \l__flowfram_next_pages_tl
             { \int_use:N \l__flowfram_tmpb_int }
         }
       }
    }
    {
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \int_compare:nNnTF 
        { \g__flowfram_pagecounter_tl } = { \l__flowfram_tmpb_int }
       {
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
         \tl_set:Ne \l__flowfram_next_pages_tl
           { \int_eval:n { \g__flowfram_pagecounter_tl } }
       }
       {
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \__flowfram_check_if_this_page:nn
           { \l__flowfram_tmpb_int } { #1 }
        \bool_if:NTF \g__flowfram_not_this_frame_bool
         {
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
           \tl_set:Ne \l__flowfram_next_pages_tl
             { \int_eval:n { \g__flowfram_pagecounter_tl } }
         }
         {
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
          \tl_set:Ne \l__flowfram_next_pages_tl
            {
              \int_eval:n { \g__flowfram_pagecounter_tl } ,
              \int_use:N \l__flowfram_tmpb_int
            }
         }
       }
    }
   \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \flowsetpagelist
         { \int_eval:n { #1 } }
         { \l__flowfram_next_pages_tl }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sflowswitchoffnextodd}
% Version 2.0 removed \cs{@sflowswitchoffnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnextodd}
% Version 2.0 removed \cs{sflowswitchoffnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\flowswitchonnextonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed flow frames for just the next page
%    \begin{macrocode}
\NewDocumentCommand \flowswitchonnextonly { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl + \c_one_int }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_flow_id:n { ##1 }
          \__flowfram_flow_switch_on_next_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_flow_switch_on_next_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_on_next_only:n 
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_check_if_this_page:nn
       { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
       \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
        {
           \exp_not:N \flowsetpagelist
            { \int_eval:n { #1 } }
            { \int_use:N \l__flowfram_tmpb_int }
        }
     }
     {
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
       \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
        {
           \exp_not:N \flowsetpagelist
            { \int_eval:n { #1 } }
            {
              \int_eval:n { \g__flowfram_pagecounter_tl } ,
              \int_use:N \l__flowfram_tmpb_int
            }
        }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sflowswitchonnextonly}
%Version 2.0 removed \cs{@sflowswitchonnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnextonly}
%Version 2.0 removed \cs{@flowswitchonnextonly}.
%\changes{2.0}{2025-11-24}{removed}
% The unstarred version uses \glspl{idn}.
%\end{macro}
%
%\begin{macro}{\flowswitchonnextoddonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed flow frames for just the next odd page
%    \begin{macrocode}
\NewDocumentCommand \flowswitchonnextoddonly { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_flow_id:n { ##1 }
          \__flowfram_flow_switch_on_next_odd_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_flow_switch_on_next_odd_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_on_next_odd_only:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \int_if_odd:nTF { \g__flowfram_pagecounter_tl }
       {
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
         \int_set:Nn \l__flowfram_tmpb_int
           { \g__flowfram_pagecounter_tl + \c_one_int }
         \__flowfram_check_if_this_page:nn
           { \l__flowfram_tmpb_int } { #1 }
         \bool_if:NTF \g__flowfram_not_this_frame_bool
          {
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
            \int_incr:N \l__flowfram_tmpb_int
            \clist_set:Ne \l__flowfram_pages_clist
             { \int_use:N \l__flowfram_tmpb_int }
          }
          {
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
            \clist_set:Ne \l__flowfram_pages_clist
              { \int_use:N \l__flowfram_tmpb_int }
            \int_incr:N \l__flowfram_tmpb_int
            \clist_put_right:Ne \l__flowfram_pages_clist
              { \int_use:N \l__flowfram_tmpb_int }
          }
       }
       {
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
         \int_set:Nn \l__flowfram_tmpb_int
           { \g__flowfram_pagecounter_tl }
         \int_incr:N \l__flowfram_tmpb_int
         \clist_set:Ne \l__flowfram_pages_clist
          { \int_use:N \l__flowfram_tmpb_int }
       }
     }
     {
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
      \int_if_odd:nTF { \g__flowfram_pagecounter_tl }
       {
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
         \int_set:Nn \l__flowfram_tmpb_int
          {
            \g__flowfram_pagecounter_tl + \c_one_int
          }
         \__flowfram_check_if_this_page:nn
           { \l__flowfram_tmpb_int } { #1 }
         \bool_if:NTF \g__flowfram_not_this_frame_bool
          {
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
            \int_incr:N \l__flowfram_tmpb_int
            \clist_set:Ne \l__flowfram_pages_clist
             {
               \int_eval:n { \g__flowfram_pagecounter_tl } ,
               \int_use:N \l__flowfram_tmpb_int
             }
          }
          {
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
            \int_incr:N \l__flowfram_tmpb_int
            \clist_set:Ne \l__flowfram_pages_clist
              {
                \int_eval:n { \g__flowfram_pagecounter_tl } -
                \int_use:N \l__flowfram_tmpb_int
              }
          }
       }
       {
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
         \int_set:Nn \l__flowfram_tmpb_int
           {
             \g__flowfram_pagecounter_tl + \c_one_int
           }
         \clist_set:Ne \l__flowfram_pages_clist
           {
             \int_eval:n { \g__flowfram_pagecounter_tl } ,
             \int_use:N \l__flowfram_tmpb_int
           }
       }
%    \end{macrocode}
%    \begin{macrocode}
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \flowsetpagelist
         { \int_eval:n { #1 } }
         { \l__flowfram_pages_clist }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sflowswitchonnextoddonly}
% Version 2.0 removed \cs{@sflowswitchonnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnextoddonly}
% Version 2.0 removed \cs{@flowswitchonnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%
%\begin{macro}{\flowswitchoffnextonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed flow frames for just the next page
%    \begin{macrocode}
\NewDocumentCommand \flowswitchoffnextonly { s m }
{
   \int_set:Nn \l__flowfram_tmpb_int
     {
      \g__flowfram_pagecounter_tl + \c_one_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_flow_id:n { ##1 }
          \__flowfram_flow_switch_off_next_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_flow_switch_off_next_only:n { ##1 }
       }
    }
}
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_off_next_only:n
 {
   \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
    {
       \exp_not:N \flowaddexclusion
        { \int_eval:n { #1 } }
        { \int_use:N \l__flowfram_tmpb_int }
    }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sflowswitchoffnextonly}
%Version 2.0 removed \cs{@sflowswitchoffnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnextonly}
%Version 2.0 removed \cs{@flowswitchoffnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\flowswitchoffnextoddonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed flow frames for just the next odd page
%    \begin{macrocode}
\NewDocumentCommand \flowswitchoffnextoddonly { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     {
       \g__flowfram_pagecounter_tl + \c_one_int
     }
   \int_if_odd:nF { \l__flowfram_tmpb_int }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_flow_id:n { ##1 }
          \__flowfram_flow_switch_off_next_odd_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_flow_switch_off_next_odd_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_flow_switch_off_next_odd_only:n
 {
   \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \flowaddexclusion
         { \int_eval:n { #1 } }
         { \int_use:N \l__flowfram_tmpb_int }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sflowswitchoffnextoddonly}
%Version 2.0 removed \cs{@sflowswitchoffnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnextoddonly}
%Version 2.0 removed \cs{@flowswitchoffnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnext}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed dynamic frames from the next page onwards
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchonnext { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_on_next:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_on_next:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_on_next:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_dynamic_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
      \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
       {
          \exp_not:N \dynamicsetpagelist 
           { \int_eval:n { #1 } }
           { > \int_eval:n { \g__flowfram_pagecounter_tl } }
       }
     }
     {
      \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
       {
         \exp_not:N \dynamicsetpagelist
           { \int_eval:n { #1 } }
           {
             \int_eval:n { \g__flowfram_pagecounter_tl } ,
             > \int_eval:n { \g__flowfram_pagecounter_tl }
           }
       }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sdynamicswitchonnext}
% Version 2.0 removed \cs{@sdynamicswitchonnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnext}
% Version 2.0 removed \cs{@dynamicswitchonnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnextodd}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed dynamic frames from the next odd page onwards
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchonnextodd { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl }
   \int_if_odd:nT { \l__flowfram_tmpb_int }
     {
       \int_incr:N \l__flowfram_tmpb_int
     }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_on_next_odd:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_on_next_odd:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_on_next_odd:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_dynamic_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 } 
    \clist_clear:N \l__flowfram_pages_clist
    \bool_if:NF \g__flowfram_not_this_frame_bool
     {
       \clist_set:Ne \l__flowfram_pages_clist
        { \int_use:n { \g__flowfram_pagecounter_tl } }
     }
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \__flowfram_dynamic_check_if_this_page:nn
      { \l__flowfram_tmpb_int } { #1 }
    \int_compare:nNnF
      { \l__flowfram_tmpb_int } = { \g__flowfram_pagecounter_tl }
     {
       \bool_if:NF \g__flowfram_not_this_frame_bool
        {
           \clist_put_right:Ne \l__flowfram_pages_clist
            { \int_eval:n { \l__flowfram_tmpb_int } }
        }
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \dynamicsetpagelist
        { \int_eval:n { #1 }}
        { 
           \l__flowfram_pages_clist
            > \int_use:N \l__flowfram_tmpb_int
        }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sdynamicswitchonnextodd}
% Version 2.0 removed \cs{@sdynamicswitchonnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnextodd}
% Version 2.0 removed \cs{@dynamicswitchonnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\dynamicswitchoffnext}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed dynamic frames from the next page onwards
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchoffnext { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_off_next:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_off_next:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_off_next:n
 {
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \__flowfram_dynamic_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
       \clist_set:Nn \l__flowfram_pages_clist { none }
     }
     {
       \clist_set:Ne \l__flowfram_pages_clist
        { \int_eval:n { \g__flowfram_pagecounter_tl } }
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \dynamicsetpagelist
        { \int_eval:n { #1 } }
        { \l__flowfram_pages_clist }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sdynamicswitchoffnext}
% Version 2.0 removed \cs{@sdynamicswitchoffnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnext}
% Version 2.0 removed \cs{@dynamicswitchoffnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\dynamicswitchoffnextodd}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed dynamic frames from the next odd page onwards
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchoffnextodd { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl }
   \int_if_odd:nT { \g__flowfram_pagecounter_tl }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_off_next_odd:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_off_next_odd:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_off_next_odd:n
 {
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \__flowfram_dynamic_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl }  { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
       \int_compare:nNnTF
         { \g__flowfram_pagecounter_tl } = { \l__flowfram_tmpb_int }
        {
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
          \tl_set:Nn \l__flowfram_next_pages_tl { none }
        }
        {
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
          \__flowfram_dynamic_check_if_this_page:nn
            { \l__flowfram_tmpb_int } { #1 }
          \bool_if:NTF \g__flowfram_not_this_frame_bool
           {
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
             \tl_set:Nn \l__flowfram_next_pages_tl { none }
           }
           {
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
              \tl_set:Ne \l__flowfram_next_pages_tl
                { \int_use:N \l__flowfram_tmpb_int }
           }
        }
     }
     {
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
       \int_compare:nNnTF
          { \g__flowfram_pagecounter_tl } = { \l__flowfram_tmpb_int }
        {
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
          \tl_set:Ne \l__flowfram_next_pages_tl
           { \int_use:n { \g__flowfram_pagecounter_tl } }
        }
        {
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
          \__flowfram_dynamic_check_if_this_page:nn
            { \l__flowfram_tmpb_int } { #1 }
          \bool_if:NTF \g__flowfram_not_this_frame_bool
            {
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
              \tl_set:Ne \l__flowfram_next_pages_tl
                { \int_eval:n { \g__flowfram_pagecounter_tl } }
            }
            {
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
              \tl_set:Ne \l__flowfram_next_pages_tl
                {
                  \int_eval:n { \g__flowfram_pagecounter_tl } ,
                  \int_use:N \l__flowfram_tmpb_int
                }
            }
        }
%    \end{macrocode}
%    \begin{macrocode}
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \dynamicsetpagelist
        { \int_eval:n { #1 } }
        { \l__flowfram_next_pages_tl }
     }
 }
%
%    \end{macrocode}
%\begin{macro}{\@sdynamicswitchoffnextodd}
%Version 2.0 removed \cs{@sdynamicswitchoffnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnextodd}
%Version 2.0 removed \cs{@dynamicswitchoffnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnextonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed dynamic frames for just the next page
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchonnextonly { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl + \c_one_int }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_on_next_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_on_next_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_on_next_only:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_dynamic_check_if_this_page:nn
     { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
      \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
       {
         \exp_not:N \dynamicsetpagelist
          { \int_eval:n { #1 } }
          { \int_use:N \l__flowfram_tmpb_int }
       }
     }
     {
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
      \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
       {
         \exp_not:N \dynamicsetpagelist
           { \int_eval:n { #1 } }
           {
             \int_eval:n { \g__flowfram_pagecounter_tl } ,
             \int_use:N \l__flowfram_tmpb_int
           }
       }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sdynamicswitchonnextonly}
% Version 2.0 removed \cs{@sdynamicswitchonnextonly}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnextonly}
% Version 2.0 removed \cs{@dynamicswitchonnextonly}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnextoddonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed dynamic frames for just the next odd page
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchonnextoddonly { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_on_next_odd_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_on_next_odd_only:n { ##1 }
       }
    }
}
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_on_next_odd_only:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_dynamic_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \int_if_odd:nTF { \g__flowfram_pagecounter_tl }
       {
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
        \int_set:Nn \l__flowfram_tmpb_int
          { \g__flowfram_pagecounter_tl + \c_one_int }
        \__flowfram_dynamic_check_if_this_page:nn
          { \l__flowfram_tmpb_int } { #1 }
        \bool_if:NTF \g__flowfram_not_this_frame_bool
         {
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
           \int_incr:N \l__flowfram_tmpb_int
           \clist_set:Ne \l__flowfram_pages_clist
             { \int_use:N \l__flowfram_tmpb_int }
         }
         {
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
           \clist_set:Ne \l__flowfram_pages_clist
             { \int_use:N \l__flowfram_tmpb_int }
           \int_inc:N \l__flowfram_tmpb_int
           \clist_put_right:Ne \l__flowfram_pages_clist
             { \int_use:N \l__flowfram_tmpb_int }
         }
       }
       {
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
         \int_set:Nn \l__flowfram_tmpb_int
           { \g__flowfram_pagecounter_tl + \c_one_int }
         \clist_set:Ne \l__flowfram_pages_clist
           { \int_use:N \l__flowfram_tmpb_int }
       }
     }
     {
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
       \int_if_odd:nTF { \g__flowfram_pagecounter_tl }
        {
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
          \int_set:Nn \l__flowfram_tmpb_int
            { \g__flowfram_pagecounter_tl + \c_one_int }
          \__flowfram_dynamic_check_if_this_page:nn
            { \l__flowfram_tmpb_int } { #1 }
          \bool_if:NTF \g__flowfram_not_this_frame_bool
           {
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
             \int_incr:N \l__flowfram_tmpb_int
             \clist_set:Ne \l__flowfram_pages_clist
               {
                 \int_eval:n { \g__flowfram_pagecounter_tl } ,
                 \int_use:N \l__flowfram_tmpb_int
               }
           }
           {
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
             \int_incr:N \l__flowfram_tmpb_int
             \clist_set:Ne \l__flowfram_pages_clist
              {
                \int_eval:n { \g__flowfram_pagecounter_tl } -
                \int_use:N \l__flowfram_tmpb_int
              }
           }
        }
        {
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
          \int_set:Nn \l__flowfram_tmpb_int
            { \g__flowfram_pagecounter_tl + \c_one_int }
          \clist_set:Ne \l__flowfram_pages_clist
            {
              \int_eval:n { \g__flowfram_pagecounter_tl } ,
              \int_use:N \l__flowfram_tmpb_int
            }
        }
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \dynamicsetpagelist
        { \int_eval:n { #1 } }
        { \l__flowfram_pages_clist }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sdynamicswitchonnextoddonly}
% Version 2.0 removed \cs{@sdynamicswitchonnextoddonly}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnextoddonly}
% Version 2.0 removed \cs{@dynamicswitchonnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%
%\begin{macro}{\dynamicswitchoffnextonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed dynamic frames for just the next page
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchoffnextonly { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl + \c_one_int }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_off_next_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_off_next_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_off_next_only:n
 {
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \dynamicaddexclusion
        { \int_eval:n { #1 } }
        { \int_use:N \l__flowfram_tmpb_int }
     }
 }
%    \end{macrocode}
%\begin{macro}{\@sdynamicswitchoffnextonly}
% Version 2.0 removed \cs{@sdynamicswitchoffnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnextonly}
% Version 2.0 removed \cs{@dynamicswitchoffnextonly}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\dynamicswitchoffnextoddonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed dynamic frames for just the next odd page
%    \begin{macrocode}
\NewDocumentCommand \dynamicswitchoffnextoddonly { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl + \c_one_int }
   \int_if_odd:nF { \l__flowfram_tmpb_int }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_dynamic_id:n { ##1 }
          \__flowfram_dynamic_switch_off_next_odd_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_dynamic_switch_off_next_odd_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_dynamic_switch_off_next_odd_only:n
 {
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \dynamicaddexclusion
        { \int_eval:n { #1 } }
        { \int_use:N \l__flowfram_tmpb_int }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sdynamicswitchoffnextoddonly}
% Version 2.0 removed \cs{@sdynamicswitchoffnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnextoddonly}
% Version 2.0 removed \cs{@dynamicswitchoffnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\staticswitchonnext}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed static frames from the next page onwards
%    \begin{macrocode}
\NewDocumentCommand \staticswitchonnext { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_on_next:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_on_next:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_on_next:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_static_check_if_this_page:nn
       { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
      {
        \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
         {
           \exp_not:N \staticsetpagelist
            { \int_eval:n { #1 } }
            { > \int_eval:n { \g__flowfram_pagecounter_tl } }
         }
      }
      {
        \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
         {
           \exp_not:N \staticsetpagelist
             { \int_eval:n { #1 } }
             {
               \int_eval:n { \g__flowfram_pagecounter_tl } ,
               > \int_eval:n { \g__flowfram_pagecounter_tl }
             }
         }
      }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchonnext}
% Version 2.0 removed \cs{@sstaticswitchonnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnext}
% Version 2.0 removed \cs{@staticswitchonnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\staticswitchonnextodd}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed static frames from the next odd page onwards
%    \begin{macrocode}
\NewDocumentCommand \staticswitchonnextodd { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl }
   \int_if_odd:nT { \l__flowfram_tmpb_int }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_on_next_odd:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_on_next_odd:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_on_next_odd:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_static_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \clist_clear:N \l__flowfram_pages_clist
    \bool_if:NF \g__flowfram_not_this_frame_bool
     {
       \clist_put_right:Ne \l__flowfram_pages_clist
        { \int_eval:n { \g__flowfram_pagecounter_tl } }
     }
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \__flowfram_static_check_if_this_page:nn
       { \l__flowfram_tmpb_int } { #1 }
    \int_compare:nNnF 
        { \l__flowfram_tmpb_int } = { \g__flowfram_pagecounter_tl }
      {
        \bool_if:NF \g__flowfram_not_this_frame_bool
         {
           \clist_put_right:Ne \l__flowfram_pages_clist
            { \int_use:N \l__flowfram_tmpb_int }
         }
      }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
      {
        \exp_not:N \staticsetpagelist
         { \int_eval:n { #1 } }
         {
           \l__flowfram_pages_clist ,
           > \int_use:N \l__flowfram_tmpb_int
         }
      }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchonnextodd}
% Version 2.0 removed \cs{@sstaticswitchonnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnextodd}
% Version 2.0 removed \cs{@staticswitchonnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\staticswitchoffnext}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed static frames from the next page onwards
%    \begin{macrocode}
\NewDocumentCommand \staticswitchoffnext { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_off_next:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_off_next:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_off_next:n
 {
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \__flowfram_static_check_if_this_page:nn
       { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
       \clist_set:Nn \l__flowfram_pages_clist { none }
     }
     {
       \clist_set:Ne \l__flowfram_pages_clist
         { \int_eval:n { \g__flowfram_pagecounter_tl } }
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \staticsetpagelist
        { \int_eval:n { #1 } }
        { \l__flowfram_pages_clist }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchoffnext}
% Version 2.0 removed \cs{@sstaticswitchoffnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnext}
% Version 2.0 removed \cs{@staticswitchoffnext}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\staticswitchoffnextodd}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed static frames from the next odd page onwards
%    \begin{macrocode}
\NewDocumentCommand \staticswitchoffnextodd { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl }
   \int_if_odd:nT { \g__flowfram_pagecounter_tl }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_off_next_odd:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_off_next_odd:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_off_next_odd:n
 {
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \__flowfram_static_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
       \int_compare:nNnTF
         { \g__flowfram_pagecounter_tl } = { \l__flowfram_tmpb_int }
        {
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
          \tl_set:Nn \l__flowfram_next_pages_tl { none }
        }
        {
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
          \__flowfram_static_check_if_this_page:nn
            { \l__flowfram_tmpb_int } { #1 }
          \bool_if:NTF \g__flowfram_not_this_frame_bool
           {
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
             \tl_set:Nn \l__flowfram_next_pages_tl { none }
           }
           {
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
             \tl_set:Ne \l__flowfram_next_pages_tl
               { \int_use:N \l__flowfram_tmpb_int }
           }
        }
     }
     {
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
       \int_compare:nNnTF 
         { \g__flowfram_pagecounter_tl } = { \l__flowfram_tmpb_int }
        {
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
          \tl_set:Ne \l__flowfram_next_pages_tl
            { \int_eval:n { \g__flowfram_pagecounter_tl } }
        }
        {
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
          \__flowfram_static_check_if_this_page:nn
            { \l__flowfram_tmpb_int } { #1 }
          \bool_if:NTF \g__flowfram_not_this_frame_bool
           {
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
             \tl_set:Ne \l__flowfram_next_pages_tl
                { \int_eval:n { \g__flowfram_pagecounter_tl } }
           }
           {
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
             \tl_set:Ne \l__flowfram_next_pages_tl
               {
                 \int_eval:n { \g__flowfram_pagecounter_tl } ,
                 \int_use:N \l__flowfram_tmpb_int
               }
           }
        }
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \staticsetpagelist
         { \int_eval:n { #1 } }
         { \l__flowfram_next_pages_tl }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchoffnextodd}
% Version 2.0 removed \cs{@sstaticswitchoffnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnextodd}
% Version 2.0 removed \cs{\@staticswitchoffnextodd}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\staticswitchonnextonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed static frames for just the next page
%    \begin{macrocode}
\NewDocumentCommand \staticswitchonnextonly { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl + \c_one_int }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_on_next_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_on_next_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_on_next_only:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_static_check_if_this_page:nn
      { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
        \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
         {
           \exp_not:N \staticsetpagelist
             { \int_eval:n { #1 } }
             { \int_use:N \l__flowfram_tmpb_int }
         }
     }
     {
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
       \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
        {
          \exp_not:N \staticsetpagelist
            { \int_eval:n { #1 } }
            {
              \int_eval:n { \g__flowfram_pagecounter_tl } ,
              \int_use:N \l__flowfram_tmpb_int
            }
        }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchonnextonly}
% Version 2.0 removed \cs{@sstaticswitchonnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnextonly}
% Version 2.0 removed \cs{@staticswitchonnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\staticswitchonnextoddonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch on the listed static frames for just the next odd page
%    \begin{macrocode}
\NewDocumentCommand \staticswitchonnextoddonly { s m }
 {
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_on_next_odd_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_on_next_odd_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_on_next_odd_only:n
 {
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \__flowfram_static_check_if_this_page:nn
       { \g__flowfram_pagecounter_tl } { #1 }
    \bool_if:NTF \g__flowfram_not_this_frame_bool
     {
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
       \int_if_odd:nTF { \g__flowfram_pagecounter_tl }
        {
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
          \int_set:Nn \l__flowfram_tmpb_int
            { \g__flowfram_pagecounter_tl + \c_one_int }
          \__flowfram_static_check_if_this_page:nn
            { \l__flowfram_tmpb_int } { #1 }
          \bool_if:NTF \g__flowfram_not_this_frame_bool
           {
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
             \int_incr:N \l__flowfram_tmpb_int
             \clist_set:Ne \l__flowfram_pages_clist
                { \int_use:N \l__flowfram_tmpb_int }
           }
           {
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
             \clist_set:Ne \l__flowfram_pages_clist
               { \int_use:N \l__flowfram_tmpb_int }
             \int_incr:N \l__flowfram_tmpb_int
             \clist_put_right:Ne \l__flowfram_pages_clist
               {
                  \int_use:N \l__flowfram_tmpb_int
               }
           }
        }
        {
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
          \int_set:Nn \l__flowfram_tmpb_int
            { \g__flowfram_pagecounter_tl + \c_one_int }
          \clist_set:Ne \l__flowfram_pages_clist
            { \int_use:N \l__flowfram_tmpb_int }
        }
     }
     {
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
       \int_if_odd:nTF { \g__flowfram_pagecounter_tl }
        {
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
          \int_set:Nn \l__flowfram_tmpb_int
            { \g__flowfram_pagecounter_tl + \c_one_int }
          \__flowfram_static_check_if_this_page:nn
            { \l__flowfram_tmpb_int } { #1 }
          \bool_if:NTF \g__flowfram_not_this_frame_bool
           {
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
             \int_incr:N \l__flowfram_tmpb_int
             \clist_set:Ne \l__flowfram_pages_clist
               {
                 \int_eval:n { \g__flowfram_pagecounter_tl } ,
                 \int_use:N \l__flowfram_tmpb_int
               }
           }
           {
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
            \int_incr:N \l__flowfram_tmpb_int
            \clist_set:Ne \l__flowfram_pages_clist
              {
                \int_eval:n { \g__flowfram_pagecounter_tl } -
                \int_use:N \l__flowfram_tmpb_int
              }
           }
        }
        {
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
          \int_set:Nn \l__flowfram_tmpb_int
            { \g__flowfram_pagecounter_tl + \c_one_int }
          \clist_set:Ne \l__flowfram_pages_clist
            {
              \int_eval:n { \g__flowfram_pagecounter_tl } ,
              \int_use:N \l__flowfram_tmpb_int
            }
        }
     }
    \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
     {
       \exp_not:N \staticsetpagelist
         { \int_eval:n { #1 } }
         { \l__flowfram_pages_clist }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchonnextoddonly}
% Version 2.0 removed \cs{@sstaticswitchonnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnextoddonly}
% Version 2.0 removed \cs{@staticswitchonnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%
%\begin{macro}{\staticswitchoffnextonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed static frames for just the next page
%    \begin{macrocode}
\NewDocumentCommand \staticswitchoffnextonly { s m }
 {
    \int_set:Nn \l__flowfram_tmpb_int
      { \g__flowfram_pagecounter_tl + \c_one_int }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_off_next_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_off_next_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_off_next_only:n
 {
   \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
    {
      \exp_not:N \staticaddexclusion
        { \int_eval:n { #1 } }
        { \int_use:N \l__flowfram_tmpb_int }
    }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchoffnextonly}
% Version 2.0 removed \cs{@sstaticswitchoffnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnextonly}
% Version 2.0 removed \cs{@staticswitchoffnextonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\staticswitchoffnextoddonly}
%\changes{1.14}{2012-11-10}{new}
%\changes{2.0}{2025-11-24}{changed to document command}
% Switch off the listed static frames for just the next odd page
%    \begin{macrocode}
\NewDocumentCommand \staticswitchoffnextoddonly { s m }
 {
   \int_set:Nn \l__flowfram_tmpb_int
     { \g__flowfram_pagecounter_tl + \c_one_int }
   \int_if_odd:nF { \l__flowfram_tmpb_int }
    {
      \int_incr:N \l__flowfram_tmpb_int
    }
   \IfBooleanTF { #1 }
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_get_static_id:n { ##1 }
          \__flowfram_static_switch_off_next_odd_only:n { \l__flowfram_id_int }
       }
    } 
    {
      \clist_map_inline:nn { #2 }
       {
          \__flowfram_static_switch_off_next_odd_only:n { ##1 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_static_switch_off_next_odd_only:n
 {
   \tl_gput_right:Ne \g__flowfram_output_adjust_frames_tl
    {
      \exp_not:N \staticaddexclusion
        { \int_eval:n { #1 } }
        { \int_use:N \l__flowfram_tmpb_int }
    }
 }
%    \end{macrocode}
%
%\begin{macro}{\@sstaticswitchoffnextoddonly}
% Version 2.0 removed \cs{@sstaticswitchoffnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnextoddonly}
% Version 2.0 removed \cs{@staticswitchoffnextoddonly}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\subsection{Static versions of floats}
% Floats can not go in saved boxes 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.
%Version 2.0 added paragraph breaks and ignore spaces.
%\begin{environment}{statictable}
%    \begin{macrocode}
\newenvironment{statictable}
 {\par\def\@captype{table}\ignorespaces}
 {\par\ignorespacesafterend}
%    \end{macrocode}
%\end{environment}
%\begin{environment}{staticfigure}
%    \begin{macrocode}
\newenvironment{staticfigure} 
 {\def\@captype{figure}\ignorespaces}
 {\par\ignorespacesafterend}
%    \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
% "\__flowfram_one_column:n". Syntax: \cs{onecolumn}\oarg{pages}, 
% where \meta{pages} is the \gls{pglist} for which the new
% \gls{flow} is defined.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\cs_set_eq:NN \__flowfram_org_onecolumn: \onecolumn
\RenewDocumentCommand \onecolumn { O{all} o }
 {
   \__flowfram_only_preamble:Nn \onecolumn
    {
      \__flowfram_one_column:n { #1 }
      \IfValueT { #2 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #2 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@onecolumn}
% Version 2.0 replaced \cs{@onecolumn}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_one_column:n
 {
   \__flowfram_one_column_in_area:nnnnn
    { #1 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumninarea}
%\changes{2.0}{2025-11-24}{changed to document command}
% "\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}
\NewDocumentCommand \onecolumninarea { O { all } m m m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumninarea
    {
      \__flowfram_one_column_in_area:nnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 }
      \IfValueT { #6 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #6 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@onecolumninarea}
% Version 2.0 replaced \cs{@onecolumninarea}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_one_column_in_area:nnnnn
 {
  \dim_set:Nn \l__flowfram_height_dim { #3 }
  \ifffvadjust
    \adjustheight \l__flowfram_height_dim 
  \fi
  \__flowfram_new_flow:nnnnn
     { #1 } { #2 } { \l__flowfram_height_dim } { #4 } { #5 }
%    \end{macrocode}
%If \cs{onecolumn} is used in the document and the column associated
%with that column hasn't yet been set, assume this is the one column to
%use.
%    \begin{macrocode}
  \tl_if_empty:NT \g__flowfram_one_col_id_tl
   {
     \tl_gset:Ne \g__flowfram_one_col_id_tl { \int_use:N \c@maxflow }
   }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumn}
%\changes{2.0}{2025-11-24}{changed to document command}
% 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 "\typeblockheight" 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}
\cs_set_eq:NN \__flowfram_org_twocolumn: \twocolumn
\RenewDocumentCommand \twocolumn { O { all } o }
 {
   \__flowfram_only_preamble:Nn \twocolumn
    {
      \__flowfram_two_columns:n { #1 }
      \IfValueT { #2 }
       {
         \clist_set:Ne \l__flowfram_tmp_clist { #2 }
         \int_compare:nNnTF
           { \clist_count:N \l__flowfram_tmp_clist } = { 2 }
          {
            \__flowfram_set_frame_id:nnn { flow } { \c@maxflow }
              { \clist_item:Nn \l__flowfram_tmp_clist { 2 } }
            \__flowfram_set_frame_id:nnn { flow }
              { \int_eval:n { \c@maxflow - \c_one_int } }
              { \clist_item:Nn \l__flowfram_tmp_clist { 1 } }
          }
          {
%    \end{macrocode}
%If only one label provided just set the last frame for backward
%compatibility.
%    \begin{macrocode}
            \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #2 }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@twocolumn}
% Version 2.0 removed \cs{@twocolumn}
%\changes{2.0}{2025-11-24}{removed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_two_columns:n
 {
   \__flowfram_two_columns_in_area:nnnnn
    { #1 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumninarea}
% Again, "\twocolumn" is actually a special case of
% "\twocolumninarea". The final optional argument
% is the label of the final frame. This is added for
% backward-compatibility where a knock-on effect of the final
% command being \cs{newflowframe} meant that a following "[" would
% be interpreted as an optional argument specifying its label.
% Syntax:\newline
% \cs{twocolumninarea}\oarg{pages}\marg{w}\marg{h}\marg{x}\marg{y}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumninarea { O{all} m m m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumninarea
    {
      \__flowfram_two_columns_in_area:nnnnn
        { #1 } { #2 } { #3 } { #4 } { #5 }
      \IfValueT { #6 }
       {
         \clist_set:Ne \l__flowfram_tmp_clist { #6 }
         \int_compare:nNnTF
           { \clist_count:N \l__flowfram_tmp_clist } = { 2 }
          {
            \__flowfram_set_frame_id:nnn { flow } { \c@maxflow }
              { \clist_item:Nn \l__flowfram_tmp_clist { 2 } }
            \__flowfram_set_frame_id:nnn { flow }
              { \int_eval:n { \c@maxflow - \c_one_int } }
              { \clist_item:Nn \l__flowfram_tmp_clist { 1 } }
          }
          {
%    \end{macrocode}
%If only one label provided just set the last frame for backward
%compatibility.
%    \begin{macrocode}
            \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #6 }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@twocolumninarea}
% Version 2.0 replaced \cs{@twocolumninarea}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_two_columns_in_area:nnnnn
 {
  \dim_set:Nn \l__flowfram_height_dim { #3 }
  \ifffvadjust
    \adjustheight \l__flowfram_height_dim 
  \fi
  \dim_set:Nn \l__flowfram_width_dim { ( #2 - \columnsep ) / 2 }
  \dim_set:Nn \l__flowfram_x_dim
    {
      #4 + \l__flowfram_width_dim + \columnsep
    }
  \iflefttorightcolumns
    \__flowfram_new_flow:nnnnn
     { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim } { #4 } { #5 } 
    \setflowframe{\c@maxflow}{margin=left}%
  \else
    \__flowfram_new_flow:nnnnn
     { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
     { \l__flowfram_x_dim  } { #5 } 
    \setflowframe{\c@maxflow}{margin=right}%
  \fi
  \iflefttorightcolumns
    \__flowfram_new_flow:nnnnn
    { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim } 
    { \l__flowfram_x_dim  } { #5 }
    \setflowframe{\c@maxflow}{margin=right}%
  \else
    \__flowfram_new_flow:nnnnn
     { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
     { #4 } { #5 } 
    \setflowframe{\c@maxflow}{margin=left}%
  \fi
%    \end{macrocode}
%If \cs{twocolumn} is used in the document and
%\verb|\flowfram_set_two_col:|
%still has its initial definition, assume this is the two column to
%use. (Note there's no header frame in this case.)
%    \begin{macrocode}
   \cs_if_eq:NNT
      \flowfram_set_two_col:
      \__flowfram_set_two_col_warning:
    {
      \cs_set:Ne \flowfram_set_two_col:
       {
         \exp_not:N \setallflowframes{pages=none}
         \exp_not:N \__flowfram_set_flow_by_idn:nn
           { \int_eval:n { \c@maxflow - \c_one_int } } { pages=all }
         \exp_not:N \__flowfram_set_flow_by_idn:nn
           { \int_use:N \c@maxflow } { pages=all }
       }
    }
%    \end{macrocode}
%If \cs{twocolumn} is used in the document and the associated
%columns haven't yet been set, assume these are the columns to
%use.
%    \begin{macrocode}
  \bool_lazy_and:nnT
    {
      \tl_if_empty_p:N \g__flowfram_two_col_i_id_tl
    }
    {
      \tl_if_empty_p:N \g__flowfram_two_col_ii_id_tl
    }
   {
     \tl_gset:Ne \g__flowfram_two_col_i_id_tl
       {
         \int_eval:n { \c@maxflow - \c_one_int }
       }
     \tl_gset:Ne \g__flowfram_two_col_ii_id_tl { \int_use:N \c@maxflow }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumn}
% Again for an arbitrary number of columns (\meta{n}). Syntax:
% \cs{Ncolumn}\oarg{pages}\marg{n}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \Ncolumn { O{ all } m o }
 {
   \__flowfram_only_preamble:Nn \Ncolumn
    {
     \Ncolumninarea
        [ #1 ] { #2 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
     \IfValueT { #3 }
      {
       \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
      }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \Ncolumninarea { O { all } m m m m m o }
 {
   \__flowfram_only_preamble:Nn \Ncolumninarea
    {
      \int_case:nnF { #2 }
       {
         { \c_one_int }
          {
            \__flowfram_one_column_in_area:nnnnn
            { #1 } { #3 } { #4 } { #5 } { #6 }
          }
         { 2 }
          {
            \__flowfram_two_columns_in_area:nnnnn
              { #1 } { #3 } { #4 } { #5 } { #6 }
          }
       }
       {
         \int_compare:nNnTF { #2 } < { \c_one_int }
          {
            \msg_error:nnne { flowfram } { invalid-num-frames }
              { flow } { \int_eval:n { #2 } }
          }
          {
            \__flowfram_n_columns_in_area:nnnnnn
              { #1 } { #2 } { #3 } { #4 } { #5 } { #6 }
          }
       }
     \IfValueT { #7 }
      {
        \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
      }
    }
 }
%    \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.
%Version 2.0 replaced \cs{@Ncolumninarea}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_n_columns_in_area:nnnnnn
 {
  \int_set:Nn \l__flowfram_col_int { #2 - \c_one_int }
  \dim_set:Nn \l__flowfram_width_dim
   {
     ( #3 - \l__flowfram_col_int \columnsep ) / ( #2 )
   }
  \dim_set:Nn \l__flowfram_x_dim { #5 }
  \iflefttorightcolumns
  \else
    \dim_add:Nn \l__flowfram_x_dim { #3 - \l__flowfram_width_dim }
  \fi
  \dim_set:Nn \l__flowfram_height_dim { #4 }
  \ifffvadjust
    \adjustheight \l__flowfram_height_dim 
  \fi
  \int_step_inline:nn { #2 }
   {
      \__flowfram_new_flow:nnnnn
         { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
         { \l__flowfram_x_dim } { #6 }
      \iflefttorightcolumns
        \dim_add:Nn \l__flowfram_x_dim { \l__flowfram_width_dim + \columnsep }
      \else
        \dim_add:Nn \l__flowfram_x_dim { - \l__flowfram_width_dim - \columnsep }
      \fi
   }
}
%    \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}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumntop { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumntop
    {
      \__flowfram_one_column_with_top_in_area:nnnnnnn
        { #1 } { #2 } { #3 }{ \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnStop}
% Special case for \gls{static}.
% Syntax: \cs{onecolumnStop}\oarg{pages}\marg{H}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnStop { O {all } m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnStop
    {
      \__flowfram_one_column_with_top_in_area:nnnnnnn
        { #1 } { static } { #2 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnDtop}
% Special case for \gls{dynamic}.
% Syntax: \cs{onecolumnDtop}\oarg{pages}\marg{H}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnDtop { O { all } m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnDtop
    {
      \__flowfram_one_column_with_top_in_area:nnnnnnn
        { #1 } { dynamic } { #2 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \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}\oarg{label}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \newframe { s O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \newframe
    {
      \cs_if_exist:cTF
         { __flowfram_new_ #3 :nnnnnn }
       {
         \IfValueTF { #8 }
          {
            \use:c { __flowfram_new_ #3 :nnnnnn }
             { #2 } { #4 } { #5 } { #6 } { #7 } { #8 }
          }
          {
            \use:c { __flowfram_new_ #3 :nnnnnn }
             { #2 } { #4 } { #5 } { #6 } { #7 } { \int_use:c { c@max #3 } }
          }
        \IfBooleanT { #1 }
          {
%    \end{macrocode}
%\changes{2.1}{2026-02-23}{corrected function name}
%    \begin{macrocode}
            \flowfram_frame_set_bool_true:nnn
              { #3 } { hasframe } { \value { max #3 } }
          }
       }
       {
         \msg_error:nne { flowfram } { invalid-frame-type } { #3 }
       }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumntopinarea { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumntopinarea
    {
      \__flowfram_one_column_with_top_in_area:nnnnnnn
        { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_one_column_with_top_in_area:nnnnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #3 }
  \dim_set:Nn \l__flowfram_y_dim 
    { #5 - \l__flowfram_sfdf_height_dim }
  \dim_set:Nn \l__flowfram_height_dim
    { \l__flowfram_y_dim - \vcolumnsep }
  \dim_add:Nn \l__flowfram_y_dim { #7 }
  \newframe
     [ #1 ] { #2 }
     { #4 } { \l__flowfram_sfdf_height_dim }
     { #6 } { \l__flowfram_y_dim }
  \ifffvadjust
    \adjustheight \l__flowfram_height_dim 
  \fi
  \__flowfram_new_flow:nnnnn
    { #1 } { #4 } { \l__flowfram_height_dim } { #6 } { #7 }
}
%    \end{macrocode}
%\begin{macro}{\onecolumnStopinarea}
% Special case for \gls{static}.
% Syntax:\newline
% \cs{onecolumnStopinarea}\oarg{pages}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnStopinarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnStopinarea
    {
      \__flowfram_one_column_with_top_in_area:nnnnnnn
        { #1 } { static } { #2 } { #3 } { #4 } { #5 } { #6 } 
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnDtopinarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnStopinarea
    {
      \__flowfram_one_column_with_top_in_area:nnnnnnn
        { #1 } { dynamic } { #2 } { #3 } { #4 } { #5 } { #6 } 
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumntop}
%\changes{2.0}{2025-11-24}{changed to document command}
% 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}
\NewDocumentCommand \twocolumntop { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumntop
    {
      \__flowfram_two_column_top_in_area:nnnnnnn
       { #1 } { #2 } { #3 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnStop}
% Special case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnStop { O{all} m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnStop
    {
      \__flowfram_two_column_with_top_in_area:nnnnnnn
       { #1 } { static }{ #2 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDtop}
%\changes{2.0}{2025-11-24}{changed to document command}
% Special case for \gls{dynamic}.
%    \begin{macrocode}
\NewDocumentCommand \twocolumnDtop { O{all} m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnDtop
    {
      \__flowfram_two_column_with_top_in_area:nnnnnnn
       { #1 } { dynamic }{ #2 } { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumntopinarea { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumntopinarea
    {
      \__flowfram_two_column_with_top_in_area:nnnnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@twocolumntopinarea}
% Version 2.0 replaced \cs{@twocolumntopinarea}
%\changes{2.0}{2025-11-24}{replaced}
%Syntax: \marg{pages}\marg{type}\marg{top
%height}\marg{area-width}\marg{area-height}\marg{area-x}\marg{area-y}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_two_column_with_top_in_area:nnnnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #3 }
%    \end{macrocode}
% Work out where to put the header frame.
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_y_dim 
    { #5 - \l__flowfram_sfdf_height_dim }
  \dim_set:Nn \l__flowfram_height_dim
    { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_y_dim { #7 }
  \newframe
    [ #1 ] { #2 }
    { #4 } { \l__flowfram_sfdf_height_dim }
    { #6 } { \l__flowfram_y_dim }
%    \end{macrocode}
%If \cs{twocolumn} is used in the document with its optional
%argument and the associated frames haven't yet been set, assume
%this is the header frame to use.
%    \begin{macrocode}
  \tl_if_empty:NT \g__flowfram_two_col_header_id_tl
   {
     \bool_lazy_and:nnT
       {
         \tl_if_empty_p:N \g__flowfram_headed_two_col_i_id_tl
       }
       {
         \tl_if_empty_p:N \g__flowfram_headed_two_col_ii_id_tl
       }
      {
       \tl_gset:Ne \g__flowfram_two_col_header_type_tl { #2 }
       \tl_gset:Ne \g__flowfram_two_col_header_id_tl
        {
          \int_use:c { c@max #2 }
        }
     }
   }
%    \end{macrocode}
% work out height of the flow frames
%    \begin{macrocode}
  \dim_sub:Nn \l__flowfram_height_dim { \vcolumnsep }
  \ifffvadjust
     \adjustheight { \l__flowfram_height_dim }
  \fi
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_width_dim
    { ( #4 - \columnsep ) / 2 }
%    \end{macrocode}
% work out the offset of the right column
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_x_dim 
    { \l__flowfram_width_dim + \columnsep + #6 }
  \iflefttorightcolumns
    \__flowfram_new_flow:nnnnn
      { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim } { #6 } { #7 }
    \setflowframe { \c@maxflow } { margin = left }
    \__flowfram_new_flow:nnnnn
     { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim } { \l__flowfram_x_dim } { #7 }
    \setflowframe { \c@maxflow } { margin = right }
  \else
    \__flowfram_new_flow:nnnnn
     { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim } { \l__flowfram_x_dim } { #7 }
    \setflowframe { \c@maxflow } { margin = right }
    \__flowfram_new_flow:nnnnn
     { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim } { #6 } { #7 }
    \setflowframe { \c@maxflow } { margin = left }
  \fi
%    \end{macrocode}
%If \cs{twocolumn} is used in the document with its optional
%argument and the associated frames haven't yet been set, assume these are the columns to
%use.
%    \begin{macrocode}
  \bool_lazy_and:nnT
    {
      \tl_if_empty_p:N \g__flowfram_headed_two_col_i_id_tl
    }
    {
      \tl_if_empty_p:N \g__flowfram_headed_two_col_ii_id_tl
    }
   {
     \tl_gset:Ne \g__flowfram_headed_two_col_i_id_tl
       {
         \int_eval:n { \c@maxflow - \c_one_int }
       }
     \tl_gset:Ne \g__flowfram_headed_two_col_ii_id_tl { \int_use:N \c@maxflow }
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnStopinarea}
% Special case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnStopinarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnStopinarea
    {
      \__flowfram_two_column_with_top_in_area:nnnnnnn
       { #1 } { static } { #2 } { #3 } { #4 } { #5 } { #6 }
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDtopinarea}
% Special case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnDtopinarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnStopinarea
    {
      \__flowfram_two_column_with_top_in_area:nnnnnnn
       { #1 } { dynamic } { #2 } { #3 } { #4 } { #5 } { #6 }
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \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}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \Ncolumntop { O{all} m m m o }
 {
   \__flowfram_only_preamble:Nn \Ncolumntop
    {
      \__flowfram_n_column_with_top_in_area:nnnnnnnn
       { #1 } { #2 } { #3 } { #4 }
       { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #5 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #5 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnStop}
% Special case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \NcolumnStop { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnStop
    {
      \__flowfram_n_column_with_top_in_area:nnnnnnnn
       { #1 } { static} { #2 } { #3 }
       { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDtop}
% Special case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \NcolumnDtop { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnDtop
    {
      \__flowfram_n_column_with_top_in_area:nnnnnnnn
       { #1 } { dynamic} { #2 } { #3 }
       { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumntopinarea}
% Again test to make sure the user requested a sensible
% number.
%\changes{2.0}{2025-11-24}{changed to document command}
% \cs{Ncolumntopinarea}\oarg{pages}\marg{type}\marg{n}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}
%    \begin{macrocode}
\NewDocumentCommand \Ncolumntopinarea { O{all} m m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \Ncolumntopinarea
    {
      \__flowfram_n_column_with_top_in_area:nnnnnnnn
       { #1 } { #2 } { #4 } { #5 } { #6 } { #7 } { #8 }
      \IfValueT { #9 }
       {
        \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #9 }
      }
    }
 }
%    \end{macrocode}
%
%\marg{pages}\marg{type}\marg{n}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_n_column_with_top_in_area:nnnnnnnn
 {
    \int_case:nnF { #3 }
      {
         { \c_one_int }
           {
             \__flowfram_one_column_with_top_in_area:nnnnnnn
              { #1 } { #2 } { #4 } { #5 } { #6 } { #7 } { #8 }
           }
         { 2 }
           {
             \__flowfram_two_column_with_top_in_area:nnnnnnn
              { #1 } { #2 } { #4 } { #5 } { #6 } { #7 } { #8 }
           }
      }
      {
        \int_compare:nNnTF { #3 } < { \c_one_int }
          {
            \msg_error:nnne { flowfram } { invalid-num-frames }
              { flow } { \int_eval:n { #3 } }
          }
          {
            \__flowfram_N_column_with_top_in_area:nnnnnnnn
              { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 }
          }
      }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@Ncolumntopinarea}
% Fit the frames into specified area.
% \marg{pages}\marg{type}\marg{n}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
% Version 2.0 replaced \cs{@Ncolumntopinarea}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_N_column_with_top_in_area:nnnnnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #4 }
%    \end{macrocode}
% Work out where to put the static frame.
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_y_dim 
    { #6 - \l__flowfram_sfdf_height_dim }
  \dim_set_eq:NN \l__flowfram_height_dim \l__flowfram_y_dim 
  \dim_add:Nn \l__flowfram_y_dim { #8 }
  \newframe
    [ #1 ] { #2 }
    { #5 } { \l__flowfram_sfdf_height_dim }
    { #7 } { \l__flowfram_y_dim }
%    \end{macrocode}
% work out height of the flow frames
%    \begin{macrocode}
  \dim_sub:Nn \l__flowfram_height_dim { \vcolumnsep }
%    \end{macrocode}
% adjust the flow frame height so that it is a multiple of 
% \cs{baselineskip}
%    \begin{macrocode}
  \ifffvadjust
    \adjustheight{\l__flowfram_height_dim}%
  \fi
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \int_set:Nn \l__flowfram_col_int { #3 - \c_one_int }
  \dim_set:Nn \l__flowfram_width_dim
     { ( #5 -\l__flowfram_col_int \columnsep ) / ( #3 ) }
%    \end{macrocode}
% Set the $x$ position of the first frame
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_x_dim { #7 }
  \iflefttorightcolumns
  \else
    \dim_add:Nn \l__flowfram_x_dim { #5 - \l__flowfram_width_dim }
  \fi
  \int_step_inline:nn { #3 }
   {
     \__flowfram_new_flow:nnnnn
      { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
      { \l__flowfram_x_dim } { #8 }
%    \end{macrocode}
% work out the offset for the next column
%    \begin{macrocode}
    \iflefttorightcolumns
      \dim_add:Nn \l__flowfram_x_dim { \l__flowfram_width_dim + \columnsep }
    \else
      \dim_add:Nn \l__flowfram_x_dim { - \l__flowfram_width_dim - \columnsep }
    \fi
   }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnStopinarea}
% Specific case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
% \marg{pages}\marg{n}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}.
%    \begin{macrocode}
\NewDocumentCommand \NcolumnStopinarea { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnStopinarea
    {
      \__flowfram_n_column_with_top_in_area:nnnnnnnn
        { #1 } { static } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDtopinarea}
% Specific case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \NcolumnDtopinarea { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnDtopinarea
    {
      \__flowfram_n_column_with_top_in_area:nnnnnnnn
        { #1 } { dynamic } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
 }
%    \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}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnbottom { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnbottom
    {
      \__flowfram_one_column_with_bottom_in_area:nnnnnnn
        { #1 } { #2 } { #3 }
        { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnSbottom}
% Special case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnSbottom { O{all} m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnbottom
    {
      \__flowfram_one_column_with_bottom_in_area:nnnnnnn
        { #1 } { static } { #2 }
        { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnDbottom}
% Special case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnDbottom { O{all} m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnbottom
    {
      \__flowfram_one_column_with_bottom_in_area:nnnnnnn
        { #1 } { dynamic } { #2 }
        { \typeblockwidth } { \typeblockheight } { 0pt } { 0pt }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnbottominarea
  { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnbottominarea
    {
      \__flowfram_one_column_with_bottom_in_area:nnnnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
          \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_one_column_with_bottom_in_area:nnnnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #3 }
  \dim_set:Nn \l__flowfram_height_dim
    {
      #5
      - \l__flowfram_sfdf_height_dim
      - \vcolumnsep
    }
  \ifffvadjust
    \adjustheight { \l__flowfram_height_dim }
  \fi
  \dim_set:Nn \l__flowfram_tmpa_dim
    {
      #5 - \l__flowfram_height_dim + #7
    }
  \newframe [ #1 ] { #2 }
     { #4 } { \l__flowfram_sfdf_height_dim }
     { #6 } { #7 }
  \__flowfram_new_flow:nnnnn
    { #1 } { #4 } { \l__flowfram_height_dim } { #6 } { \l__flowfram_tmpa_dim }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnSbottominarea}
% Special case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnSbottominarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnSbottominarea
    {
      \__flowfram_one_column_with_bottom_in_area:nnnnnnn
       { #1 } { static } { #2 } { #3 } { #4 } { #5 } { #6 }
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\onecolumnDbottominarea}
% Special case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \onecolumnDbottominarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \onecolumnDbottominarea
    {
      \__flowfram_one_column_with_bottom_in_area:nnnnnnn
       { #1 } { dynamic } { #2 } { #3 } { #4 } { #5 } { #6 }
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnbottom { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnbottom
    {
      \__flowfram_two_column_with_bottom_in_area:nnnnnnn
        { #1 } { #2 } { #3 } { \typeblockwidth } { \typeblockheight }
        { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnSbottom}
% Special case for \gls{static}.
%    \begin{macrocode}
\NewDocumentCommand \twocolumnSbottom { O{all} m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnDbottom
    {
      \__flowfram_two_column_with_bottom_in_area:nnnnnnn
        { #1 } { static } { #2 }
         { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDbottom}
% Special case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnDbottom { O{all} m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnDbottom
    {
      \__flowfram_two_column_with_bottom_in_area:nnnnnnn
        { #1 } { dynamic } { #2 }
         { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #3 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #3 }
       }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnbottominarea { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnbottominarea
    {
      \__flowfram_two_column_with_bottom_in_area:nnnnnnn
        { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_two_column_with_bottom_in_area:nnnnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_width_dim { #4 }
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #3 }
%    \end{macrocode}
% Work out height of the flow frames.
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_height_dim
    { #5 - \l__flowfram_sfdf_height_dim - \vcolumnsep }
  \ifffvadjust
    \adjustheight { \l__flowfram_height_dim }
  \fi
  \newframe
   [ #1 ] { #2 }
   { \l__flowfram_sfdf_width_dim } { \l__flowfram_sfdf_height_dim }
   { #6 } { #7 }
%    \end{macrocode}
% Work out the $y$ position of the flow frames.
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_y_dim { #5 - \l__flowfram_height_dim + #7 }
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_width_dim
   {
     ( \l__flowfram_sfdf_width_dim - \columnsep ) /2
   }
%    \end{macrocode}
% work out the $x$ offset of the right column
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_x_dim 
    {
      \l__flowfram_width_dim + \columnsep + #6
    }
%    \end{macrocode}
% Define the frames
%    \begin{macrocode}
  \iflefttorightcolumns
    \__flowfram_new_flow:nnnnn
      { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
      { #6 } { \l__flowfram_y_dim }
    \setflowframe{\c@maxflow}{margin=left}%
    \__flowfram_new_flow:nnnnn
      { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
      { \l__flowfram_x_dim } { \l__flowfram_y_dim }
    \setflowframe{\c@maxflow}{margin=right}%
  \else
    \__flowfram_new_flow:nnnnn
      { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
      { \l__flowfram_x_dim } { \l__flowfram_y_dim }
    \setflowframe{\c@maxflow}{margin=right}%
    \__flowfram_new_flow:nnnnn
      { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
      { #6 } { \l__flowfram_y_dim }
    \setflowframe{\c@maxflow}{margin=left}%
  \fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnSbottominarea}
% Special case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnSbottominarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnSbottominarea
    {
      \__flowfram_two_column_with_bottom_in_area:nnnnnnn
        { #1 } { static } { #2 } { #3 } { #4 } { #5 } { #6 } 
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\twocolumnDbottominarea}
% Special case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \twocolumnDbottominarea { O{all} m m m m m o }
 {
   \__flowfram_only_preamble:Nn \twocolumnDbottominarea
    {
      \__flowfram_two_column_with_bottom_in_area:nnnnnnn
        { #1 } { dynamic } { #2 } { #3 } { #4 } { #5 } { #6 } 
      \IfValueT { #7 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #7 }
       }
    }
 }
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \Ncolumnbottom { O{all} m m m o }
 {
   \__flowfram_only_preamble:Nn \Ncolumnbottominarea
    {
      \__flowfram_n_column_with_bottom_in_area:nnnnnnnn
        { #1 } { #2 } { #3 } { #4 }
        { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #5 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #5 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnSbottom}
% Special case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \NcolumnSbottom { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnSbottom
    {
      \__flowfram_n_column_with_bottom_in_area:nnnnnnnn
        { #1 } { static } { #2 } { #3 } 
        { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDbottom}
% Special case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \NcolumnDbottom { O{all} m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnDbottom
    {
      \__flowfram_n_column_with_bottom_in_area:nnnnnnnn
        { #1 } { dynamic } { #2 } { #3 } 
        { \typeblockwidth } { \typeblockheight } { \c_zero_dim } { \c_zero_dim }
      \IfValueT { #4 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #4 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\Ncolumnbottominarea}
% Again check the user has requested a sensible number.
%\changes{2.0}{2025-11-24}{changed to document command}
% \cs{Ncolumnbottominarea}\oarg{pages}\marg{type}\marg{n}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}
%    \begin{macrocode}
\NewDocumentCommand \Ncolumnbottominarea { O{all} m m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \Ncolumnbottominarea
    {
      \__flowfram_n_column_with_bottom_in_area:nnnnnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 }
      \IfValueT { #9 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #9 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@Ncolumnbottominarea}
% Version 2.0 replaced \cs{@Ncolumnbottominarea}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_n_column_with_bottom_in_area:nnnnnnnn
 {
   \int_case:nnF { #3 }
    {
      { \c_one_int }
       {
         \__flowfram_one_column_with_bottom_in_area:nnnnnnn
          { #1 } { #2 } { #4 } { #5 } { #6 } { #7 } { #8 }
       }
      { 2 }
       {
         \__flowfram_two_column_with_bottom_in_area:nnnnnnn
          { #1 } { #2 } { #4 } { #5 } { #6 } { #7 } { #8 }
       }
    }
    {
      \int_compare:nNnTF { #3 } > { 2 }
       {
         \__flowfram_N_column_with_bottom_in_area:nnnnnnnn
          { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 }
       }
       {
         \msg_error:nnne { flowfram } { invalid-num-frames }
           { flow } { \int_eval:n { #3 } }
       }
    }
}
%    \end{macrocode}
%\end{macro}
% Syntax: \marg{pages}\marg{type}\marg{n}\marg{H}\marg{w}\marg{h}\marg{x}\marg{y}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_N_column_with_bottom_in_area:nnnnnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #4 }
%    \end{macrocode}
% Work out height of the flow frames.
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_height_dim
    { #6 - \l__flowfram_sfdf_height_dim - \vcolumnsep }
%    \end{macrocode}
% adjust the flow frame height so that it is a multiple of 
% \cs{baselineskip}
%    \begin{macrocode}
  \ifffvadjust
    \adjustheight { \l__flowfram_height_dim }
  \fi
  \newframe
    [ #1 ] { #2 }
    { #5 } { \l__flowfram_sfdf_height_dim } { #7 } { #8 }
%    \end{macrocode}
% Work out the $y$ offset of the flow frames.
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_y_dim 
    { #6 - \l__flowfram_height_dim + #8 }
%    \end{macrocode}
% work out the widths of the flow frames
%    \begin{macrocode}
  \int_set:Nn \l__flowfram_col_int { #3 - \c_one_int }
  \dim_set:Nn \l__flowfram_width_dim
    { ( #5 -\l__flowfram_col_int \columnsep ) / ( #3 ) }
%    \end{macrocode}
% Set the $x$ offset of the first frame.
%    \begin{macrocode}
  \dim_set:Nn \l__flowfram_x_dim { #7 }
  \iflefttorightcolumns
  \else
    \dim_add:Nn \l__flowfram_x_dim { #5 - \l__flowfram_width_dim }
  \fi
  \int_step_inline:nn { #3 }
   {
    \__flowfram_new_flow:nnnnn
     { #1 } { \l__flowfram_width_dim } { \l__flowfram_height_dim }
     { \l__flowfram_x_dim } { \l__flowfram_y_dim }
%    \end{macrocode}
% Work out the offset for the next column.
%    \begin{macrocode}
    \iflefttorightcolumns
      \dim_add:Nn \l__flowfram_x_dim { \l__flowfram_width_dim + \columnsep }
    \else
      \dim_add:Nn \l__flowfram_x_dim { - \l__flowfram_width_dim -\columnsep }
    \fi
   }
}
%    \end{macrocode}
%
%\begin{macro}{\NcolumnSbottominarea}
% Specific case for \gls{static}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \NcolumnSbottominarea { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnSbottominarea
    {
      \__flowfram_n_column_with_bottom_in_area:nnnnnnnn
       { #1 } { static } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\NcolumnDbottominarea}
% Specific case for \gls{dynamic}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \NcolumnDbottominarea { O{all} m m m m m m o }
 {
   \__flowfram_only_preamble:Nn \NcolumnDbottominarea
    {
      \__flowfram_n_column_with_bottom_in_area:nnnnnnnn
       { #1 } { dynamic } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 }
      \IfValueT { #8 }
       {
         \__flowfram_set_frame_id:nnn { flow } { \c@maxflow } { #8 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ff@adjh}
% Version 2.0 replaced \cs{@ff@adjh}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_new:N \l__flowfram_adjust_height_int 
%    \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}
\newcommand*{\adjustheight}[1]{%
%    \end{macrocode}
% Convert the dimension to an integer.
%    \begin{macrocode}
  \int_set:Nn \l__flowfram_adjust_height_int
    {
      \int_div_round:nn
        { \dim_to_decimal_in_sp:n { #1 } }
        { \dim_to_decimal_in_sp:n { \baselineskip } }
    }
  \dim_set:Nn #1 { \l__flowfram_adjust_height_int \baselineskip }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\adjustcolsep}
% Adjust the value of "\columnsep" so that the margins will fit between columns.
%    \begin{macrocode}
\newcommand*{\adjustcolsep}{%
  \dim_set:Nn \columnsep { 2 \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}".
%
% Vertical two tone effect where the height of the static
% frames is equal to the paper height.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \vtwotone
  { O{all} O {\c_zero_dim} m m m m m m }
 {
   \__flowfram_only_preamble:Nn \vtwotone
    {
      \__flowfram_v_two_tone_bottom:nnnnnnnnn
       { #1 } { #2 } { \paperheight } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vtwotone}
% Version 2.0 removed \cs{@vtwotone}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
% Vertical two tone effect along the bottom of the page, of
% height \meta{H}.
% Syntax:\newline
% \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}
\cs_new:Nn \__flowfram_v_two_tone_bottom:nnnnnnnnn
 {
  \computeleftedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computeleftedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_set_eq:NN \l__flowfram_evenx_dim \l__flowfram_x_dim 
  \fi
  \computebottomedge { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_x_dim { #2 }
  \dim_add:Nn \l__flowfram_evenx_dim { #2 }
  \__flowfram_next_v_band:nnnnn { #1 } { #3 } { #4 } { #5 } { #6 }
  \__flowfram_next_v_band:nnnnn { #1 } { #3 } { #7 } { #8 } { #9 }
}
%    \end{macrocode}
%
%\begin{macro}{\vtwotonebottom}
% Border strip along the bottom of the page
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \vtwotonebottom
  { O{all} O {\c_zero_dim} m m m m m m m }
 {
   \__flowfram_only_preamble:Nn \vtwotonebottom
    {
      \__flowfram_v_two_tone_bottom:nnnnnnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vtwotonebottom}
% Version 2.0 removed \cs{@vtwotonebottom}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\vtwotonetop}
% Border strip along the top of the page.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \vtwotonetop
  { O{all} O {\c_zero_dim} m m m m m m m }
 {
   \__flowfram_only_preamble:Nn \vtwotonebottom
    {
      \__flowfram_v_two_tone_top:nnnnnnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vtwotonetop}
% Version 2.0 removed \cs{@vtwotonetop}
%\changes{2.0}{2025-11-24}{removed}
%    \begin{macrocode}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@vtwotonetop}
% Version 2.0 replaced \cs{@@vtwotonetop}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_v_two_tone_top:nnnnnnnnn
 {
  \computeleftedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computeleftedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_set:Nn \l__flowfram_evenx_dim { \l__flowfram_x_dim }
  \fi
  \computetopedge { \l__flowfram_y_dim }
  \dim_sub:Nn \l__flowfram_y_dim { #3 }
  \dim_add:Nn \l__flowfram_x_dim { #2 }
  \dim_add:Nn \l__flowfram_evenx_dim { #2 }
  \__flowfram_next_v_band:nnnnn { #1 } { #3 } { #4 } { #5 } { #6 }
  \__flowfram_next_v_band:nnnnn { #1 } { #3 } { #7 } { #8 } { #9 }
}
%    \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 "\l__flowfram_x_dim " and "\l__flowfram_y_dim ". 
% On exit, "\l__flowfram_x_dim " is set to the right border.
% Version 2.0 renamed \cs{@nextvband}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_next_v_band:nnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_width_dim { #3 }
  \tl_if_empty:nTF { #5 }
   {
     \__flowfram_new_static:nnnnn
      { #1 } { \l__flowfram_sfdf_width_dim } { #2 }
      { \l__flowfram_x_dim } { \l__flowfram_y_dim }
   }
   {
     \__flowfram_new_static:nnnnnn
      { #1 } { \l__flowfram_sfdf_width_dim } { #2 }
      { \l__flowfram_x_dim } { \l__flowfram_y_dim } { #5 }
   }
  \flowfram_frame_set_dim:nnnn { static} { evenx } { \c@maxstatic }
       { \l__flowfram_evenx_dim }
  \__flowfram_set_frame_color:w
    #4 \q_stop { static } { backcolor } { \c@maxstatic }
  \dim_add:Nn \l__flowfram_x_dim { \l__flowfram_sfdf_width_dim }
  \dim_add:Nn \l__flowfram_evenx_dim { \l__flowfram_sfdf_width_dim }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@thisstrip}
% Keep track of which strip we are doing.
% Version 2.0 renamed \cs{@thisstrip}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\int_new:N \l__flowfram_this_strip_int 
%    \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}.
%
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \vNtone { O{all} O {\c_zero_dim} m }
 {
   \clist_set:Nn \l__flowfram_pages_clist { #1 }
   \__flowfram_v_N_tone_bottom:nnn  { #2 } { #3 } { \paperheight }
 }
\@onlypreamble{\vNtone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vNtone}
% Got the first argument, now get the next.
% Version 2.0 removed \cs{@vNtone}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@vNtone}
% Vertical \meta{n} tone aligned along the
% bottom of the page with height "#3".
% Version 2.0 renamed \cs{@@vNtone}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_v_N_tone_bottom:nnn
 {
  \computeleftedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computeleftedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_set_eq:NN \l__flowfram_evenx_dim \l__flowfram_x_dim 
  \fi
  \computebottomedge { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_x_dim { #1 }
  \dim_add:Nn \l__flowfram_evenx_dim { #1 }
  \int_set:Nn \l__flowfram_this_strip_int { #2 }
  \dim_set:Nn\l__flowfram_sfdf_height_dim { #3 }
  \__flowfram_next_v_N_band: 
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@nextvNband}
% Recursively do the next strip.
% Version 2.0 renamed \cs{@nextvNband}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_next_v_N_band: 
 {
   \int_compare:nNnTF { \l__flowfram_this_strip_int } > { \c_zero_int }
    {
      \let \flf@next \@@nextvNband
    }
    {
      \let \flf@next \relax
    }
  \int_decr:N \l__flowfram_this_strip_int
  \flf@next
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@nextvNband}
% Do current strip, and go on to next one.
%    \begin{macrocode}
\newcommand*{\@@nextvNband}[3]{%
  \__flowfram_next_v_band:nnnnn
    { \l__flowfram_pages_clist } { \l__flowfram_sfdf_height_dim }
    { #1 } { #2 } { #3 }
  \__flowfram_next_v_N_band: 
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\vNtonebottom}
% Border strip along the bottom of the page. Same as above
% but user specifies the height.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \vNtonebottom { O{all} O{\c_zero_dim} m m }
{
  \clist_set:Nn \l__flowfram_pages_clist { #1 }
  \__flowfram_v_N_tone_bottom:nnn { #2 } { #3 } { #4 }
}
\@onlypreamble{\vNtonebottom}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vNtonebottom}
% Version 2.0 removed \cs{@vNtonebottom}.
%\changes{2.0}{2025-11-24}{removed}
%\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}
\NewDocumentCommand \vNtonetop { O{all} O{\c_zero_dim} m m }
 {
  \clist_set:Nn \l__flowfram_pages_clist { #1 }
  \__flowfram_v_N_tone_top:nnn { #2 } { #3 } { #4 }
 }
\@onlypreamble{\vNtonetop}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@vNtonetop}
% Get next optional argument.
% Version 2.0 removed \cs{@vNtonetop}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@@vNtonetop}
% Now get on with it.  Again, it has to be done 
% recursively.
% Version 2.0 renamed \cs{@@vNtonetop}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_v_N_tone_top:nnn
 {
  \computeleftedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computeleftedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_set_eq:NN \l__flowfram_evenx_dim \l__flowfram_x_dim 
  \fi
  \computetopedge { \l__flowfram_y_dim }
  \dim_sub:Nn \l__flowfram_y_dim { #3 }
  \dim_add:Nn \l__flowfram_x_dim { #1 }
  \dim_add:Nn \l__flowfram_evenx_dim { #1 }
  \int_set:Nn \l__flowfram_this_strip_int { #2 }
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #3 }
  \__flowfram_next_v_N_band: 
 }
%    \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}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \htwotone
  { O{all} O {\c_zero_dim} m m m m m m }
 {
   \__flowfram_only_preamble:Nn \htwotone
    {
      \__flowfram_h_two_tone_left:nnnnnnnnn
       { #1 } { #2 } { \paperwidth } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 }
    }
 }
\@onlypreamble{\htwotone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@htwotone}
% Version 2.0 removed \cs{@htwotone}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@htwotoneleft}
% This is all done in much the same way as the vertical
% strips.
% Version 2.0 replaced \cs{@@htwotoneleft}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_h_two_tone_left:nnnnnnnnn
 {
  \computeleftedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computeleftedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_set:Nn \l__flowfram_evenx_dim { \l__flowfram_x_dim }
  \fi
  \computebottomedge { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_y_dim { #2 }
  \__flowfram_h_two_tone_left:nnnnnnnnn  { #1 } { #3 } { #4 } { #5 } { #6 }
  \__flowfram_h_two_tone_left:nnnnnnnnn  { #1 } { #3 } { #7 } { #8 } { #9 }
}

%    \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}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \htwotoneleft
  { O{all} O {\c_zero_dim} m m m m m m m }
 {
   \__flowfram_only_preamble:Nn \htwotoneleft
    {
      \__flowfram_h_two_tone_left:nnnnnnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
    }
 }
\@onlypreamble{\htwotoneleft}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@htwotoneleft}
% Version 2.0 removed \cs{@htwotoneleft}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\htwotoneright}
% Two tone horizontal strips along right border
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \htwotoneright
  { O{all} O {\c_zero_dim} m m m m m m m }
 {
   \__flowfram_only_preamble:Nn \htwotoneright
    {
      \__flowfram_h_two_tone_right:nnnnnnnnn
       { #1 } { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
    }
 }
\@onlypreamble{\htwotoneright}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@htwotoneright}
% Version 2.0 removed \cs{@htwotoneright}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@htwotoneright}
% Version 2.0 replaced \cs{@@htwotoneright}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_h_two_tone_right:nnnnnnnnn
 {
  \computerightedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computerightedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_set:Nn \l__flowfram_evenx_dim { \l__flowfram_x_dim }
  \fi
  \computebottomedge { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_y_dim { #2 }
  \dim_sub:Nn \l__flowfram_x_dim { #3 }
  \dim_sub:Nn \l__flowfram_evenx_dim { #3 }
  \__flowfram_h_two_tone_left:nnnnnnnnn { #1 } { #3 } { #4 } { #5 } { #6 }
  \__flowfram_h_two_tone_left:nnnnnnnnn { #1 } { #3 } { #7 } { #8 } { #9 }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\hNtone}
% Now for \meta{N} coloured horizontal strips
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \hNtone { O{all} O {\c_zero_dim} m }
 {
   \clist_set:Nn \l__flowfram_pages_clist { #1 }
   \__flowfram_h_N_tone_left:nnn  { #2 } { #3 } { \paperwidth }
 }
\@onlypreamble{\hNtone}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@hNtone}
% Version 2.0 removed \cs{@hNtone}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@hNtone}
% Version 2.0 replaced \cs{@@hNtone}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_h_N_tone_left:nnn  
 {
  \computeleftedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computeleftedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_add:Nn \l__flowfram_evenx_dim { \l__flowfram_x_dim }
  \fi
  \computebottomedge { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_y_dim { #1 }
  \int_set:Nn \l__flowfram_this_strip_int { #2 }
  \dim_set:Nn l__flowfram_static_width_dim { #3 }
  \__flowfram_next_h_N_band: 
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\hNtoneleft}
% Now for the N tone strips along the left border
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \hNtoneleft { O{all} O {\c_zero_dim} m m }
 {
   \clist_set:Nn \l__flowfram_pages_clist { #1 }
   \__flowfram_h_N_tone_left:nnn  { #2 } { #3 } { #4 }
 }
\@onlypreamble{\hNtoneleft}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@hNtoneleft}
% Version 2.0 removed \cs{@hNtoneleft}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\hNtoneright}
% Border strip along the right border
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \hNtoneright { O{all} O {\c_zero_dim} m m }
 {
   \clist_set:Nn \l__flowfram_pages_clist { #1 }
   \__flowfram_h_N_tone_right:nnn  { #2 } { #3 } { #4 }
 }
\@onlypreamble{\hNtoneright}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@hNtoneright}
% Version 2.0 removed \cs{@hNtoneright}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@hNtoneright}
% Version 2.0 replaced \cs{@@hNtoneright}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_h_N_tone_right:nnn  
{
  \computerightedgeodd { \l__flowfram_x_dim }
  \if@twoside
    \computerightedgeeven { \l__flowfram_evenx_dim }
  \else
    \dim_set:Nn \l__flowfram_evenx_dim { \l__flowfram_x_dim }
  \fi
  \computebottomedge { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_y_dim { #1 }
  \dim_sub:Nn \l__flowfram_x_dim { #3 }
  \dim_sub:Nn \l__flowfram_evenx_dim { #3 }
  \int_set:Nn \l__flowfram_this_strip_int { #2 }
  \dim_set:Nn \l__flowfram_sfdf_width_dim { #3 }
  \__flowfram_next_h_N_band: 
}
%    \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 "\l__flowfram_x_dim " and "\l__flowfram_y_dim ". 
% On exit, "\l__flowfram_y_dim " is set to the top border.
% Version 2.0 replaced \cs{@nexthband}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_next_h_band:nnnnn
 {
  \dim_set:Nn \l__flowfram_sfdf_height_dim { #3 }
  \tl_if_empty:nTF { #5 }
   {
    \__flowfram_new_static:nnnnn
     { #1 } { #2 } { \l__flowfram_sfdf_height_dim }
     { \l__flowfram_x_dim } { \l__flowfram_y_dim }
   }
   {
    \__flowfram_new_static:nnnnnn
     { #1 } { #2 } { \l__flowfram_sfdf_height_dim }
     { \l__flowfram_x_dim } { \l__flowfram_y_dim }
   }
  \flowfram_frame_set_dim:nnnn { static} { evenx } { \c@maxstatic }
       { \l__flowfram_evenx_dim }
  \__flowfram_set_frame_color:w
    #4 \q_stop { static } { backcolor } { \c@maxstatic }
  \dim_add:Nn \l__flowfram_y_dim { \l__flowfram_sfdf_height_dim }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@nexthNband}
% Get next horizontal strip recursively.
% Version 2.0 renamed \cs{@nexthNband}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_next_h_N_band: 
 {
   \int_compare:nNnTF
      { \l__flowfram_this_strip_int } > { \c_zero_int }
    {
      \let \flf@next \@@nexthNband
    }
    {
      \let \flf@next \relax
    }
  \int_decr:N \l__flowfram_this_strip_int
  \flf@next
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@nexthNband}
%    \begin{macrocode}
\newcommand*{\@@nexthNband}[3]{%
  \__flowfram_h_two_tone_left:nnnnnnnnn
    { \l__flowfram_pages_clist } { \l__flowfram_sfdf_width_dim }
    { #1 } { #2 } { #3 }
  \__flowfram_next_h_N_band: 
}
%    \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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \makebackgroundframe { O{all} o }
 {
   \__flowfram_only_preamble:Nn \NcolumnDbottominarea
    {
      \int_if_zero:nF { \c@maxstatic }
       {
         \msg_warning:nn { flowfram } { background-not-first }
       }
      \computeleftedgeodd { \l__flowfram_x_dim }
      \if@twoside
        \computeleftedgeeven { \l__flowfram_evenx_dim }
      \else
        \dim_set:Nn \l__flowfram_evenx_dim { \l__flowfram_x_dim }
      \fi
      \computebottomedge { \l__flowfram_y_dim }
       \IfValueTF { #2 }
        {
          \__flowfram_new_static:nnnnnn
            { #1 } { \paperwidth }{ \paperheight }
            { \l__flowfram_x_dim } { \l__flowfram_y_dim }
            { #2 }
        }
        {
          \__flowfram_new_static:nnnnn
            { #1 } { \paperwidth } { \paperheight }
            { \l__flowfram_x_dim } { \l__flowfram_y_dim }
        }
      \flowfram_frame_set_dim:nnnn { static} { evenx } { \c@maxstatic }
        { \l__flowfram_evenx_dim }
   }
}
%    \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. The starred version uses the label for the id.
%The first optional argument \meta{y-top} extends the rule by that
%much above the highest point. The second optional argument
%\meta{y-bottom} extends the rule by that much below the lowest
%point.
%Syntax:
%\cs{insertvrule}*\oarg{y-top}\oarg{y-bottom}\marg{type-1}\marg{id}\marg{type-2}\marg{id}
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \insertvrule
   { s O { \c_zero_dim } O { \c_zero_dim } m m m m }
 {
   \__flowfram_only_preamble:Nn \insertvrule
    {
      \__flowfram_get_frame_type:n { #4 }
      \__flowfram_get_frame_type:Nn
          \l__flowfram_type_ii_int
          { #6 }
      \bool_lazy_or:nnF
         {
           \int_compare_p:nNn
             { \l__flowfram_type_int } = { -\c_one_int }
         }
         {
           \int_compare_p:nNn
             { \l__flowfram_type_ii_int } = { -\c_one_int }
         }
       {
         \IfBooleanTF { #1 }
          {
            \use:c { __flowfram_get_ #6 _id:e } { #7 }
            \int_set_eq:NN \l__flowfram_id_ii_int \l__flowfram_id_int 
            \use:c { __flowfram_get_ #4 _id:e } { #5 }
            \__flowfram_insert_v_rule:nnNnNn
              { #2 } { #3 }
              \l__flowfram_type_int { \l__flowfram_id_int }
              \l__flowfram_type_ii_int { \l__flowfram_id_ii_int }
          }
          {
            \__flowfram_insert_v_rule:nnNnNn
              { #2 } { #3 }
              \l__flowfram_type_int { #5 }
              \l__flowfram_type_ii_int { #7 }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@insertvrule}
% Version 2.0 removed \cs{@insertvrule},
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
% Need some lengths:
%\begin{macro}{\@ff@left@x}
% Version 2.0 replaced \cs{@ff@left@x}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\dim_new:N \l__flowfram_left_x_dim 
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@left@y}
% Version 2.0 replaced \cs{@ff@left@y}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\dim_new:N \l__flowfram_left_y_dim 
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@left@evenx}
% Version 2.0 replaced \cs{@ff@left@evenx}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\dim_new:N \l__flowfram_left_evenx_dim 
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@left@eveny}
% Version 2.0 replaced \cs{@ff@left@eveny}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\dim_new:N \l__flowfram_left_eveny_dim 
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@left@width}
% Version 2.0 replaced \cs{@ff@left@width}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\dim_new:N \l__flowfram_left_width_dim 
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@left@height}
% Version 2.0 replaced \cs{@ff@left@height}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\dim_new:N \l__flowfram_left_height_dim 
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@@insertvrule}
% Version 2.0 removed \cs{@@insertvrule}.
%\changes{2.0}{2025-11-24}{removed}
%\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
%\marg{y-top}\marg{y-bottom}\meta{type-1 int}\marg{idn}\meta{type-2 int}\marg{idn}
% Version 2.0 replaced \cs{@@insert@vrule}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_insert_v_rule:nnNnNn
 {
  \__flowfram_get_frame_bounds_by_typeid:nn { #3 } { #4 }
  \dim_set_eq:NN \l__flowfram_left_x_dim \ffareax 
  \dim_set_eq:NN \l__flowfram_left_y_dim \ffareay
  \dim_set_eq:NN \l__flowfram_left_width_dim \ffareawidth 
  \dim_set_eq:NN \l__flowfram_left_height_dim \ffareaheight
  \__flowfram_get_frame_bounds_by_typeid:nn { #5 } { #6 }
  \dim_compare:nNnT
     { \l__flowfram_left_x_dim } > { \ffareax }
   {
     \__flowfram_swap_dim:NN \l__flowfram_left_x_dim \ffareax
     \__flowfram_swap_dim:NN \l__flowfram_left_y_dim \ffareax
     \__flowfram_swap_dim:NN \l__flowfram_left_evenx_dim \ffareaevenx
     \__flowfram_swap_dim:NN \l__flowfram_left_eveny_dim \ffareaevenx
     \__flowfram_swap_dim:NN \l__flowfram_left_width_dim \ffareawidth
     \__flowfram_swap_dim:NN \l__flowfram_left_height_dim \ffareaheight
   }
  \dim_set:Nn \l__flowfram_x_dim 
    {
        \l__flowfram_left_x_dim
      + \l__flowfram_left_width_dim
    }
  \dim_set:Nn \l__flowfram_sfdf_width_dim 
    {
       \ffareax - \l__flowfram_x_dim
    }
  \dim_set:Nn \l__flowfram_sfdf_height_dim
    {
        \l__flowfram_left_y_dim
      + \l__flowfram_left_height_dim
    }
  \dim_set:Nn \l__flowfram_y_dim
    {
      \ffareay + \ffareaheight
    }
  \dim_compare:nNnT
     { \l__flowfram_y_dim } > { \l__flowfram_sfdf_height_dim }
   {
     \dim_set_eq:NN \l__flowfram_sfdf_height_dim \l__flowfram_y_dim 
   }
  \dim_compare:nNnTF
     { \l__flowfram_left_y_dim } < { \ffareay }
   {
     \dim_set_eq:NN \l__flowfram_y_dim \l__flowfram_left_y_dim 
   }
   {
     \dim_set_eq:NN \l__flowfram_y_dim \ffareay
   }
  \dim_add:Nn \l__flowfram_sfdf_height_dim
    {
      - \l__flowfram_y_dim
    }
  \__flowfram_new_static:nnnnn
    { all } 
    { \l__flowfram_sfdf_width_dim }
    { \l__flowfram_sfdf_height_dim }
    { \l__flowfram_x_dim }
    { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_sfdf_height_dim
    {
      #1 + #2 
    }
  \setstaticcontents { \c@maxstatic }
   {
     \ffruledeclarations
     \ffvrule { #2 } { \ffcolumnseprule }
     { \l__flowfram_sfdf_height_dim }
   }
  \int_case:nn { #3 }
   {
     { \c_flowfram_frame_type_flow_int }
       {
         \flowfram_set_clist_to_frame_clist:Nnnn
           \l__flowfram_pages_clist 
           { flow } { pagelist } { #4 }
       } 
     { \c_flowfram_frame_type_static_int }
       {
         \flowfram_set_clist_to_frame_clist:Nnnn
           \l__flowfram_pages_clist 
           { static } { pagelist } { #4 }
       } 
     { \c_flowfram_frame_type_dynamic_int }
       {
       \flowfram_set_clist_to_frame_clist:Nnnn
         \l__flowfram_pages_clist 
         { dynamic } { pagelist } { #4 }
     }
   }
  \setstaticframe { \c@maxstatic }
    { pages = \l__flowfram_pages_clist }
%    \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}
  \dim_add:Nn \l__flowfram_x_dim 
   { 
       \l__flowfram_left_evenx_dim
     - \l__flowfram_left_x_dim
   }
  \dim_add:Nn \l__flowfram_y_dim 
   {
      \l__flowfram_left_eveny_dim
    - \l__flowfram_left_y_dim
   }
  \setstaticframe { \c@maxstatic }
    {
      evenx=\l__flowfram_x_dim ,
      eveny=\l__flowfram_y_dim
    }
}
%    \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}
% Version 2.0 removed \cs{@sinsertvrule}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@sinsertvrule}
% Version 2.0 removed \cs{@@sinsertvrule}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\inserthrule}
% Now for a horizontal rule. Syntax similar to "\insertvrule".
%Syntax:
%\cs{inserthrule}*\oarg{x-left}\oarg{x-right}\marg{type-1}\marg{id}\marg{type-2}\marg{id}
%    \begin{macrocode}
\NewDocumentCommand \inserthrule
   { s O { \c_zero_dim } O { \c_zero_dim } m m m m }
 {
   \__flowfram_only_preamble:Nn \inserthrule
    {
      \__flowfram_get_frame_type:n { #4 }
      \__flowfram_get_frame_type:Nn
          \l__flowfram_type_ii_int
          { #6 }
      \bool_lazy_or:nnF
         {
           \int_compare_p:nNn
             { \l__flowfram_type_int } = { -\c_one_int }
         }
         {
           \int_compare_p:nNn
             { \l__flowfram_type_ii_int } = { -\c_one_int }
         }
       {
         \IfBooleanTF { #1 }
          {
            \use:c { __flowfram_get_ #6 _id:e } { #7 }
            \int_set_eq:NN \l__flowfram_id_ii_int \l__flowfram_id_int 
            \use:c { __flowfram_get_ #4 _id:e } { #5 }
            \__flowfram_insert_h_rule:nnNnNn
              { #2 } { #3 }
              \l__flowfram_type_int { \l__flowfram_id_int }
              \l__flowfram_type_ii_int { \l__flowfram_id_ii_int }
          }
          {
            \__flowfram_insert_h_rule:nnNnNn
              { #2 } { #3 }
              \l__flowfram_type_int { #5 }
              \l__flowfram_type_ii_int { #7 }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@inserthrule}
% Version 2.0 removed \cs{@inserthrule}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@inserthrule}
% Version 2.0 removed \cs{@@inserthrule}.
%\changes{2.0}{2025-11-24}{removed}
%\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
%\marg{x left}\marg{x right}\marg{type ID}\marg{IDN}\marg{type ID}\marg{IDN}.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_insert_h_rule:nnNnNn
 {
  \__flowfram_get_frame_bounds_by_typeid:nn { #3 } { #4 }
  \dim_set_eq:NN \l__flowfram_left_x_dim \ffareax
  \dim_set_eq:NN \l__flowfram_left_y_dim \ffareay
  \dim_set_eq:NN \l__flowfram_left_width_dim \ffareawidth
  \dim_set_eq:NN \l__flowfram_left_height_dim \ffareaheight
  \__flowfram_get_frame_bounds_by_typeid:nn { #5 } { #6 }
  \dim_compare:nNnT
      { \l__flowfram_left_y_dim } > { \ffareay }
   {
    \__flowfram_swap_dim:NN \l__flowfram_left_x_dim \ffareax
    \__flowfram_swap_dim:NN \l__flowfram_left_y_dim \ffareay
    \__flowfram_swap_dim:NN \l__flowfram_left_width_dim \ffareawidth
    \__flowfram_swap_dim:NN \l__flowfram_left_height_dim \ffareaheight
   }
  \dim_set:Nn \l__flowfram_y_dim 
    {
      \l__flowfram_left_y_dim
      + \l__flowfram_left_height_dim
    }
  \dim_set:Nn \l__flowfram_sfdf_height_dim
    { 
      \ffareay - \l__flowfram_y_dim
    }
  \dim_set:Nn \l__flowfram_sfdf_width_dim 
    {
        \l__flowfram_left_x_dim
      + \l__flowfram_left_width_dim
    }
  \dim_set:Nn \l__flowfram_x_dim 
    {
      \ffareax + \ffareawidth
    }
  \dim_compare:nNnT
      { \l__flowfram_x_dim }  > { \l__flowfram_sfdf_width_dim }
   {
     \dim_set:Nn \l__flowfram_sfdf_width_dim { \l__flowfram_x_dim }
   }
  \dim_compare:nNnTF
      { \l__flowfram_left_x_dim } < { \ffareax }
   {
     \dim_set:Nn \l__flowfram_x_dim { \l__flowfram_left_x_dim }
   }
   {
     \dim_set:Nn \l__flowfram_x_dim { \ffareax }
   }
  \dim_add:Nn \l__flowfram_sfdf_width_dim 
   {
      - \l__flowfram_x_dim
   }
  \__flowfram_new_static:nnnnn
    { all }
    { \l__flowfram_sfdf_width_dim }
    { \l__flowfram_sfdf_height_dim }
    { \l__flowfram_x_dim }
    { \l__flowfram_y_dim }
  \dim_add:Nn \l__flowfram_sfdf_width_dim 
    { #1 + #2 }
  \setstaticcontents { \c@maxstatic }
   {
     \ffruledeclarations
     \ffhrule { #1 } { \l__flowfram_sfdf_width_dim } { \ffcolumnseprule }
   }
  \int_case:nn { #3 }
   {
     { \c_flowfram_frame_type_flow_int }
       {
         \flowfram_set_clist_to_frame_clist:Nnnn
           \l__flowfram_pages_clist 
            { flow } { pagelist } { #4 }
       }
     { \c_flowfram_frame_type_static_int }
       {
         \flowfram_set_clist_to_frame_clist:Nnnn
           \l__flowfram_pages_clist 
           { static } { pagelist } { #4 }
       } 
     { \c_flowfram_frame_type_dynamic_int }
       {
         \flowfram_set_clist_to_frame_clist:Nnnn
           \l__flowfram_pages_clist 
           { dynamic } { pagelist } { #4 }
       }
   }
  \setstaticframe { \c@maxstatic }
    { pages = \clist_use:N \l__flowfram_pages_clist }
  \dim_add:Nn \l__flowfram_x_dim 
    {
       \l__flowfram_left_evenx_dim
     - \l__flowfram_left_x_dim
    }
  \dim_add:Nn \l__flowfram_y_dim 
    {
        \l__flowfram_left_eveny_dim
      - \l__flowfram_left_y_dim
    }
  \setstaticframe {\c@maxstatic}
    {
      evenx = \l__flowfram_x_dim ,
      eveny = \l__flowfram_y_dim
    }
}
%    \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}
% Version 2.0 removed \cs{@sinserthrule}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@@sinserthrule}
% Version 2.0 removed \cs{@@sinserthrule}.
%\changes{2.0}{2025-11-24}{removed}
%\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}.
%\changes{2.0}{2025-11-24}{changed to document command}
%
%This is implemented by redefining \cs{@makechapterhead}
%and \cs{@makeschapterhead} so that they place their argument in the
%applicable dynamic frame. Unfortunately this causes a problem if a
%class doesn't use these commands. As from v2.0, an alternative
%approach is available but the original method is retained.
%    \begin{macrocode}
\NewDocumentCommand \dfchaphead { s m }
{
  \cs_if_exist:NTF \chapter
   {
     \IfBooleanTF { #1 }
      {
        \__flowfram_get_dynamic_id:n { #2 }
      }
      {
        \int_set:Nn \l__flowfram_id_int { #2 }
      }
%    \end{macrocode}
% Store current chapter head definitions for starred and unstarred
% versions
%    \begin{macrocode}
       \let\@ff@OLDmakechapterhead\@makechapterhead
       \let\@ff@OLDmakeschapterhead\@makeschapterhead
%    \end{macrocode}
% Define user commands that can be redefined to modify the chapter
% head style (in the event that the user is using a class that
% doesn't provide an easy means to do this.)
%    \begin{macrocode}
       \renewcommand{\DFchapterstyle}[1]{\@ff@OLDmakechapterhead{##1}}%
       \renewcommand{\DFschapterstyle}[1]{\@ff@OLDmakeschapterhead{##1}}%
%    \end{macrocode}
% Redefine chapter heads so that they put their contents in the
% requested dynamic frame. First the unstarred version:
%    \begin{macrocode}
       \xdef\@makechapterhead##1{%
         \exp_not:N 
            \__flowfram_set_dynamic_contents:nn
           { \int_use:N \l__flowfram_id_int }
         {
           \noexpand\DFchapterstyle { ##1 }
         }
       }
%    \end{macrocode}
% Now the starred version:
%    \begin{macrocode}
       \xdef\@makeschapterhead##1{%
         \exp_not:N \__flowfram_set_dynamic_contents:nn
           { \int_use:N \l__flowfram_id_int }
         {
           \noexpand \DFschapterstyle { ##1 }
         }
       }
   }
   {
     \msg_error:nn { flowfram } { no-chapters }
   }
}
%    \end{macrocode}
%\end{macro}
%
% Define style for the chapter heading. These commands
% are only used with \cs{dfchaphead}.
%\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{macrocode}
\int_new:N \g__flowfram_chaphead_frame_id
%    \end{macrocode}
%
%\begin{macro}{\ChapterInDynamic}
%An alternative to \cs{dfchaphead} that doesn't alter \cs{@makechapterhead}
%and \cs{@makeschapterhead}.
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\NewDocumentCommand \ChapterInDynamic { s m }
{
  \cs_if_exist:NTF \chapter
   {
     \IfBooleanTF { #1 }
      {
        \__flowfram_get_dynamic_id:e { #2 }
         \int_gset_eq:NN
           \g__flowfram_chaphead_frame_id
           \l__flowfram_id_int
      }
      {
        \int_gset:Nn \g__flowfram_chaphead_frame_id { #2 }
      }
     \__flowfram_make_chapter_head:n { \g__flowfram_chaphead_frame_id }
   }
   {
     \msg_error:nn { flowfram } { no-chapters }
   }
}
%    \end{macrocode}
%\end{macro}
%
%With the alternative approach, \cs{chapter} command is placed in the dynamic
%frame content instead of redefining the internal commands to put
%their argument in the dynamic frame. There are a number of problems with this:
%the initial clear page (or clear double page) can't go in the
%\cs{parbox} used by the dynamic frame. If there are any sections that
%follow the chapter heading on the same page their numbering will be
%out of sync as the dynamic contents aren't typeset until the page
%is output. So this approach first typesets the chapter heading in a
%box (having locally disabled the problematic commands) and then
%places the box in the dynamic contents. This rather goes against
%the idea that dynamic frames don't typeset their content until the
%page is output, but it's the simplest way around it that avoids
%messing around with internals that may break certain classes.
%Extra content can still be appended to the dynamic frame (which
%can't be done in a static frame.
%
%Replicate report and book class \cs{@makechapterhead} and
%\cs{@makeschapterhead} to test if those definitions currently
%apply. This means they can be redefined to remove the hard-coded
%top vertical space and allow more flexibility. Other classes, such
%as memoir and the KOMA Script classes have their own hooks so don't
%worry about them.
%    \begin{macrocode}
\ExplSyntaxOff
\newcommand*\@flowfram@standard@makechapterhead[1]{%
 \vspace *{50\p@ }%
 {\parindent \z@ \raggedright \normalfont
   \ifnum \c@secnumdepth >\m@ne
     \if@mainmatter \huge \bfseries \@chapapp \space \thechapter
       \par
       \nobreak \vskip 20\p@
     \fi
   \fi
   \interlinepenalty \@M
   \Huge \bfseries #1\par
   \nobreak
   \vskip 40\p@
}}
\ExplSyntaxOn
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_if_exist:NTF \chapter
 {
%    \end{macrocode}
%Redefine \cs{@makechapterhead} and \cs{@makeschapterhead} if they
%have the book or report definition to allow for greater
%flexibility. Only testing the definition of \cs{@makechapterhead}.
%This assumes that if that definition matches the standard classes
%then it's likely that \cs{@makeschapterhead} will also be the
%standard definition.
%    \begin{macrocode}
   \cs_if_eq:NNT \@makechapterhead \@flowfram@standard@makechapterhead
    {
%    \end{macrocode}
%\begin{macro}{\ffchapterpreheadskip}
%    \begin{macrocode}
       \newcommand \ffchapterpreheadskip
        {
          \vspace *{50\p@ }
        }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffchapterpostheadskip}
%    \begin{macrocode}
       \newcommand \ffchapterpostheadskip
        {
          \vspace *{40\p@ }
        }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffchapterheadstyle}
%    \begin{macrocode}
       \newcommand \ffchapterheadstyle
       {
         \parindent \z@ \raggedright
       }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffchapternamenumfont}
%    \begin{macrocode}
       \newcommand \ffchapternamenumfont [ 1 ] { { \huge #1 } }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffchapternamenum}
%    \begin{macrocode}
       \newcommand \ffchapternamenum [ 2 ]
        {
          #1 \space #2
        }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffchapterpostnamenum}
%    \begin{macrocode}
       \newcommand \ffchapterpostnamenum
        {
          \par
          \nobreak
          \vspace *{20\p@ }
        }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\ffchaptertitlefont}
%    \begin{macrocode}
       \newcommand \ffchaptertitlefont [ 1 ] { { \Huge #1 } }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffchapterdefaultfont}
%    \begin{macrocode}
       \newcommand{\ffchapterdefaultfont}{\normalfont \bfseries}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@makechapterhead}
%    \begin{macrocode}
      \renewcommand*\@makechapterhead[1]
       {
        \ffchapterpreheadskip
        {
          \ffchapterheadstyle
          \ffchapterdefaultfont
          \ifnum \c@secnumdepth >\m@ne
           \if@mainmatter
              \ffchapternamenumfont
               {
                 \ffchapternamenum { \@chapapp } { \thechapter }
                 \ffchapterpostnamenum
               }
           \fi
         \fi
         \interlinepenalty \@M
         \ffchaptertitlefont { #1 \par }
         \nobreak
         \ffchapterpostheadskip
        }
       }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@makeschapterhead}
%    \begin{macrocode}
      \renewcommand*\@makeschapterhead[1]
       {
        \ffchapterpreheadskip
        {
          \ffchapterheadstyle
          \ffchapterdefaultfont
          \interlinepenalty \@M
          \ffchaptertitlefont { #1 \par }
          \nobreak
          \ffchapterpostheadskip
        }
       }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
    }
%    \end{macrocode}
%\begin{macro}{\dfchapterclearpage}
%    \begin{macrocode}
   \cs_if_exist:NTF \if@openright
    {
      \newcommand \dfchapterclearpage
       {
         \legacy_if:nTF { @openright }
           {
             \cleardoublepage
           }
           {
             \clearpage
           }
       }
    }
    {
      \newcommand \dfchapterclearpage
       {
         \clearpage
       }
    }
%    \end{macrocode}
%\end{macro}
%Box used to store the chapter heading:
%    \begin{macrocode}
   \newsavebox \flowfram@dfchap@sbox
%    \end{macrocode}
%Hooks for use within the box:
%    \begin{macrocode}
   \NewMirroredHookPair
     { flowfram / chaphead / before }
     { flowfram / chaphead / after }
   \NewMirroredHookPair
     { flowfram / chaphead / box / before }
     { flowfram / chaphead / box / after }
%    \end{macrocode}
%If \cs{ffchapterpreheadskip} is defined, redefine to do nothing at
%the start of the box:
%    \begin{macrocode}
   \cs_if_exist:NT \ffchapterpreheadskip
    {
      \AddToHook
       { flowfram / chaphead / box / before }
       {
         \let \ffchapterpreheadskip \relax
       }
    }
%    \end{macrocode}
%Gather toc lines so they can be expanded straight away:
%    \begin{macrocode}
   \tl_new:N \g__flowfram_df_chapter_lines_tl
   \cs_new:Nn \__flowfram_df_addcontentsline:nnn
    {
      \tl_gput_right:Nn \g__flowfram_df_chapter_lines_tl
       {
         \addcontentsline { #1 } { #2 } { #3 }
       }
    }
   \cs_new:Nn \__flowfram_df_markright:n
    {
      \tl_gput_right:Nn \g__flowfram_df_chapter_lines_tl
       {
         \markright { #1 }
       }
    }
   \cs_new:Nn \__flowfram_df_markboth:nn
    {
      \tl_gput_right:Nn \g__flowfram_df_chapter_lines_tl
       {
         \markboth { #1 } { #2 }
       }
    }
%    \end{macrocode}
%The box needs to have the same width as the dynamic frame.
%    \begin{macrocode}
   \dim_new:N \l__flowfram_df_chapbox_head_width_dim
%    \end{macrocode}
%The argument is the actual chapter command (with its arguments):
%    \begin{macrocode}
   \cs_new:Nn \__flowfram_df_chapter:n
    {
      \dfchapterclearpage
      \tl_gclear:N \g__flowfram_df_chapter_lines_tl
      \flowfram_set_dim_to_frame_dim:Nnnn
        \l__flowfram_df_chapbox_head_width_dim
         { dynamic } { width } { \g__flowfram_chaphead_id_int }
      \UseHook { flowfram / chaphead / before }
      \sbox \flowfram@dfchap@sbox
       {
%    \end{macrocode}
%Set the frame's text colour:
%    \begin{macrocode}
         \flowfram_set_tl_to_frame_tl:Nnnn
           \l__flowfram_textcolor_tl
           { dynamic } { textcolor } { \g__flowfram_chaphead_id_int }
         \__flowfram_set_text_color:
%    \end{macrocode}
%Typeset the heading in a parbox:
%    \begin{macrocode}
         \parbox 
           { \l__flowfram_df_chapbox_head_width_dim }
           {
             \let \clearpage \relax
             \let \cleardoublepage \relax
             \let \onecolumn \relax
             \@twocolumnfalse
             \let \addcontentsline \__flowfram_df_addcontentsline:nnn
             \let \markright \__flowfram_df_markright:n
             \let \markboth \__flowfram_df_markboth:nn
             \UseHook { flowfram / chaphead / box / before }
             #1
%    \end{macrocode}
%The scoping introduced by the \cs{parbox} interferes with
%KOMA's local redefinition of \cs{@currenttocentry}, so if this
%command is defined, ensure that its definition is still available
%outside this box.
%    \begin{macrocode}
             \tl_if_exist:NT \@currenttocentry
              {
                \tl_gset:Ne \@currenttocentry { \@currenttocentry }
              }
             \UseHook { flowfram / chaphead / box / after }
           }
       }
      \__flowfram_set_dynamic_contents:nn
        { \g__flowfram_chaphead_id_int }
        {
          \box_use_drop:N \flowfram@dfchap@sbox
          \@afterheading
        }
      \g__flowfram_df_chapter_lines_tl
      \tl_gclear:N \g__flowfram_df_chapter_lines_tl
      \UseHook { flowfram / chaphead / after }
    }
%    \end{macrocode}
%Unstarred chapter with one optional argument.
%    \begin{macrocode}
   \cs_new:Nn \__flowfram_df_chapter:nn
    {
      \__flowfram_df_chapter:n
       {
          \__flowfram_org_chapter: [ #1 ] { #2 }
       }
    }
%    \end{macrocode}
%Unstarred chapter with two optional arguments.
%    \begin{macrocode}
   \cs_new:Nn \__flowfram_df_chapter:nnn
    {
      \__flowfram_df_chapter:n
       {
          \__flowfram_org_chapter: [ #1 ] [ #2 ] { #3 }
       }
    }
%    \end{macrocode}
%Starred chapter.
%    \begin{macrocode}
   \cs_new:Nn \__flowfram_df_chapter_star:nn
    {
      \__flowfram_df_chapter:n
       {
          \flowfram_nonum_section:Nnn
           \__flowfram_org_chapter:  { #1 } { #2 }
       }
    }
%    \end{macrocode}
%Return true if the argument is "chapter" and a dynamic frame has
%been identified for chapter headings.
%    \begin{macrocode}
   \prg_new_conditional:Nnn \__flowfram_if_df_chapter:n
     { T, F, TF }
    {
      \int_if_zero:nTF { \g__flowfram_chaphead_id_int }
       { \prg_return_false: }
       {
         \tl_if_eq:nnTF { #1 } { chapter }
          { \prg_return_true: }
          { \prg_return_false: }
       }
    }
 }
 {
%    \end{macrocode}
%Always returns false as there are no chapters.
%    \begin{macrocode}
   \prg_new_conditional:Nnn \__flowfram_if_df_chapter:n
     { T, F, TF }
    {
      \prg_return_false: 
    }
 }
%    \end{macrocode}
%\begin{macro}{\@dynamicchap}
% Version 2.0 replaced \cs{@dynamicchap}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_make_chapter_head:n
 {
   \int_set:Nn \g__flowfram_chaphead_id_int { #1 }
 }
\int_new:N \g__flowfram_chaphead_id_int
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sdynamicchap}
% Version 2.0 removed \cs{@sdynamicchap}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\NoChapterInDynamic}
%\changes{2.0}{2025-11-24}{new}
%Revert back.
%    \begin{macrocode}
\NewDocumentCommand \NoChapterInDynamic { }
 {
   \int_zero:N \g__flowfram_chaphead_id_int
 }
%    \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}
\cs_if_exist:NTF \chapter
 {
   \newcommand*{\defaultthumbtabtype}{chapter}
 }
 {
   \newcommand*{\defaultthumbtabtype}{section}
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@type}
% Section type to assign to thumbtabs.
% Version 2.0 renamed \cs{@ttb@type}
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\tl_new:N \g__flowfram_thumbtab_type_tl
\tl_gset:Nn \g__flowfram_thumbtab_type_tl
   { \defaultthumbtabtype }
%    \end{macrocode}
%\end{macro}
%
%The table of contents isn't read until the start of the
%document, but the thumbtabs are created in the preamble, so the toc
%information can't be used as it will be too late by the time it's
%read. This means a separate file is required.
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_ttb_num:n
 {
   \addtocontents {ttb}
    {
      \protect \thumbtab
       { \theFramePageCounter }
       { \arabic { \g__flowfram_thumbtab_type_tl } }
       { #1 } 
       { \@currentHref }
    }
 }
%    \end{macrocode}
%
%Provide a counter for unnumbered tabs.
%    \begin{macrocode}
\newcounter{thumbtabnonum}
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_ttb_nonum:n 
 {
   \bool_if:NT \g__flowfram_save_nonum_thumbtabs_bool
    {
      \refstepcounter { thumbtabnonum }
      \addtocontents { ttb }
       {
        \protect \thumbtab
          { \theFramePageCounter }
          { }
          { #1 }
          { thumbtabnonum . \thethumbtabnonum }
       }
    }
 }
%    \end{macrocode}
%
%\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}.
%
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \makethumbtabs
  { O { \c_zero_dim } m O { \defaultthumbtabtype } }
 {
   \exp_args:Nnne
    \__flowfram_make_thumbtabs:nnn { #1 } { #2 } { #3 }
   \cs_set:Nn \__flowfram_make_thumbtabs:nnn
    {
      \msg_note:nn { flowfram } { ignoring-multiple-makethumbtabs }
    }
 }
%    \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.
% Version 2.0 replaced \cs{@makethumbtabs}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_make_thumbtabs:nnn
 {
  \cs_if_exist:cTF { #3 }
   {
      \tl_gset:Ne \g__flowfram_thumbtab_type_tl  { #3 }
      \@starttoc { ttb }
      \__flowfram_create_thumbtabs:nn { #1 } { #2 }
      \cs_set:Nn \__flowfram_write_backmatter_ttb:
       {
         \addtocontents {ttb}
          {
            \protect \thumbtab@backmatter
              { \theFramePageCounter }
          }
       }
    \cs_set:Nn \__flowfram_no_thumbtabs_warn:
     {
       \msg_warning:nn { flowfram } { no-thumbtabs-rerun } 
     }
   }
   {
     \msg_error:nnn { flowfram } { section-unit-not-defined } { #3 }
   }
}
%    \end{macrocode}
%\end{macro}
%Warning to produce if no thumbtabs:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_no_thumbtabs_warn:
 {
   \msg_warning:nn { flowfram } { no-thumbtabs-missing-makethumbtabs } 
 }
%    \end{macrocode}
%Write the page number to the ttb file when \cs{backmatter} is used
%to get the end page range if not thumbtabs in backmatter.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_write_backmatter_ttb:
 {
 }
%    \end{macrocode}
%
%\begin{macro}{\@makethumbchapter}
% Version 2.0 removed \cs{@makethumbchapter}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@makethumbpart}
% Version 2.0 removed \cs{@makethumbpart}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@makethumbsection}
% Version 2.0 removed \cs{@makethumbsection}
%\changes{2.0}{2025-11-24}{removed}
%\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. The table of contents needs to be read first
% to pick up any unnumbered sections that should be included.
%Syntax: \marg{page}\marg{unit num}\marg{title}\marg{target}
%    \begin{macrocode}
\newcommand{\thumbtab}[4]{%
  \stepcounter { maxthumbtabs }
  \__flowfram_message:nnnnn { info-found-thumbtab }
    { #1 } { #2 } { #3 } { #4 }
  \tl_new:c { g__thumbtab_ \romannumeral \c@maxthumbtabs _pages_tl }
  \int_new:c { g__thumbtab_ \romannumeral \c@maxthumbtabs _start_int }
  \int_gset:cn { g__thumbtab_ \romannumeral \c@maxthumbtabs _start_int }
    { #1 }
  \tl_new:c { g__thumbtab_ \romannumeral \c@maxthumbtabs _unitnum_tl }
  \tl_gset:cn
    { g__thumbtab_ \romannumeral \c@maxthumbtabs _unitnum_tl }
    { #2 }
  \tl_new:c { g__thumbtab_ \romannumeral \c@maxthumbtabs _title_tl }
  \tl_gset:cn { g__thumbtab_ \romannumeral \c@maxthumbtabs _title_tl }
    { #3 }
  \tl_new:c { g__thumbtab_ \romannumeral \c@maxthumbtabs _link_tl }
  \tl_gset:cn { g__thumbtab_ \romannumeral \c@maxthumbtabs _link_tl }
    { #4 }
  \tl_gclear:N \g__flowfram_ttb_endpage_tl
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\thumbtab@backmatter}
%    \begin{macrocode}
\tl_new:N \g__flowfram_ttb_endpage_tl
\newcommand{\thumbtab@backmatter}[1]{%
  \tl_gset:Ne \g__flowfram_ttb_endpage_tl { \int_eval:n { #1 - \c_one_int } }
}
%    \end{macrocode}
%\end{macro}
%
%Use the thumbtab information.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_thumbtab_start:n
 {
   \int_use:c { g__thumbtab_ \romannumeral #1 _start_int }
 }
\cs_new:Nn \__flowfram_thumbtab_unitnum:n
 {
   \tl_use:c { g__thumbtab_ \romannumeral #1 _unitnum_tl }
 }
\cs_new:Nn \__flowfram_thumbtab_pages:n
 {
   \tl_use:c { g__thumbtab_ \romannumeral #1 _pages_tl }
 }
\cs_new:Nn \__flowfram_thumbtab_set_pages:nn
 {
   \tl_gset:cn { g__thumbtab_ \romannumeral #1 _pages_tl }
     { #2 }
 }
\cs_generate_variant:Nn \__flowfram_thumbtab_set_pages:nn { ne }
\cs_new:Nn \__flowfram_thumbtab_title:n
 {
   \tl_use:c { g__thumbtab_ \romannumeral #1 _title_tl }
 }
%    \end{macrocode}
%\begin{macro}{\SetThumbTabTitle}
%The title for individual thumbtabs may be changed.
%\changes{2.0}{2025-11-24}{new}
%    \begin{macrocode}
\NewDocumentCommand \SetThumbTabTitle { m m }
 {
   \tl_if_exist:cTF { g__thumbtab_ \romannumeral #1 _title_tl }
    {
      \tl_gset:cn { g__thumbtab_ \romannumeral #1 _title_tl } { #2 }
    }
    {
      \msg_warning:nnn { flowfram } { cant-find-thumbtab } { #1 }
    }
 }
%    \end{macrocode}
%\end{macro}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_thumbtab_link:n
 {
   \tl_use:c { g__thumbtab_ \romannumeral #1 _link_tl }
 }
%    \end{macrocode}
%
%\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 variable
% 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 should
% 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: \marg{y offset}\marg{height}.
% Version 2.0 replaced \cs{@dothumbtabs}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_create_thumbtabs:nn
 {
   \dim_set:Nn \l__flowfram_y_dim
     {
       \typeblockheight - ( #2 ) - ( #1 )
     }
   \computerightedgeodd { \l__flowfram_x_dim }
   \dim_sub:Nn \l__flowfram_x_dim { \thumbtabwidth }
   \computeleftedgeeven { \l__flowfram_evenx_dim }
   \int_step_inline:nn { \c@maxthumbtabs }
    {
%    \end{macrocode}
%First set the data obtained from the ttb file:
%    \begin{macrocode}
      \int_set:Nn \l__flowfram_range_start_int
        {
          \__flowfram_thumbtab_start:n { ##1 }
        }
      \int_compare:nNnTF { ##1 } = { \c@maxthumbtabs }
        {
          \tl_if_empty:NTF \g__flowfram_ttb_endpage_tl
           {
             \__flowfram_thumbtab_set_pages:ne { ##1 }
               {
                  \int_use:N \l__flowfram_range_start_int ,
                  > \int_use:N \l__flowfram_range_start_int 
               }
           }
           {
             \__flowfram_thumbtab_set_pages:ne { ##1 }
               {
                  \int_use:N \l__flowfram_range_start_int 
                  - \g__flowfram_ttb_endpage_tl
               }
           }
        }
        {
%    \end{macrocode}
%Last page of this thumbtab is likely to be one less then the start of the next
%thumbtab.
%    \begin{macrocode}
          \int_set:Nn \l__flowfram_range_end_int
            {
              \__flowfram_thumbtab_start:n
                { \int_eval:n {  ##1 + \c_one_int } }
            }
          \int_decr:N \l__flowfram_range_end_int
          \int_compare:nNnTF
              { \l__flowfram_range_end_int }
               >
              { \l__flowfram_range_start_int }
            {
              \__flowfram_thumbtab_set_pages:ne { ##1 }
               {
                 \int_use:N \l__flowfram_range_start_int 
                 - \int_use:N \l__flowfram_range_end_int
               }
            }
            {
              \__flowfram_thumbtab_set_pages:ne { ##1 }
               {
                 \int_use:N \l__flowfram_range_start_int 
               }
            }
        }
%    \end{macrocode}
%Now create the dynamic frames associated with this thumbtab:
%    \begin{macrocode}
     \__flowfram_create_thumbtab:nn { ##1 } { #2 }
   }
%    \end{macrocode}
% Now that all thumbtabs have been defined, set the page lists:
%    \begin{macrocode}
   \bool_if:NTF \g__flowfram_has_bespoke_thumbtabs_bool
    {
      \int_step_inline:nn { \c@maxthumbtabs }
       {
         \exp_args:Nnee
         \__flowfram_set_thumbtab_pagelist:nnn { ##1 }
          {
            \seq_item:Nn \g__flowfram_thumbtab_seq { ##1 }
          }
          {
            \seq_item:Nn \g__flowfram_even_thumbtab_seq { ##1 }
          }
         \flowfram_frame_set_bool_true:nnn
           { dynamic } { hide }
           {
             \seq_item:Nn \g__flowfram_thumbtab_seq { ##1 }
           }
         \flowfram_frame_set_bool_true:nnn
           { dynamic } { hide }
           {
             \seq_item:Nn \g__flowfram_even_thumbtab_seq { ##1 }
           }
       }
    }
    {
      \seq_map_indexed_inline:Nn \g__flowfram_thumbtab_seq
       {
         \clist_set:Ne \l__flowfram_pages_clist
          {
            \__flowfram_thumbtab_pages:n
              { ##1 }
          }
          \flowfram_frame_set_clist:nnnV
           { dynamic } { pagelist } { ##2 }
            \l__flowfram_pages_clist
          \flowfram_frame_set_bool_true:nnn
           { dynamic } { hide } { ##2 }
        }
     }
}
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_thumbtab_pagelist:nnn
 {
   \clist_set:Ne \l__flowfram_pages_clist
    {
      \__flowfram_thumbtab_pages:n { #1 }
    }
   \__flowfram_separate_odd_even:
   \__flowfram_set_thumbtab_pages:nn { #2 } { #3 }
 }
%    \end{macrocode}
%\begin{macro}{\thumbtabwidth}
% Default thumbtab width.
%    \begin{macrocode}
\newlength{\thumbtabwidth}
\setlength{\thumbtabwidth}{1cm}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabnumtitle}
%\changes{2.0}{2025-11-24}{new}
%Used to format number and title if both shown.
%    \begin{macrocode}
\NewDocumentCommand \thumbtabnumtitle { m m }
 {
   #1 \c_space_tl #2
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabformat}
% Individual thumbtab format.
% Syntax: \cs{thumbtabformat}\marg{text}\marg{height}
%    \begin{macrocode}
\newcommand{\thumbtabformat}[2]{%
  \__flowfram_thumbtab_fmt:nn { #1 } { #2 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flf@subsp}
%\changes{1.10}{2007/08/21}{new}
% Version 2.0 removed \cs{@flf@subsp}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@ttb@stack}
% Stack letters vertically. 
%\changes{1.10}{2007/08/21}{spaces now replaced with \cs{space}}
% Version 2.0 replaced \cs{@ttb@stack}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \flowfram_thumbtab_stack:n
 {
   \tl_clear:N \l__flowfram_tmpa_tl
   \exp_args:Ne \text_map_inline:nn { \text_purify:n { #1 } }
    {
      \tl_if_empty:NF \l__flowfram_tmpa_tl
       {
         \tl_put_right:Nn \l__flowfram_tmpa_tl { \\ }
       }
      \tl_put_right:Nn \l__flowfram_tmpa_tl { ##1 }
    }
   \tl_put_left:Nn \l__flowfram_tmpa_tl { \begin { tabular } { l } }
   \tl_put_right:Nn \l__flowfram_tmpa_tl { \end { tabular } }
   \l__flowfram_tmpa_tl
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@@ttb@stack}
%\changes{1.10}{2007/08/21}{now uses \cs{mbox}}
% Version 2.0 removed \cs{@@ttb@stack}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@greyscale}
% Count register to compute the grey scale.
% Version 2.0 replaced \cs{@greyscale}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\fp_new:N \l__flowfram_greyscale_fp 
%    \end{macrocode}
%\end{macro}
%Keep track of IDNs of thumbtabs.
%    \begin{macrocode}
\seq_new:N \g__flowfram_thumbtab_seq
\seq_new:N \g__flowfram_thumbtab_index_seq
%    \end{macrocode}
%
%Version 2.0 allows bespoke thumbtabs. The dynamic frames should be
%labelled "thumbtab1", "thumbtab2", etc. With corresponding dynamic
%frames for the thumbtab index labelled "thumbtabindex1",
%"thumbtabindex2", etc. The index thumbtabs should have the same
%height as the thumbtabs. Allow for bespoke even thumbtabs, which
%should be labelled "eventhumbtab1", "eventhumbtab2", etc, and
%"eventhumbtabindex1", "eventhumbtabindex2", etc.
%    \begin{macrocode}
\seq_new:N \g__flowfram_even_thumbtab_seq
\seq_new:N \g__flowfram_even_thumbtab_index_seq
\bool_new:N \g__flowfram_has_bespoke_thumbtabs_bool
\bool_gset_false:N \g__flowfram_has_bespoke_thumbtabs_bool
%    \end{macrocode}
%
%\begin{macro}{\@@dothumbtabs}
% 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.
%If the frame is already defined (for example via flowframtk)
%then omit defining it but set the contents as appropriate.
%Syntax: \marg{index}\marg{height}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_create_thumbtab:nn
 {
   \fp_set:Nn \l__flowfram_greyscale_fp
    {
       0.01 * ( ( 60 * ( #1 ) / \c@maxthumbtabs ) + 25 )
    }
%    \end{macrocode}
% Create dynamic frame for thumbtab, unless it already exists.
%    \begin{macrocode}
    \__flowfram_if_frame_label_exists:nnNTF
        { dynamic } 
        { thumbtab \int_eval:n { #1 } }
        \l__flowfram_id_int
     {
%    \end{macrocode}
% Bespoke thumbtab. Change the offset in case we run out and need to
% create extra.
%    \begin{macrocode}
       \bool_set_true:N \g__flowfram_has_bespoke_thumbtabs_bool
       \flowfram_set_dim_to_frame_dim:Nnnn
         \l__flowfram_y_dim
         { dynamic } { posy } { \l__flowfram_id_int }
     }
     {
       \__flowfram_new_dynamic:nnnnnn
        { none } { \thumbtabwidth } { #2 }
        { \l__flowfram_x_dim } { \l__flowfram_y_dim }
        { thumbtab \int_eval:n { #1 } }
       \int_set_eq:NN \l__flowfram_id_int \c@maxdynamic
%    \end{macrocode}
% Set the position for even pages.
%    \begin{macrocode}
       \flowfram_frame_set_dim:nnnn { dynamic } { evenx }
         { \l__flowfram_id_int }
         { \l__flowfram_evenx_dim }
%    \end{macrocode}
% Set the background colour.
%    \begin{macrocode}
       \flowfram_frame_set_tl:nnne
        { dynamic } { backcolor } { \l__flowfram_id_int }
        { [gray] { \fp_to_decimal:N \l__flowfram_greyscale_fp } } 
     }
   \__flowfram_message:neee { info-thumbtab }
     { \int_eval:n { #1 } }
     { thumbtab \int_eval:n { #1 } }
     { \int_use:N \l__flowfram_id_int }
   \seq_put_right:NV \g__flowfram_thumbtab_seq
      \l__flowfram_id_int
%    \end{macrocode}
% Set the contents of the thumbtab dynamic frame.
%The title isn't expanded at this point to allow individual thumbtab
%titles to be changed with \cs{SetThumbTabTitle}.
%    \begin{macrocode}
   \__flowfram_set_thumbtab_content:NVneen
     \thumbtabregularformat
     \l__flowfram_id_int 
     { \__flowfram_thumbtab_link:n { #1 } }
     { \__flowfram_thumbtab_unitnum:n { #1 } }
     { \exp_not:N \__flowfram_thumbtab_title:n { #1 } }
     { #2 }
%    \end{macrocode}
%Has an even frame been defined?
%    \begin{macrocode}
    \__flowfram_if_frame_label_exists:nnNTF
        { dynamic } 
        { eventhumbtab \int_eval:n { #1 } }
        \l__flowfram_id_ii_int
     {
       \bool_set_true:N \g__flowfram_has_bespoke_thumbtabs_bool
       \seq_put_right:NV \g__flowfram_even_thumbtab_seq
        \l__flowfram_id_ii_int
%    \end{macrocode}
%Set the frame content.
%    \begin{macrocode}
       \__flowfram_set_thumbtab_content:NVneen
         \thumbtabregularformat
         \l__flowfram_id_ii_int 
         { \__flowfram_thumbtab_link:n { #1 } }
         { \__flowfram_thumbtab_unitnum:n { #1 } }
         { \exp_not:N \__flowfram_thumbtab_title:n { #1 } }
         { #2 }
     }
     {
       \seq_put_right:NV \g__flowfram_even_thumbtab_seq
        \l__flowfram_id_int
     }
%    \end{macrocode}
% Create dynamic frame for thumbtab index, unless it already exists.
%    \begin{macrocode}
    \__flowfram_if_frame_label_exists:nnNTF
        { dynamic } 
        { thumbtabindex \int_eval:n { #1 } }
        \l__flowfram_id_int
     {
       \bool_set_true:N \g__flowfram_has_bespoke_thumbtabs_bool
     }
     {
       \__flowfram_new_dynamic:nnnnnn
        { none } { \thumbtabwidth } { #2 }
        { \l__flowfram_x_dim } { \l__flowfram_y_dim }
        { thumbtabindex \int_eval:n { #1 } }
       \int_set_eq:NN \l__flowfram_id_int \c@maxdynamic
%    \end{macrocode}
% Set the position for even pages.
%    \begin{macrocode}
       \flowfram_frame_set_dim:nnnn { dynamic } { evenx }
         { \l__flowfram_id_int }
         { \l__flowfram_evenx_dim }
%    \end{macrocode}
% Set the background colour.
%    \begin{macrocode}
       \flowfram_frame_set_tl:nnne
        { dynamic } { backcolor } { \l__flowfram_id_int }
        { [gray] { \fp_to_decimal:N \l__flowfram_greyscale_fp } } 
     }
   \__flowfram_message:neee {info-thumbtab-index}
     { \int_eval:n { #1 } }
     { thumbtabindex \int_eval:n { #1 } }
     { \int_use:N \l__flowfram_id_int }
   \seq_put_right:NV \g__flowfram_thumbtab_index_seq
      \l__flowfram_id_int
%    \end{macrocode}
% Set the contents of the dynamic frame.
%    \begin{macrocode}
   \__flowfram_set_thumbtab_content:NVeeen
     \thumbtabindexformat
     \l__flowfram_id_int 
     { \__flowfram_thumbtab_link:n { #1 } }
     { \__flowfram_thumbtab_unitnum:n { #1 } }
     { \exp_not:N \__flowfram_thumbtab_title:n { #1 } }
     { #2 }
%    \end{macrocode}
%Has an even index frame been defined?
%    \begin{macrocode}
    \__flowfram_if_frame_label_exists:nnNTF
        { dynamic } 
        { eventhumbtabindex \int_eval:n { #1 } }
        \l__flowfram_id_ii_int
     {
       \bool_set_true:N \g__flowfram_has_bespoke_thumbtabs_bool
       \seq_put_right:NV \g__flowfram_even_thumbtab_index_seq
        \l__flowfram_id_ii_int
%    \end{macrocode}
%Set the frame content.
%    \begin{macrocode}
       \__flowfram_set_thumbtab_content:NVneen
         \thumbtabindexformat
         \l__flowfram_id_ii_int 
         { \__flowfram_thumbtab_link:n { #1 } }
         { \__flowfram_thumbtab_unitnum:n { #1 } }
         { \exp_not:N \__flowfram_thumbtab_title:n { #1 } }
         { #2 }
     }
     {
       \seq_put_right:NV \g__flowfram_even_thumbtab_index_seq
        \l__flowfram_id_int
     }
   \dim_sub:Nn \l__flowfram_y_dim { #2 }
 }
%    \end{macrocode}
%Set the frame content taking the package options into account.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_thumbtab_content:Nnnnnn
 {
   \tl_clear:N \l__flowfram_contents_tl
   \tl_if_empty:nTF { #4 }
    {
%    \end{macrocode}
%No number (starred sectioning command) so just use title.
%    \begin{macrocode}
      \tl_set:Ne \l__flowfram_contents_tl
       {
          \exp_not:N #1
           { #3 }
           { \exp_not:n { #5 } }
           { \dim_eval:n { #6 } }
       }
    }
    {
      \bool_if:NTF \l__flowfram_ttb_show_number_bool
        {
          \bool_if:NTF \l__flowfram_ttb_show_title_bool
            {
              \tl_set:Ne \l__flowfram_contents_tl
               {
                  \exp_not:N #1
                   { #3 }
                   {
                     \exp_not:N \thumbtabnumtitle
                      { #4 } { \exp_not:n { #5 } }
                   }
                   { \dim_eval:n { #6 } }
               }
            }
            {
              \tl_set:Ne \l__flowfram_contents_tl
               {
                  \exp_not:N #1
                   { #3 }
                   { #4 } { \dim_eval:n { #6 } }
               }
            }
        }
        {
           \tl_set:Ne \l__flowfram_contents_tl
            {
               \exp_not:N #1
                { #3 }
                { \exp_not:n { #5 } }
                { \dim_eval:n { #6 } }
            }
        }
     }
   \exp_args:NnV \__flowfram_set_dynamic_contents:nn
     { #2 }
     \l__flowfram_contents_tl
 }
\cs_generate_variant:Nn  \__flowfram_set_thumbtab_content:Nnnnnn
 { NVneen , NVeeen }
%    \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.)
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \enablethumbtabs { }
 {
%    \end{macrocode}
%Ensure that \cs{FlowFramSectionUnit} writes to the ttb file:
%    \begin{macrocode}
   \cs_set_eq:NN
     \__flowfram_add_thumbtab:n
     \__flowfram_actual_add_thumbtab:n 
   \int_if_zero:nTF
    { \seq_count:N \g__flowfram_thumbtab_seq }
    {
      \__flowfram_no_thumbtabs_warn:
    }
    {
      \seq_map_inline:Nn \g__flowfram_thumbtab_seq
       {
         \flowfram_frame_set_bool_false:nnn
          { dynamic } { hide } { ##1 }
       }
     \bool_if:NT \g__flowfram_has_bespoke_thumbtabs_bool
       {
         \seq_map_inline:Nn \g__flowfram_even_thumbtab_seq
          {
            \flowfram_frame_set_bool_false:nnn
             { dynamic } { hide } { ##1 }
          }
       }
    }
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\disablethumbtabs}
% Disable all thumbtabs.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \disablethumbtabs { }
 {
%    \end{macrocode}
%Prevent \cs{FlowFramSectionUnit} from writing to the ttb file:
%    \begin{macrocode}
   \cs_set_eq:NN
     \__flowfram_add_thumbtab:n
     \use_none:n
   \seq_map_inline:Nn \g__flowfram_thumbtab_seq
    {
      \flowfram_frame_set_bool_true:nnn
       { dynamic } { hide } { ##1 }
    }
   \seq_map_inline:Nn \g__flowfram_thumbtab_index_seq
    {
      \flowfram_frame_set_clist:nnnn
       { dynamic } { pagelist } { ##1 } { none }
    }
   \bool_if:NT \g__flowfram_has_bespoke_thumbtabs_bool
    {
      \seq_map_inline:Nn \g__flowfram_even_thumbtab_seq
       {
         \flowfram_frame_set_clist:nnnn
          { dynamic } { hide } { ##1 } \c_true_bool
       }
      \seq_map_inline:Nn \g__flowfram_even_thumbtab_index_seq
       {
         \flowfram_frame_set_clist:nnnn
          { dynamic } { pagelist } { ##1 } { none }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\thumbtabindex}
% Show thumbtab indexes on current page (if no optional argument) or
% for the given page list. Version 2.0 added optional argument.
%\changes{2.0}{2025-11-24}{changed to document command and added
%optional argument}
%    \begin{macrocode}
\NewDocumentCommand \thumbtabindex { o }
{
 \IfValueTF { #1 }
  {
    \clist_set:Ne \l__flowfram_pages_clist { #1 }
%    \end{macrocode}
%If bespoke thumbtabs, need to separate the odd and even pages.
%    \begin{macrocode}
    \bool_if:NT \g__flowfram_has_bespoke_thumbtabs_bool
     {
       \__flowfram_separate_odd_even:
     }
  }
  {
    \clist_set:Ne \l__flowfram_pages_clist
     {
       \int_eval:n { \g__flowfram_pagecounter_tl } 
     }
    \bool_if:NT \g__flowfram_has_bespoke_thumbtabs_bool
     {
       \int_if_odd:nTF { \g__flowfram_pagecounter_tl }
        {
          \clist_set_eq:NN \l__flowfram_odd_pages_clist
             \l__flowfram_pages_clist
          \clist_set:Nn \l__flowfram_even_pages_clist { none }
        }
        {
          \clist_set_eq:NN \l__flowfram_even_pages_clist
             \l__flowfram_pages_clist
          \clist_set:Nn \l__flowfram_odd_pages_clist { none }
        }
     }
  }
 \bool_if:NTF \g__flowfram_has_bespoke_thumbtabs_bool
  {
    \seq_map_pairwise_function:NNN
      \g__flowfram_thumbtab_index_seq
      \g__flowfram_even_thumbtab_index_seq
      \__flowfram_set_thumbtab_pages:nn
  }
  {
    \seq_map_inline:Nn \g__flowfram_thumbtab_index_seq
     {
       \flowfram_frame_set_clist:nnnV
         { dynamic } { pagelist } { ##1 }
         \l__flowfram_pages_clist
     }
  }
}
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_separate_odd_even:
 {
   \clist_if_empty:NTF \l__flowfram_pages_clist
    {
      \clist_set:Nn \l__flowfram_pages_clist { none }
      \clist_set:Nn \l__flowfram_even_pages_clist { none }
      \clist_set:Nn \l__flowfram_odd_pages_clist { none}
    }
    {
      \exp_args:Ne \__flowfram_get_range:n 
        { \clist_item:Nn \l__flowfram_pages_clist { \c_one_int } }
      \clist_clear:N \l__flowfram_even_pages_clist
      \clist_clear:N \l__flowfram_odd_pages_clist
      \int_compare:nNnTF
         { \l__flowfram_range_end_int} < { \c_flowfram_max_page_int }
       {
          \int_step_inline:nnn
             { \l__flowfram_range_start_int } { \l__flowfram_range_end_int }
           {
             \int_if_odd:nTF { ##1 }
               {
                 \clist_put_right:Nn
                    \l__flowfram_odd_pages_clist { ##1 }
               }
               {
                 \clist_put_right:Nn
                    \l__flowfram_even_pages_clist { ##1 }
               }
           }
          \clist_if_empty:NT \l__flowfram_odd_pages_clist
           {
             \clist_set:Nn \l__flowfram_odd_pages_clist { none }
           }
          \clist_if_empty:NT \l__flowfram_even_pages_clist
           {
             \clist_set:Nn \l__flowfram_even_pages_clist { none }
           }
       }
       {
         \clist_set:Nn \l__flowfram_even_pages_clist { even }
         \clist_set:Nn \l__flowfram_odd_pages_clist { odd }
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_thumbtab_pages:nn
 {
   \int_compare:nNnTF { #1 } = { #2 }
    {
      \flowfram_frame_set_clist:nnnV
        { dynamic } { pagelist } { #1 }
        \l__flowfram_pages_clist
    }
    {
      \flowfram_frame_set_clist:nnnV
        { dynamic } { pagelist } { #1 }
        \l__flowfram_odd_pages_clist
      \flowfram_frame_set_clist:nnnV
        { dynamic } { pagelist } { #2 }
        \l__flowfram_even_pages_clist
    }
 }
%    \end{macrocode}
%\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.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setthumbtab { m m }
 {
   \tl_if_eq:nnTF { #1 } { all }
    {
      \int_step_inline:nn { \c@maxthumbtabs }
       {
         \__flowfram_set_thumbtab:nn { ##1 } { #2 }
       }
    }
    {
      \clist_map_inline:nn { #1 }
       {
         \int_compare:nNnTF { ##1 } < { \c_one_int }
          {
            \msg_error:nnn { flowfram }
              { invalid-thumbtab-index }
              { ##1 }
          }
          {
            \int_compare:nNnTF
              { ##1 } >
              { \seq_count:N \g__flowfram_thumbtab_seq }
             {
               \msg_warning:nnn {flowfram} {cant-find-thumbtab} { ##1 }
             }
             {
               \__flowfram_set_thumbtab:nn { ##1 } { #2 }
             }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@setthumbtab}
% Set individual thumbtab and its index tab.
% Version 2.0 replaced \cs{@setthumbtab}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_thumbtab:nn
 {
%    \end{macrocode}
%Find the ID for the index thumbtab:
%    \begin{macrocode}
   \int_set:Nn \l__flowfram_id_int
     {
       \seq_item:Nn 
         \g__flowfram_thumbtab_index_seq
         { #1 }
     }
   \__flowfram_set_dynamic_by_idn:nn
     {
       \l__flowfram_id_int
     }
     { #2 }
   \bool_if:NT \g__flowfram_has_bespoke_thumbtabs_bool
    {
%    \end{macrocode}
%If bespoke thumbtabs, find the ID for the even index thumbtab:
%    \begin{macrocode}
      \int_set:Nn \l__flowfram_id_ii_int
        {
          \seq_item:Nn 
            \g__flowfram_even_thumbtab_index_seq
            { #1 }
        }
      \int_compare:nNnF
        {
          \l__flowfram_id_int
        }
         =
        {
          \l__flowfram_id_ii_int
        }
       {
         \__flowfram_set_dynamic_by_idn:nn
           {
             \l__flowfram_id_ii_int
           }
           { #2 }
       }
    }
%    \end{macrocode}
%Find the ID for the thumbtab:
%    \begin{macrocode}
   \int_set:Nn \l__flowfram_id_int
     {
       \seq_item:Nn 
         \g__flowfram_thumbtab_seq
         { #1 }
     }
   \__flowfram_set_dynamic_by_idn:nn
     {
       \l__flowfram_id_int
     }
     { #2 }
   \bool_if:NT \g__flowfram_has_bespoke_thumbtabs_bool
    {
%    \end{macrocode}
%If bespoke thumbtabs, find the ID for the even thumbtab:
%    \begin{macrocode}
      \int_set:Nn \l__flowfram_id_ii_int
        {
          \seq_item:Nn 
            \g__flowfram_even_thumbtab_seq
            { #1 }
        }
      \int_compare:nNnF
        {
          \l__flowfram_id_int
        }
         =
        {
          \l__flowfram_id_ii_int
        }
       {
         \__flowfram_set_dynamic_by_idn:nn
           {
             \l__flowfram_id_ii_int
           }
           { #2 }
       }
    }
 }
%    \end{macrocode}
%
%\end{macro}
%\begin{macro}{\setthumbtabindex}
% Only change settings for the thumbtab index. This can
% take a comma-separated number list.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \setthumbtabindex { m m }
 {
   \tl_if_eq:nnTF { #1 } { all }
    {
      \int_step_inline:nn { \c@maxthumbtabs }
       {
         \__flowfram_set_thumbtab_index:nn { ##1 } { #2 }
       }
    }
    {
      \clist_map_inline:nn { #1 }
       {
         \int_compare:nNnTF { ##1 } < { \c_one_int }
          {
            \msg_error:nnn { flowfram }
              { invalid-thumbtab-index }
              { ##1 }
          }
          {
            \int_compare:nNnTF
              { ##1 } >
              { \seq_count:N \g__flowfram_thumbtab_seq }
             {
               \msg_warning:nnn {flowfram} {cant-find-thumbtab} { ##1 }
             }
             {
               \__flowfram_set_thumbtab_index:nn { ##1 } { #2 }
             }
          }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@setthumbtabindex}
% Change setting for individual thumbtab index entry.
% Version 2.0 replaced \cs{@setthumbtabindex}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_set_thumbtab_index:nn
 {
%    \end{macrocode}
%Find the ID for the index thumbtab:
%    \begin{macrocode}
   \int_set:Nn \l__flowfram_id_int
     {
       \seq_item:Nn 
         \g__flowfram_thumbtab_index_seq
         { #1 }
     }
   \__flowfram_set_dynamic_by_idn:nn
     {
       \l__flowfram_id_int
     }
     { #2 }
   \bool_if:NT \g__flowfram_has_bespoke_thumbtabs_bool
    {
%    \end{macrocode}
%If bespoke thumbtabs, find the ID for the even index thumbtab:
%    \begin{macrocode}
      \int_set:Nn \l__flowfram_id_ii_int
        {
          \seq_item:Nn 
            \g__flowfram_even_thumbtab_index_seq
            { #1 }
        }
      \int_compare:nNnF
        {
          \l__flowfram_id_int
        }
         =
        {
          \l__flowfram_id_ii_int
        }
       {
         \__flowfram_set_dynamic_by_idn:nn
           {
             \l__flowfram_id_ii_int
           }
           { #2 }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\tocandhumbtabindex}
% Do both the table of contents and the thumbtab index.
% This is intended for single paged table of contents.
%    \begin{macrocode}
\NewDocumentCommand \tocandthumbtabindex { }
 {
   \aligntoctrue
   \bool_set_true:N \l__flowfram_thumbtabs_in_toc_bool
   \tableofcontents
   \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
% Version 2.0 replaced \cs{@ttb@minitoctype}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\tl_new:N \g__flowfram_minitoc_type_tl 
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\if@storetoc}
% Version 2.0 removed \cs{if@storetoc}.
%\changes{2.0}{2025-11-24}{removed}
%\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. A boolean is used to determine whether
% to store the contents, or act as normal.
% \cs{@starttoc} will be set to the following:
%    \begin{macrocode}
\cs_new:Nn \__flowfram_starttoc:n
 {
   \__flowfram_store_toc:n { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@ttb@storetoc}
% Store the contents of the file with the given extension.
% Version 2.0 replaced \cs{@ttb@storetoc}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_store_toc:n
 {
  \begingroup
    \makeatletter
    \__flowfram_parse_toc:n { \jobname . #1 }
%    \end{macrocode}
%The rest is the same as for the kernel definition of \cs{@starttoc}
%but includes the extra check used by \sty{rerunfilecheck}.
%    \begin{macrocode}
    \if@filesw
      \RerunFileCheck { \jobname . #1 }
       {
        \@ifundefined{tf@#1}{}
         {
           \immediate\closeout\csname tf@#1  \endcsname
         }
       }
       { }
      \@ifundefined{tf@#1}
       {
        \expandafter\newwrite\csname tf@#1\endcsname
       }
       { }
      \immediate\openout\csname tf@#1\endcsname\jobname.#1\relax
    \fi
    \@nobreakfalse
  \endgroup
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\ior_new:N \g__flowfram_toc_ior
%    \end{macrocode}
%\begin{macro}{\@ttb@minitoclevel}
% Version 2.0 replaced \cs{@ttb@minitoclevel}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_new:N \g__flowfram_minitoc_level_int 
%    \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}}
% Version 2.0 replaced \cs{@storefileconts}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_parse_toc:n
 {
   \ior_open:NnTF \g__flowfram_toc_ior { #1 }
    {
      \int_if_exist:cTF
         {
            c_flowfram_level_
            \g__flowfram_minitoc_type_tl
            _int
         }
       {
         \int_gset_eq:Nc \g__flowfram_minitoc_level_int 
           {
              c_flowfram_level_
              \g__flowfram_minitoc_type_tl
              _int
           }
       }
       {
         \int_gset:Nn \g__flowfram_minitoc_level_int  { 6 }
       }
      \int_gzero:N \c@maxtocunits
      \int_gzero:N \c@maxminitoc
      \int_gzero:N \g__flowfram_toc_level_int
      \ior_map_inline:Nn \g__flowfram_toc_ior
        {
          \__flowfram_add_to_toc_list:Nn
            \c@maxtocunits { ##1 }
        }
      \ior_close:N \g__flowfram_toc_ior
    }
    {
      \msg_info:nnn { flowfram } { info-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}
% Version 2.0 removed \cs{@@storefileconts}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\if@contsline}
% Version 2.0 removed \cs{if@contsline}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@ttb@level}
% Version 2.0 removed \cs{@ttb@level}.
%\changes{2.0}{2025-11-24}{removed}
%\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 deeper than "\g__flowfram_minitoc_type_tl ". The number of minitoc
% lists is given by "\c@maxminitoc".
% Version 2.0 replaced \cs{@addtotoclist}
%\changes{2.0}{2025-11-24}{replaced}
%
%Keep track of current level:
%    \begin{macrocode}
\int_new:N \g__flowfram_toc_level_int
%    \end{macrocode}
% Token list that will contain the whole toc:
%    \begin{macrocode}
\tl_new:N \g__flowfram_table_of_contents_tl
%    \end{macrocode}
% Add a line from the toc to the applicable list.
%Syntax: \meta{int-var}\marg{toc line}
%The variable keeps track of the number of toc sub lists.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_add_to_toc_list:Nn
 {
%    \end{macrocode}
% First add to the whole list:
%    \begin{macrocode}
   \tl_gput_right:Nn \g__flowfram_table_of_contents_tl { #2 }
%    \end{macrocode}
% Now check if the line starts with \cs{contentsline}.
%    \begin{macrocode}
   \tl_if_head_eq_meaning:nNT 
      { #2 } \contentsline
    {
%    \end{macrocode}
% Get the content of the first argument that follows \cs{contentsline}.
%First discard \cs{contentsline}.
%    \begin{macrocode}
      \tl_set:Ne \l__flowfram_remainder_tl
        {
          \tl_tail:n { #2 }
        }
%    \end{macrocode}
%Now get the first argument:
%    \begin{macrocode}
      \tl_set:Ne \l__flowfram_contents_tl
        {
          \tl_head:N \l__flowfram_remainder_tl
        }
%    \end{macrocode}
%If this section type is recognised, get the numeric identifier:
%    \begin{macrocode}
      \int_if_exist:cTF
        {
          c_flowfram_level_
          \l__flowfram_contents_tl
          _int
        }
       {
         \int_gset_eq:Nc \g__flowfram_toc_level_int
           {
             c_flowfram_level_
             \l__flowfram_contents_tl
             _int
           }
       }
       {
%    \end{macrocode}
%Not recognised, assume it comes after the known lowest level.
%    \begin{macrocode}
         \int_gset:Nn \g__flowfram_toc_level_int
           { \c_flowfram_level_subparagraph_int + \c_one_int }
       }
%    \end{macrocode}
%If this level is the designated thumbtab level, increment the
%counter that keeps track of the number of toc units.
%    \begin{macrocode}
      \tl_if_eq:eeT
        { \g__flowfram_thumbtab_type_tl }
        { \l__flowfram_contents_tl }
       {
         \int_gincr:N #1
       }
%    \end{macrocode}
%If a token list is not yet available for this toc sub list, create it.
%    \begin{macrocode}
      \tl_if_exist:cF 
        { g__flowfram_toc_level_ \romannumeral #1 _tl }
       {
         \tl_new:c 
          { g__flowfram_toc_level_ \romannumeral #1 _tl }
       }
%    \end{macrocode}
%Append the toc line to this toc sub list.
%    \begin{macrocode}
      \tl_gput_right:cn
        { g__flowfram_toc_level_ \romannumeral #1 _tl }
        { #2 }
    }
%    \end{macrocode}
% Now do minitoc stuff if applicable.
%    \begin{macrocode}
   \bool_if:NT \g__flowfram_minitocs_enabled_bool
    {
%    \end{macrocode}
% If the current toc level matches the designated minitoc level,
% increment the counter that stores the maximum number of minitocs
% and create the associated token list. 
%    \begin{macrocode}
    \int_compare:nNnTF
        { \g__flowfram_toc_level_int }
        =
        { \g__flowfram_minitoc_level_int }
      {
        \int_gincr:N \c@maxminitoc
%    \end{macrocode}
% Create the associated token list but don't add this toc line to
% it.
%    \begin{macrocode}
        \tl_clear_new:c { g__flowfram_minitoc_ \romannumeral \c@maxminitoc _tl }
      }
      {
        \int_compare:nNnT
          { \g__flowfram_toc_level_int }
            >
          { \g__flowfram_minitoc_level_int }
         {
%    \end{macrocode}
% If the current section level is deeper than the designated minitoc
% level, add this toc line to the list.
%    \begin{macrocode}
           \tl_if_exist:cF { g__flowfram_minitoc_ \romannumeral \c@maxminitoc _tl }
            {
              \tl_new:c { g__flowfram_minitoc_ \romannumeral \c@maxminitoc _tl }
            }
           \tl_gput_right:cn
             { g__flowfram_minitoc_ \romannumeral \c@maxminitoc _tl }
            { #2 }
         }
      }
    }
 }
%    \end{macrocode}
%\end{macro}
% Is there already a way of determining the sectioning
% level from its name?
%\begin{macro}{\@ttb@part@level}
% Version 2.0 replaced \cs{@ttb@part@level}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_const:Nn \c_flowfram_level_part_int { -1 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@chapter@level}
% Version 2.0 replaced \cs{@ttb@chapter@level}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_const:Nn \c_flowfram_level_chapter_int { 0 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@section@level}
% Version 2.0 replaced \cs{@ttb@section@level}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_const:Nn \c_flowfram_level_section_int { 1 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@subsection@level}
% Version 2.0 replaced \cs{@ttb@subsection@level}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_const:Nn \c_flowfram_level_subsection_int { 2 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@subsubsection@level}
% Version 2.0 replaced \cs{@ttb@subsubsection@level}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_const:Nn \c_flowfram_level_subsubsection_int { 3 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@paragraph@level}
% Version 2.0 replaced \cs{@ttb@paragraph@level}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_const:Nn \c_flowfram_level_paragraph_int { 4 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ttb@subparagraph@level}
% Version 2.0 replaced \cs{@ttb@subparagraph@level}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\int_const:Nn \c_flowfram_level_subparagraph_int { 5 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@checkcontentsline}
% Version 2.0 removed \cs{@checkcontentsline}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@gettype}
% Version 2.0 removed \cs{@gettype}
%\changes{2.0}{2025-11-24}{removed}
%\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.
% This is the default code used for "\tableofcontents":
%    \begin{macrocode}
\cs_new:Nn \__flowfram_tableofcontents:
{
  \cs_set_eq:NN \@starttoc \__flowfram_starttoc:n
  \flowfram_toc:
  \bool_lazy_and:nnTF
    {
      \bool_not_p:n
       {
         \tl_if_empty_p:N \g__flowfram_table_of_contents_tl
       }
    }
    {
      \bool_if_p:N \l__flowfram_thumbtabs_in_toc_bool
    }
   {
     \bool_if:NTF \l__flowfram_thumbtabs_span_toc_bool
      {
        \thumbtabindex[all]
      }
      {
        \thumbtabindex
      }
     \legacy_if:nTF { aligntoc }
      {
       \__flowfram_print_aligned_toc:
      }
      {
        \__flowfram_print_toc:
      }
     \bool_if:NT \l__flowfram_thumbtabs_span_toc_bool
      {
       \afterpage
        {
          \thumbtabindex[none]
        }
      }
   }
   {
     \__flowfram_print_toc:
   }
  \cs_set_eq:NN \@starttoc \__flowfram_org_starttoc:
  \int_gzero:N \c@minitoc
}
%    \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". (Version 2.0 removed check that
% minitocs have been enabled since this command won't be used if
% they haven't been enabled). The argument is the minitoc index.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \dominitoc { m }
 {
   \flowfram_do_minitoc:n { #1 }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@dominitoc}
%This command is redefined by \cs{appenddfminitoc}.
% Version 2.0 renamed \cs{@dominitoc}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \flowfram_do_minitoc:n 
 {
   \flowfram_use_minitoc:n { #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".
% Version 2.0 renamed \cs{@@dominitoc}.
%\changes{2.0}{2025-11-24}{renamed}
%    \begin{macrocode}
\cs_new:Nn \flowfram_use_minitoc:n
 {
  \bool_lazy_and:nnT
    {
      \tl_if_exist_p:c { g__flowfram_minitoc_ \romannumeral #1 _tl } 
    }
    {
      \bool_not_p:n
       { \tl_if_empty_p:c { g__flowfram_minitoc_ \romannumeral #1 _tl } }
    }
   {
     \vskip \beforeminitocskip
     \group_begin:
       \minitocstyle
        {
          \tl_use:c { g__flowfram_minitoc_ \romannumeral #1 _tl }
        }
     \group_end:
     \vskip \afterminitocskip
   }
}
%    \end{macrocode}
%\end{macro}
%
%We don't want to repeatedly add the minitoc to the dynamic frame
%but \cs{ChapterInDynamic} automatically resets the contents which
%means the minitoc will need to be appended at the start of each
%chapter if they are both using the same frame. Also, if the clear
%setting is on then the minitoc will need to be appended again when
%needed.
%    \begin{macrocode}
\cs_new:Nn \flowfram_clear_do_minitoc:
 {
   \int_compare:nNnF
     { \g__flowfram_minitoc_frame_id }
       =
     { \g__flowfram_chaphead_frame_id }
    {
      \flowfram_if_frame_bool:nnnF
         { dynamic } { clear } { \g__flowfram_minitoc_frame_id }
       {
         \cs_gset_eq:NN \flowfram_do_minitoc:n \use_none:n
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\int_new:N \g__flowfram_minitoc_frame_id
%    \end{macrocode}
%
%\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}
\NewDocumentCommand \appenddfminitoc { s m }
 {
   \renewcommand{\beforeminitocskip}{\baselineskip}%
   \IfBooleanTF { #1 }
    {
      \__flowfram_get_dynamic_id:e { #2 }
      \int_gset_eq:NN
         \g__flowfram_minitoc_frame_id
         \l__flowfram_id_int
    }
    {
      \int_gset:Nn \g__flowfram_minitoc_frame_id { #2 }
    }
   \cs_set:Nn \flowfram_do_minitoc:n
    {
      \__flowfram_append_dynamic_contents_idn:nn
       { \g__flowfram_minitoc_frame_id }
       {
         \flowfram_use_minitoc:n { ##1 }
       }
      \flowfram_clear_do_minitoc:
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@sappendminitocdf}
% Version 2.0 removed \cs{@sappendminitocdf}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@appendminitocdf}
% Version 2.0 removed \cs{@appendminitocdf}
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%
%\begin{macro}{\@printtoc}
% Do the table of contents, which has been gathered from the toc
% file.
% Version 2.0 replaced \cs{@printtoc}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_print_toc_units:
 {
   \int_step_inline:nn { \c@maxtocunits }
    {
      \tl_use:c { g__flowfram_toc_level_ \romannumeral ##1 _tl }
    }
 }
%    \end{macrocode}
%Print all the content found in the toc.
%    \begin{macrocode}
\cs_new:Nn \__flowfram_print_toc:
 {
    \g__flowfram_table_of_contents_tl
 }
%    \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.
% Version 2.0 replaced \cs{@printalignedtoc}
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\cs_new:Nn \__flowfram_print_aligned_toc:
 {
   \tl_if_exist:NT \g__flowfram_toc_level__tl 
    {
       \g__flowfram_toc_level__tl 
       \par
       \noindent
       \hrulefill
    }
   \int_step_inline:nn { \c@maxtocunits }
    {
      \int_compare:nNnTF { ##1 } > { \c@maxthumbtabs }
       {
         \tl_use:c { g__flowfram_toc_level_ \romannumeral ##1 _tl }
       }
       {
         \__flowfram_get_dynamic_id:n
           { thumbtabindex ##1 }
         \flowfram_set_dim_to_frame_dim:Nnnn
           \l__flowfram_x_dim
           { dynamic } { width } { \l__flowfram_id_int }
         \flowfram_set_dim_to_frame_dim:Nnnn
           \l__flowfram_y_dim
           { dynamic } { height } { \l__flowfram_id_int }
         \vbox_to_ht:nn { \l__flowfram_y_dim }
           {
             \noindent
             \parbox { \linewidth }
              {
                \tl_use:c { g__flowfram_toc_level_ \romannumeral ##1 _tl }
              }
             \vfill
             \par
             \noindent
             \hrulefill
           }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\if@minitoc}
% Version 2.0 replaced \cs{if@minitoc}.
%\changes{2.0}{2025-11-24}{replaced}
%    \begin{macrocode}
\bool_new:N \g__flowfram_minitocs_enabled_bool
\bool_gset_false:N \g__flowfram_minitocs_enabled_bool
%    \end{macrocode}
%\end{macro}
%Counter to keep track of the current minitoc.
%    \begin{macrocode}
\newcounter{minitoc}
%    \end{macrocode}
%
%\begin{macro}{\enableminitoc}
% Make mini tocs appear at the start of given sectional unit.
%\changes{2.0}{2025-11-24}{changed to document command}
%    \begin{macrocode}
\NewDocumentCommand \enableminitoc
    { O { \g__flowfram_thumbtab_type_tl } }
 {
  \bool_gset_true:N \g__flowfram_minitocs_enabled_bool
  \int_gzero:N \c@minitoc
  \cs_if_exist:cTF { c_flowfram_level_ #1 _int }
   {
    \tl_gset:Ne \g__flowfram_minitoc_type_tl  { #1 }
    \cs_set:Nn \__flowfram_minitoc_post_section_unit:n
     {
       \tl_if_eq:NnT \g__flowfram_minitoc_type_tl { ##1 }
        {
          \stepcounter { minitoc }
          \dominitoc { \c@minitoc }
        }
     }
   }
   {
     \msg_error:nne { flowfram } { section-unit-not-defined } { #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}
% Version 2.0 removed \cs{@makeminitocchapter}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@makeminitocpart}
% Version 2.0 removed \cs{@makeminitocpart}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%\begin{macro}{\@makeminitocsection}
% Version 2.0 removed \cs{@makeminitocsection}.
%\changes{2.0}{2025-11-24}{removed}
%\end{macro}
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%\iffalse
%    \begin{macrocode}
%</flowfram.sty>
%    \end{macrocode}
%\fi
%\iffalse
%    \begin{macrocode}
%<*flowframtkutils.sty>
%    \end{macrocode}
%\fi
% \section{Support for FlowframTk}
%This package (new in v2.0) is provided to support commands written by FlowframTk
%when exporting to a LaTeX class, package, document file or 
%image file. This package doesn't automatically load \sty{flowfram}
%as the exported file could simply just contain a \env{pgfpicture}
%environment, in which case \sty{flowfram} isn't required.
%
%A FlowframTk image consists of the actual image itself, which is
%defined by a set of objects, that may be paths, text (no line
%breaks), bitmaps, composite shapes (defined by an underlying shape
%with replicas or a reflection or text decoration), or groups (a
%subset of objects). Each object may have \sty{flowfram} data
%assigned to it. Additionally, the image may include early preamble
%code, mid preamble code and late preamble code. These may be
%inserted when exporting to a class, package or complete document.
%
%FlowframTk has two types of export: create an image using the
%\env{pgfpicture} environment, provided by the \sty{pgf} package, or 
%export the \sty{flowfram} data assigned to objects, which will
%write the applicable \cs{newflowframe}, \cs{newstaticframe} or
%\cs{newdynamicframe}. Objects the don't have \sty{flowfram} data
%assigned will be omitted from the export. The object's graphical
%representation (shape, text, bitmap, etc) may be used as the border
%for the frame, or may simply be used to identify the location and
%dimension of the frame.
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
%    \end{macrocode}
%Declare package:
%    \begin{macrocode}
\ProvidesPackage{flowframtkutils}[2026/06/19 v2.3 (NLCT)]
%    \end{macrocode}
%Switch on L3 syntax.
%    \begin{macrocode}
\ExplSyntaxOn
%    \end{macrocode}
% Provide outline support if true:
%    \begin{macrocode}
\bool_new:N \l__flowframtk_outline_bool
\bool_set_false:N \l__flowframtk_outline_bool
%    \end{macrocode}
% Provide text-path support if true:
%    \begin{macrocode}
\bool_new:N \l__flowframtk_textpath_bool
\bool_set_false:N \l__flowframtk_textpath_bool
%    \end{macrocode}
% Provide package options:
%    \begin{macrocode}
\keys_define:nn { flowframtkutils }
{
   outline .bool_set:N = \l__flowframtk_outline_bool ,
   outline .usage:n = { load },
   textpath .bool_set:N = \l__flowframtk_textpath_bool ,
   textpath .usage:n = { load },
}
%    \end{macrocode}
%
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%Process options:
%    \begin{macrocode}
\ProcessKeyOptions[flowframtkutils]
%    \end{macrocode}
%Load \sty{pgf} and \sty{graphicx}:
%    \begin{macrocode}
\RequirePackage{pgf}
\RequirePackage{graphicx}
%    \end{macrocode}
%
%    \begin{macrocode}
\ExplSyntaxOn
%    \end{macrocode}
%
%The following is for use when FlowframTk exports to cls or sty. This allows all
%\sty{flowfram} options to be passed in the created class or package
%option list. This means that FlowframTk doesn't have to keep
%track of all \sty{flowfram}['s] options and, in the case of an
%exported class file, the remaining options can be passed to the
%underlying class. Some of these
%options are not applicable with FlowframTk but they are provided
%for completeness.
%    \begin{macrocode}
\clist_new:N \g__flowframtk_options_clist
%    \end{macrocode}
%\begin{macro}{\FlowFramTkSetKey}
%Check if \sty{flowfram} has already been loaded. Bear in mind that
%some options can only be specified when \sty{flowfram} is loading.
%FlowframTk will write the require package line for \sty{flowfram}
%after that for \sty{flowframtkutils}.
%    \begin{macrocode}
\IfPackageLoadedTF { flowfram }
  {
   \newcommand \FlowFramTkSetKey [ 1 ]
    {
      \keys_set:nn { flowfram } { #1 }
    }
  }
  {
   \newcommand \FlowFramTkSetKey [ 1 ]
    {
      \clist_gput_right:Nn \g__flowframtk_options_clist { #1 } 
    }
  }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FlowFramTkDeclareKeys}
%Either set the option (if \sty{flowfram} has already been loaded)
%or add to the list of options to pass to \sty{flowfram}.
%    \begin{macrocode}
\newcommand \FlowFramTkDeclareKeys [ 1 ]
 {
  \keys_define:nn { #1 }
   {
     adjust-toc .code:n =
       {
          \FlowFramTkSetKey { adjust-toc = { ##1 } }
       } ,
     backmatter-sections .code:n =
       {
          \FlowFramTkSetKey { backmatter-sections = { ##1 } }
       } ,
     color .code:n =
       {
         \FlowFramTkSetKey { color = { ##1 } } 
       } ,
     color .default:n = { true } ,
     column-changes .code:n =
       {
          \FlowFramTkSetKey { column-changes = { ##1 } }
       } ,
     draft .code:n =
      {
         \FlowFramTkSetKey { draft }
      } ,
     dynamic-empty-page-style .code:n =
       {
          \FlowFramTkSetKey { dynamic-empty-page-style = { ##1 } }
       } ,
     dynamic-header-case .code:n =
       {
          \FlowFramTkSetKey { dynamic-header-case = { ##1 } }
       } ,
     dynamic-page-style .code:n =
       {
          \FlowFramTkSetKey { dynamic-page-style = { ##1 } }
       } ,
     dynamic-page-style-header-font .code:n =
       {
          \FlowFramTkSetKey { dynamic-page-style-header-font = { ##1 } }
       } ,
     dynamic-page-style-subheader-font .code:n =
       {
          \FlowFramTkSetKey { dynamic-page-style-subheader-font = { ##1 } }
       } ,
     dynamic-subheader-case .code:n =
       {
          \FlowFramTkSetKey { dynamic-subheader-case = { ##1 } }
       } ,
     final .code:n =
      {
         \FlowFramTkSetKey { final }
      } ,
     LR .code:n =
      {
         \FlowFramTkSetKey { LR = ##1 }
      } ,
     LR .default:n = { true } ,
     matter-thumbtabs .code:n =
      {
         \FlowFramTkSetKey { matter-thumbtabs = { ##1 } } 
      } ,
     nocolor .code:n =
      { 
         \FlowFramTkSetKey { nocolor } 
      } ,
     norotate .code:n =
      {
         \FlowFramTkSetKey { norotate } 
      } ,
     pages .code:n =
      {
         \FlowFramTkSetKey { pages = ##1 }
      } ,
     prohibit-frame-rotation .code:n =
      {
         \FlowFramTkSetKey { prohibit-frame-rotation = { ##1 } }
      } ,
     prohibit-frame-rotation .default:n = { true } ,
     RL .code:n =
      {
         \FlowFramTkSetKey { RL = ##1 }
      } ,
     RL .default:n = { true } ,
     rotate .code:n = 
      {
         \FlowFramTkSetKey { rotate = { ##1 } } 
      } ,
     rotate .default:n = { true } , 
     thumbtabs .code:n =
      {
         \FlowFramTkSetKey { thumbtabs = ##1 }
      } ,
     thumbtabs .default:n = { title } ,
     thumbtab-links .code:n =
      {
         \FlowFramTkSetKey { thumbtab-links = { ##1 } } 
      } ,
     thumbtab-text .code:n =
      {
         \FlowFramTkSetKey { thumbtab-text = { ##1 } }
      } ,
     toc-thumbtabs .code:n =
      {
         \FlowFramTkSetKey { toc-thumbtabs = { ##1 } } 
      } ,
     toc-thumbtabs .default:n = { true } ,
     ttbnotitle .code:n =
      {
         \FlowFramTkSetKey { ttbnotitle }
      } ,
     ttbnonum .code:n =
      {
         \FlowFramTkSetKey { ttbnonum }
      } ,
     ttbnum .code:n =
      {
         \FlowFramTkSetKey { ttbnum } 
      } ,
     ttbtitle .code:n =
      {
         \FlowFramTkSetKey { ttbtitle } 
      } ,
     sections-extra-option .code:n =
       {
          \FlowFramTkSetKey { sections-extra-option = { ##1 } }
       } ,
     verbose .code:n =
      {
         \FlowFramTkSetKey { verbose = { ##1 } }
      } ,
     verbose .default:n = { true } ,
     unstarred-thumbtabs .code:n =
      {
         \FlowFramTkSetKey { unstarred-thumbtabs = { ##1 } } 
      } ,
     unstarred-thumbtabs .default:n = { true } ,
   }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\jdrimagebox}
% For encapsulated images when FlowframTk creates a \LaTeX\ document
% file that simply contains the image in a \env{pgfpicture}
% environment.
% This command is just in case numerical rounding errors 
% cause the image to be marginally larger than the
% typeblock, which can cause a spurious blank page.
%    \begin{macrocode}
\NewDocumentCommand \jdrimagebox { m }
 {
   \noindent
   \vbox_to_ht:nn { \textheight } { \hbox_to_wd:nn { \textwidth } { #1 } }
 }
%    \end{macrocode}
%\end{macro}
%
%Provide support for outline text, if applicable. This depends on the output format.
%First the code if \LuaLaTeX:
%    \begin{macrocode}
\newcommand \@flowframtk@def@outlinelua
 {
%    \end{macrocode}
%The \file{pdf-trans} file uses \pdfLaTeX\ primitives so these need
%to be defined and the simplest way to do that is to load
%\sty{luatex85}.
%    \begin{macrocode}
   \RequirePackage{luatex85}
%    \end{macrocode}
%The rest is the same as for \pdfLaTeX:
%    \begin{macrocode}
   \@flowframtk@def@outlinepdf
 }
%    \end{macrocode}
%The code if \pdfLaTeX. This is much the same as the above, except
%\sty{luatex85} isn't required.
%    \begin{macrocode}
\newcommand \@flowframtk@def@outlinepdf
 {
%    \end{macrocode}
% pdf-trans defines \cs{mod} which is likely to conflict with other
% packages so save it so that it can be restored afterwards.
%    \begin{macrocode}
   \cs_set_eq:NN \__flowframtk_mod: \mod
%    \end{macrocode}
%Now input pdf-trans:
%    \begin{macrocode}
   \input{pdf-trans}
%    \end{macrocode}
%Make pdf-trans's \cs{mod} available under a different name if
%required:
%    \begin{macrocode}
   \let \flowframtkpdftransmod \mod
%    \end{macrocode}
%Restore the original \cs{mod}:
%    \begin{macrocode}
   \cs_set_eq:NN \mod \__flowframtk_mod:
%    \end{macrocode}
%Now define \cs{jdroutline} so that it uses the \cs{boxgs} command
%provided by pdf-trans:
%    \begin{macrocode}
   \NewDocumentCommand \jdroutline { m m m }
    {
     \setbox\@tempboxa\hbox{##3}
     \boxgs{##1}{}\copy\@tempboxa
    }
 }
%    \end{macrocode}
%Otherwise fallback on using PSTricks:
%    \begin{macrocode}
\newcommand \@flowframtk@def@outlinepst
 {
   \RequirePackage{pst-char}
   \NewDocumentCommand \jdroutline { m m m }
    {
     \begin{pspicture}(0,0)
     \pscharpath[##2]{##3}
     \end{pspicture}
   }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\msg_new:nnn { flowframtk }
 { no-outline }
 {
   outline ~ support ~ not ~ enabled
 }
%    \end{macrocode}
%
%\begin{macro}{\@flowframtk@outline}
%This command will be set to the applicable above command according
%to the engine, but only if outline support was requested with the
%"outline" package option. This will be set later after exp3 syntax
%has been switched off in case it interferes with the required file
%or package.
%    \begin{macrocode}
\newcommand \@flowframtk@outline
 {
   \NewDocumentCommand \jdroutline { m m m }
    {
      \msg_warning:nn { flowframtk } { no-outline }
      ##3
    }
 }
%    \end{macrocode}
%\end{macro}
%
% Provide outline support if requested:
%    \begin{macrocode}
\bool_if:NT \l__flowframtk_outline_bool
 {
   \sys_if_engine_luatex:TF
    {
      \let \@flowframtk@outline \@flowframtk@def@outlinelua
    }
    {
      \sys_if_engine_pdftex:TF
       {
         \let \@flowframtk@outline \@flowframtk@def@outlinepdf
       }
       {
         \let \@flowframtk@outline \@flowframtk@def@outlinepst
       }
    }
 }
%    \end{macrocode}
%Provide text-path support if requested. This is simply a matter of
%loading the \opt{decorations.text} \sty{pgf} library:
%    \begin{macrocode}
\bool_if:NTF \l__flowframtk_textpath_bool
 {
   \newcommand \@flowframtk@provide@textpath
    {
      \usepgflibrary{decorations.text}
    }
 }
 {
   \newcommand \@flowframtk@provide@textpath { }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%
%    \begin{macrocode}
\@flowframtk@outline
\@flowframtk@provide@textpath
%    \end{macrocode}
%
%    \begin{macrocode}
\ExplSyntaxOn
%    \end{macrocode}
%Scratch variable:
%    \begin{macrocode}
\tl_new:N \l__flowframtk_tmp_tl
%    \end{macrocode}
%
%Provide command to restore full justification (may be used by
%import function if justification switches in blocks of text).
%    \begin{macrocode}
\let\@flowframtk@cr\\
\skip_const:Nn \c__flowframtk_org_@right_skip { \@rightskip } 
\skip_const:Nn \c__flowframtk_org_right_skip { \rightskip } 
\skip_const:Nn \c__flowframtk_org_left_skip { \leftskip } 
\int_const:Nn \c__flowframtk_org_finalhyphendemerits { \finalhyphendemerits }
\dim_const:Nn \c__flowframtk_org_parindent_dim { \parindent }
\skip_const:Nn \c__flowframtk_org_parfill_skip { \parfillskip } 
%    \end{macrocode}
%\begin{macro}{\flowframtkNoRagged}
%\changes{2.2}{2026-04-25}{new}
%    \begin{macrocode}
\NewDocumentCommand\flowframtkNoRagged{}{%
  \let\\\@flowframtk@cr
  \@rightskip \c__flowframtk_org_@right_skip
  \rightskip \c__flowframtk_org_right_skip
  \leftskip \c__flowframtk_org_left_skip
  \finalhyphendemerits \c__flowframtk_org_finalhyphendemerits 
  \parindent \c__flowframtk_org_parindent_dim
  \parfillskip \c__flowframtk_org_parfill_skip
}
%    \end{macrocode}
%\end{macro}
%
%Object markup is an optional setting in FlowframTk's export dialog
%(v0.8.8+). Each object in the image can either be encapsulated or
%bookended. Each object has a unique value
%of \meta{n}, starting with 0 for the entire image (which is an
%implicit group).
%
%\begin{macro}{\flowframtkencapobject}
%\begin{definition}
%\cs{flowframtkencapobject}\marg{n}\marg{class name}\marg{description}\marg{tag}\marg{pgf
%point}\marg{width}\marg{height}\marg{object}
%\end{definition}
%Encapsulate the image object.
%    \begin{macrocode}
\newcommand\flowframtkencapobject[8]{#8}
%    \end{macrocode}
%\end{macro}
%
%Alternatively, bookend with start and matching end pairs. Each pair
%must have the same \meta{n} that identifies the object they are
%marking.
%\begin{macro}{\flowframtkstartobject}
%\begin{definition}
%\cs{flowframtkstartobject}\marg{n}\marg{class name}\marg{description}\marg{tag}\marg{pgf point}\marg{width}\marg{height}
%\end{definition}
%Markup just before object \meta{n} starts.
%    \begin{macrocode}
\newcommand\flowframtkstartobject[7]{}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkendobject}
%Markup when object \meta{n} ends.
%Syntax as for \cs{flowframtkstartobject}.
%    \begin{macrocode}
\newcommand\flowframtkendobject[7]{}
%    \end{macrocode}
%\end{macro}
%
%Provide some convenient commands for use in the above.
%\begin{macro}{\FlowframTkScopeIfGroup}
%\changes{2.2}{2026-04-25}{new}
%\begin{definition}
%\cs{FlowframTkScopeIfGroup}\marg{class name}\marg{object}
%\end{definition}
%This command is designed for \cs{flowframtkencapobject}. If the
%\meta{class name} is "JDRGroup" it will add scoping around
%\meta{object} otherwise it will just do \meta{object}.
%    \begin{macrocode}
\newcommand\FlowframTkScopeIfGroup[2]{
  \tl_if_eq:nnTF { #1 } { JDRGroup }
   {
      \begin { pgfscope }
      #2
      \end { pgfscope }
   }
   { #2 }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FlowframTkBeginScopeIfGroup}
%\changes{2.2}{2026-04-25}{new}
%\begin{definition}
%\cs{FlowframTkBeginScopeIfGroup}\marg{class name}
%\end{definition}
%Similar to the above but designed for the paired markup commands.
%    \begin{macrocode}
\newcommand\FlowframTkBeginScopeIfGroup[1]{
  \tl_if_eq:nnT { #1 } { JDRGroup }
   {
      \begin { pgfscope }
   }
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FlowframTkEndScopeIfGroup}
%\changes{2.2}{2026-04-25}{new}
%\begin{definition}
%\cs{FlowframTkEndScopeIfGroup}\marg{class name}
%\end{definition}
%    \begin{macrocode}
\newcommand\FlowframTkEndScopeIfGroup[1]{
  \tl_if_eq:nnT { #1 } { JDRGroup }
   {
      \end { pgfscope }
   }
}
%    \end{macrocode}
%\end{macro}
%
%
%Provide a definition of \cs{flowframtkencapobject} that can be used
%to uncover parts of the image in \cls{beamer} or similar.
%First the command that does the uncovering. This may be redefined
%as applicable. Individual uncover:
%    \begin{macrocode}
\cs_new:Nn \flowframtkutils_uncover:nn
 {
   \uncover < #1 > { #2 }
 }
%    \end{macrocode}
%
%Uncover from:
%    \begin{macrocode}
\cs_new:Nn \flowframtkutils_uncover_from:nn
 {
   \uncover < #1 - > { #2 }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowframtkutils_uncover:nn
 {
   \flowframtkutils_uncover_from:nn { #1 } { #2 }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowframtkutils_current_encap:nn { #2 }
%    \end{macrocode}
%
%    \begin{macrocode}
\int_new:N \g_flowframtkutils_overlay_int
\tl_new:N \l__flowframtkutils_overlay_tl
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_new:N \l__flowframtkutils_auto_overlay_bool
\bool_set_true:N \l__flowframtkutils_auto_overlay_bool
%    \end{macrocode}
%
%    \begin{macrocode}
\tl_new:N \l__flowframtkutils_propval_tl
%    \end{macrocode}
%
% Tag to text mapping (for annotations):
%    \begin{macrocode}
\prop_new:N \l_flowframtkutils_tag_text_prop
%    \end{macrocode}
%
% Tag to overlay number:
%    \begin{macrocode}
\prop_new:N \l_flowframtkutils_tag_overlay_prop
%    \end{macrocode}
%
% Object type to overlay number:
%    \begin{macrocode}
\prop_new:N \l_flowframtkutils_object_type_overlay_prop
%    \end{macrocode}
%Note that groups will have nested objects with a single
%all-encompassing group. Unexpected results may occur if an overlay
%is applied to a group.
%
%Annotations.
%    \begin{macrocode}
\bool_new:N \l_flowframtkutils_annote_bool
\bool_set_false:N \l_flowframtkutils_annote_bool
%    \end{macrocode}
%Include arrows:
%    \begin{macrocode}
\bool_new:N \l_flowframtkutils_annote_arrow_bool
\bool_set_true:N \l_flowframtkutils_annote_arrow_bool
%    \end{macrocode}
%
%    \begin{macrocode}
\dim_new:N \l_flowframtkutils_annote_offsetx_dim
\dim_set:Nn \l_flowframtkutils_annote_offsetx_dim { 1cm }
\dim_new:N \l_flowframtkutils_annote_offsety_dim
\dim_set:Nn \l_flowframtkutils_annote_offsety_dim { 1cm }
%    \end{macrocode}
%
%    \begin{macrocode}
\int_new:N \l_flowframtkutils_annote_location_int
\int_new:N \l_flowframtkutils_current_annote_location_int
\int_const:Nn \c_flowframtkutils_annote_location_auto_int { 0 }
\int_const:Nn \c_flowframtkutils_annote_location_north_int { 1 }
\int_const:Nn \c_flowframtkutils_annote_location_northeast_int { 2 }
\int_const:Nn \c_flowframtkutils_annote_location_east_int { 3 }
\int_const:Nn \c_flowframtkutils_annote_location_southeast_int { 4 }
\int_const:Nn \c_flowframtkutils_annote_location_south_int { 5 }
\int_const:Nn \c_flowframtkutils_annote_location_southwest_int { 6 }
\int_const:Nn \c_flowframtkutils_annote_location_west_int { 7 }
\int_const:Nn \c_flowframtkutils_annote_location_northwest_int { 8 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowframtkutils_annote_uncover:nn
 {
    \flowframtkutils_uncover:nn { #1 } { #2 }
 }
%    \end{macrocode}
%
%Syntax: \meta{tl var} \marg{description} \marg{tag}
%    \begin{macrocode}
\cs_new:Nn \__flowframtkutils_get_annotation_text:Nnn 
 {
   \tl_if_empty:nF { #2 }
    {
      \tl_set:Nn #1 { #2 }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_new:N \l_flowframtkutils_default_auto_bool
\bool_set_false:N \l_flowframtkutils_default_auto_bool
\tl_new:N \l_flowframtkutils_default_overlay_tl
%    \end{macrocode}
%Get default overlay if auto overlay setting not on.
%Syntax: \meta{tl var} \marg{object index} \marg{object}
%    \begin{macrocode}
\cs_new:Nn \flowframtkutils_get_default_overlay:Nnn
 {
   \bool_if:NT \l_flowframtkutils_default_auto_bool
    {
      \tl_if_eq:nnF { #3 } { JDRGroup }
       {
         \tl_if_empty:NTF \l_flowframtkutils_default_overlay_tl
          {
            \int_gincr:N \g_flowframtkutils_overlay_int
          }
          {
            \int_gset:Nn \g_flowframtkutils_overlay_int
             { \l_flowframtkutils_default_overlay_tl }
          }
         \tl_set:NV
            #1
            \g_flowframtkutils_overlay_int
       }
    }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowframtkutils_get_default_annotation_overlay:Nnn
 {
   \tl_set:Nn #1 { 1 }
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\tl_new:N \l__flowframtkutils_annotation_tl
%    \end{macrocode}
%
%    \begin{macrocode}
\keys_define:nn { flowframtkutils / overlay }
 {
    uncover .choice: ,
    uncover / single .code:n =
     {
       \cs_set:Nn \__flowframtkutils_uncover:nn
        {
          \flowframtkutils_uncover:nn { ##1 } { ##2 }
        }
     } ,
    uncover / from .code:n =
     {
       \cs_set:Nn \__flowframtkutils_uncover:nn
        {
          \flowframtkutils_uncover_from:nn { ##1 } { ##2 }
        }
     } ,
    uncover / false .code:n =
     {
       \cs_set:Nn \__flowframtkutils_uncover:nn { ##2 }
     } ,
    annote .choice: ,
    annote / match .code:n =
     {
       \cs_new:Nn \__flowframtkutils_annote_uncover:nn
        {
           \__flowframtkutils_uncover:nn { ##1 } { ##2 }
        }
       \bool_set_true:N \l_flowframtkutils_annote_bool
     } ,
    annote / single .code:n =
     {
       \cs_new:Nn \__flowframtkutils_annote_uncover:nn
        {
           \flowframtkutils_uncover:nn { ##1 } { ##2 }
        }
       \bool_set_true:N \l_flowframtkutils_annote_bool
     } ,
    annote / from .code:n =
     {
       \cs_new:Nn \__flowframtkutils_annote_uncover:nn
        {
           \flowframtkutils_uncover_from:nn { ##1 } { ##2 }
        }
       \bool_set_true:N \l_flowframtkutils_annote_bool
     } ,
    annote / true .code:n =
     {
       \bool_set_true:N \l_flowframtkutils_annote_bool
     } ,
    annote / false .code:n =
     {
       \bool_set_false:N \l_flowframtkutils_annote_bool
     } ,
    annote .default:n = true ,
    annote-position .choices:nn =
      {
         auto , north, northeast , east, southeast , south ,
         southwest, west , northwest
      }
      {
        \int_set:Nn
          \l_flowframtkutils_annote_location_int
           { \l_keys_choice_int - \c_one_int }
      } ,
    annote-arrow .code:n =
      {
        \keys_set:nn { flowframtkutils / overlay / arrow } { #1 }
      } ,
    annote-arrow .default:n = show ,
    annote-text .choice: ,
    annote-text / hide .code:n = 
     {
       \cs_set:Nn \__flowframtkutils_get_annotation_text:Nnn { }
     } ,
    annote-text / description .code:n = 
     {
       \cs_set:Nn \__flowframtkutils_get_annotation_text:Nnn
        {
          \tl_if_empty:nF { ##2 }
           {
             \tl_set:Nn ##1 { ##2 }
           }
        }
     } ,
    annote-text / tag .code:n = 
     {
       \cs_set:Nn \__flowframtkutils_get_annotation_text:Nnn
        {
          \tl_if_empty:nF { ##3 }
           {
             \tl_set:Nn ##1 { ##3 }
           }
        }
     } ,
    annote-text / description-or-tag .code:n = 
     {
       \cs_set:Nn \__flowframtkutils_get_annotation_text:Nnn
        {
          \tl_if_empty:nTF { ##2 }
           {
             \tl_if_empty:nF { ##3 }
              {
                \tl_set:Nn ##1 { ##3 }
              }
           }
           {
             \tl_set:Nn ##1 { ##2 }
           }
        }
     } ,
    annote-text / tag-map .code:n = 
     {
       \cs_set:Nn \__flowframtkutils_get_annotation_text:Nnn
        {
          \tl_if_empty:nF { ##3 }
           {
             \prop_get:NnN \l_flowframtkutils_tag_text_prop
              { ##3 } ##1
           }
        }
     } ,
    tag-text .code:n =
     {
       \prop_set_from_keyval:Nn \l_flowframtkutils_tag_text_prop { #1 }
       \prop_if_empty:NF \l_flowframtkutils_tag_text_prop
        {
          \cs_set:Nn \__flowframtkutils_get_annotation_text:Nnn
           {
             \tl_if_empty:nF { ##3 }
              {
                \prop_get:NnN \l_flowframtkutils_tag_text_prop
                 { ##3 } ##1
              }
           }
        }
     } ,
    tag-overlay .code:n =
     {
       \prop_set_from_keyval:Nn \l_flowframtkutils_tag_overlay_prop { #1 }
       \prop_if_empty:NF \l_flowframtkutils_tag_overlay_prop
        {
          \bool_set_false:N \l__flowframtkutils_auto_overlay_bool
        }
     } ,
    object-overlay .code:n =
     {
       \prop_clear:N \l_flowframtkutils_object_type_overlay_prop
       \keys_set:nn { flowframtkutils / overlay / objects } { #1 }
       \prop_if_empty:NF \l_flowframtkutils_object_type_overlay_prop
        {
          \bool_set_false:N \l__flowframtkutils_auto_overlay_bool
        }
     } ,
    auto-overlay .bool_set:N = \l__flowframtkutils_auto_overlay_bool ,
    fallback-overlay .code:n = 
     {
       \keys_set:nn { flowframtkutils / overlay / fallback } { #1 }
     } ,
    fallback-overlay .default:n = { enable } ,
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\keys_define:nn { flowframtkutils / overlay / fallback }
 {
    enable .bool_set:N = \l_flowframtkutils_default_auto_bool ,
    fixed .tl_set:N = \l_flowframtkutils_default_overlay_tl ,
    increment .code:n = 
     {
       \tl_clear:N \l_flowframtkutils_default_overlay_tl
     } ,
    increment .value_forbidden:n = true ,
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\keys_define:nn { flowframtkutils / overlay / objects }
 {
    group .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRGroup } { #1 } 
     },
    path .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRPath } { #1 } 
     },
    text .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRText } { #1 } 
     },
    text-path .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRTextPath } { #1 } 
     },
    symmetric-path .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRSymmetricPath } { #1 } 
     },
    bitmap .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRBitmap } { #1 } 
     },
    scaled-pattern .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRScaledPattern } { #1 } 
     },
    spiral-pattern .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRSpiralPattern } { #1 } 
     },
    rotational-pattern .code:n =
     {
       \prop_put:Nne
         \l_flowframtkutils_object_type_overlay_prop
         { JDRRotationalPattern } { #1 } 
     },
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\keys_define:nn { flowframtkutils / overlay / arrow }
 {
    show .bool_set:N = \l_flowframtkutils_annote_arrow_bool ,
    hide .bool_set_inverse:N = \l_flowframtkutils_annote_arrow_bool ,
    dx .dim_set:N = \l_flowframtkutils_annote_offsetx_dim ,
    dy .dim_set:N = \l_flowframtkutils_annote_offsety_dim ,
    color .code:n = 
    {
      \tl_if_empty:nTF { #1 }
       {
         \tl_clear:N \l_flowframtkutils_annotation_stroke_color_tl
       }
       {
         \tl_set:Nn \l_flowframtkutils_annotation_stroke_color_tl
          { \pgfsetstrokecolor { #1 } }
       }
    } ,
    start .code:n =
    {
      \tl_if_empty:nTF { #1 }
       {
         \tl_clear:N \l_flowframtkutils_annotation_start_arrow_tl
       }
       {
         \tl_set:Nn \l_flowframtkutils_annotation_start_arrow_tl
          {
             \pgfsetarrowsstart { #1 }
          }
       }
    } ,
    end .code:n =
    {
      \tl_if_empty:nTF { #1 }
       {
         \tl_clear:N \l_flowframtkutils_annotation_end_arrow_tl
       }
       {
         \tl_set:Nn \l_flowframtkutils_annotation_end_arrow_tl
          {
             \pgfsetarrowsend { #1 }
          }
       }
    } ,
 }
%    \end{macrocode}
%
%    \begin{macrocode}
\dim_new:N \l__flowframtkutils_image_minx_dim
\dim_new:N \l__flowframtkutils_image_miny_dim
\dim_new:N \l__flowframtkutils_image_maxx_dim
\dim_new:N \l__flowframtkutils_image_maxy_dim
\dim_new:N \l__flowframtkutils_image_cx_dim
\dim_new:N \l__flowframtkutils_image_cy_dim
\dim_new:N \l__flowframtkutils_image_width_dim
\dim_new:N \l__flowframtkutils_image_height_dim
%    \end{macrocode}
%Object boundary:
%    \begin{macrocode}
\dim_new:N \l__flowframtkutils_object_minx_dim
\dim_new:N \l__flowframtkutils_object_miny_dim
\dim_new:N \l__flowframtkutils_object_maxx_dim
\dim_new:N \l__flowframtkutils_object_maxy_dim
\dim_new:N \l__flowframtkutils_object_cx_dim
\dim_new:N \l__flowframtkutils_object_cy_dim
\dim_new:N \l__flowframtkutils_object_width_dim
\dim_new:N \l__flowframtkutils_object_height_dim
%    \end{macrocode}
%
%    \begin{macrocode}
\dim_new:N \l__flowframtkutils_x_dim
\dim_new:N \l__flowframtkutils_y_dim
%    \end{macrocode}
%Keep track of current group:
%    \begin{macrocode}
\int_new:N \l_flowframtkutils_group_level_int
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \flowframtkutils_uncover_encap:nnnnnnnn
 {
%    \end{macrocode}
%Default to no overlay:
%    \begin{macrocode}
    \cs_set_eq:NN \__flowframtkutils_current_encap:nn \use_ii:nn
    \int_if_zero:nTF { #1 }
     {
%    \end{macrocode}
% Start of the image (0, JDRGroup, no tag, image description).
%    \begin{macrocode}
       \int_gzero:N \g_flowframtkutils_overlay_int
       \tl_clear:N \l__flowframtkutils_overlay_tl
%    \end{macrocode}
%This will be incremented later. So the group level for the entire
%image will be 1. Actual top-level groups will be level 2,
%sub-groups level 3, etc.
%    \begin{macrocode}
       \int_zero:N \l_flowframtkutils_group_level_int
%    \end{macrocode}
% The bottom left position will be in the form
% \cs{pgfpoint}\marg{x}\marg{y}.
%    \begin{macrocode}
       \pgfextractx \l__flowframtkutils_image_minx_dim { #5 }
       \pgfextracty \l__flowframtkutils_image_miny_dim { #5 }
%    \end{macrocode}
%Width and height:
%    \begin{macrocode}
       \dim_set:Nn \l__flowframtkutils_image_width_dim { #6 }
       \dim_set:Nn \l__flowframtkutils_image_height_dim { #7 }
%    \end{macrocode}
%Calculate maximum.
%    \begin{macrocode}
       \dim_set:Nn \l__flowframtkutils_image_maxx_dim
         {
            \l__flowframtkutils_image_minx_dim
          + \l__flowframtkutils_image_width_dim
         }
       \dim_set:Nn \l__flowframtkutils_image_maxy_dim
         {
            \l__flowframtkutils_image_miny_dim
          + \l__flowframtkutils_image_height_dim
         }
%    \end{macrocode}
%Calculate centre point.
%    \begin{macrocode}
       \dim_set:Nn \l__flowframtkutils_image_cx_dim
         {
            \l__flowframtkutils_image_minx_dim
          + 0.5 \l__flowframtkutils_image_width_dim
         }
       \dim_set:Nn \l__flowframtkutils_image_cy_dim
         {
            \l__flowframtkutils_image_miny_dim
          + 0.5 \l__flowframtkutils_image_height_dim
         }
%    \end{macrocode}
%If annote setting is on, set the current object bounds to the image
%bounds.
%    \begin{macrocode}
       \bool_if:NT \l_flowframtkutils_annote_bool
         {
           \dim_set_eq:NN
              \l__flowframtkutils_object_minx_dim
              \l__flowframtkutils_image_minx_dim
           \dim_set_eq:NN
              \l__flowframtkutils_object_miny_dim
              \l__flowframtkutils_image_miny_dim
           \dim_set_eq:NN
              \l__flowframtkutils_object_maxx_dim
              \l__flowframtkutils_image_maxx_dim
           \dim_set_eq:NN
              \l__flowframtkutils_object_maxy_dim
              \l__flowframtkutils_image_maxy_dim
           \dim_set_eq:NN
              \l__flowframtkutils_object_cx_dim
              \l__flowframtkutils_image_cx_dim
           \dim_set_eq:NN
              \l__flowframtkutils_object_cy_dim
              \l__flowframtkutils_image_cy_dim
           \dim_set_eq:NN
              \l__flowframtkutils_object_width_dim
              \l__flowframtkutils_image_width_dim
           \dim_set_eq:NN
              \l__flowframtkutils_object_height_dim
              \l__flowframtkutils_image_height_dim
         }
     }
     {
%    \end{macrocode}
%Obtain the overlay, if set.
%    \begin{macrocode}
       \tl_set:Nn \l__flowframtkutils_propval_tl { \q_no_value }
       \bool_if:NTF \l__flowframtkutils_auto_overlay_bool 
        {
%    \end{macrocode}
%Auto setting is on. Overlay is incremented but skip groups to
%prevent nesting.
%    \begin{macrocode}
          \tl_if_eq:nnF { #2 } { JDRGroup }
           {
             \int_gincr:N \g_flowframtkutils_overlay_int
             \tl_set:NV
                \l__flowframtkutils_propval_tl
                \g_flowframtkutils_overlay_int
           }
        }
        {
%    \end{macrocode}
%Tag setting takes precedence.
%    \begin{macrocode}
          \tl_if_empty:nF { #4 }
           {
             \prop_get:NnN \l_flowframtkutils_tag_overlay_prop { #4 }
               \l__flowframtkutils_propval_tl
           }
          \quark_if_no_value:NT
               \l__flowframtkutils_propval_tl
           {
%    \end{macrocode}
%If no tag setting, use the object setting. The second argument is
%the object type and will always be non-empty.
%    \begin{macrocode}
             \prop_get:NnN \l_flowframtkutils_object_type_overlay_prop { #2 }
               \l__flowframtkutils_propval_tl
%    \end{macrocode}
%If no object setting either, get the default:
%    \begin{macrocode}
             \quark_if_no_value:NT
                  \l__flowframtkutils_propval_tl
              {
                \flowframtkutils_get_default_overlay:Nnn
                  \l__flowframtkutils_propval_tl
                  { #1 } { #2 }
              }
           }
        }
%    \end{macrocode}
%Set the overlay and uncover functions as appropriate.
%    \begin{macrocode}
       \quark_if_no_value:NTF
            \l__flowframtkutils_propval_tl
        {
          \tl_clear:N \l__flowframtkutils_overlay_tl
        }
        {
           \tl_if_empty:NF \l__flowframtkutils_propval_tl
            {
              \cs_set_eq:NN
                \__flowframtkutils_current_encap:nn 
                \__flowframtkutils_uncover:nn
            }
          \tl_set_eq:NN 
            \l__flowframtkutils_overlay_tl
            \l__flowframtkutils_propval_tl
        }
       \bool_if:NT \l_flowframtkutils_annote_bool
        {
%    \end{macrocode}
%Annotation on. Store the current object's bounding box dimensions.
%    \begin{macrocode}
          \pgfextractx \l__flowframtkutils_object_minx_dim { #5 }
          \pgfextracty \l__flowframtkutils_object_miny_dim { #5 }
          \dim_set:Nn \l__flowframtkutils_object_width_dim { #6 }
          \dim_set:Nn \l__flowframtkutils_object_height_dim { #7 }
%    \end{macrocode}
%Calculate maximum point.
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_object_maxx_dim
            {
               \l__flowframtkutils_object_minx_dim
              + \l__flowframtkutils_object_width_dim
            }
          \dim_set:Nn \l__flowframtkutils_object_maxy_dim
            {
               \l__flowframtkutils_object_miny_dim
              + \l__flowframtkutils_object_height_dim
            }
%    \end{macrocode}
%Calculate centre point.
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_object_cx_dim
            {
               \l__flowframtkutils_object_minx_dim
             + 0.5 \l__flowframtkutils_object_width_dim
            }
          \dim_set:Nn \l__flowframtkutils_object_cy_dim
            {
               \l__flowframtkutils_object_miny_dim
             + 0.5 \l__flowframtkutils_object_height_dim
            }
        }
     }
   \tl_if_eq:nnT { #2 } { JDRGroup }
     {
%    \end{macrocode}
%Increment group level. This isn't scoped so it will need
%decrementing afterwards.
%    \begin{macrocode}
       \int_incr:N \l_flowframtkutils_group_level_int
     }
%    \end{macrocode}
%Encapsulate object.
%    \begin{macrocode}
   \exp_args:NV
   \__flowframtkutils_current_encap:nn 
     \l__flowframtkutils_overlay_tl { #8 }
   \bool_if:NT \l_flowframtkutils_annote_bool
    {
%    \end{macrocode}
%Add annotation (arrow, if applicable, and text).
%    \begin{macrocode}
      \tl_clear:N \l__flowframtkutils_annotation_tl
      \tl_set:Nn \l__flowframtkutils_propval_tl { \q_no_value }
      \__flowframtkutils_get_annotation_text:Nnn 
        \l__flowframtkutils_propval_tl
        { #3 } { #4 }
%    \end{macrocode}
%If no text value, skip.
%    \begin{macrocode}
      \quark_if_no_value:NF
           \l__flowframtkutils_propval_tl
       {
          \int_if_zero:nTF
              { \l_flowframtkutils_annote_location_int }
            {
%    \end{macrocode}
%Position set to auto so calculate suitable position id.
%    \begin{macrocode}
              \__flowframtkutils_auto_set_annote_location:
            }
            {
%    \end{macrocode}
%Specific position, so just store position id.
%    \begin{macrocode}
              \int_set_eq:NN
                 \l_flowframtkutils_current_annote_location_int
                 \l_flowframtkutils_annote_location_int
            }
%    \end{macrocode}
%Set the annotation content.
%    \begin{macrocode}
          \exp_args:NV
          \__flowframtkutils_set_annote_content:n
            \l__flowframtkutils_propval_tl
       }
%    \end{macrocode}
%If an annotation has been set, draw it with the applicable overlay.
%    \begin{macrocode}
      \tl_if_empty:NF \l__flowframtkutils_annotation_tl
       {
         \tl_if_empty:NT \l__flowframtkutils_overlay_tl
          {
%    \end{macrocode}
%No overlay for the current object so use the default annotation
%overlay.
%    \begin{macrocode}
             \flowframtkutils_get_default_annotation_overlay:Nnn
              \l__flowframtkutils_overlay_tl { #1 } { #2 }
          }
%    \end{macrocode}
%Draw the annotation:
%    \begin{macrocode}
         \exp_args:NVV
         \__flowframtkutils_annote_uncover:nn 
            \l__flowframtkutils_overlay_tl
            \l__flowframtkutils_annotation_tl
       }
    }
%    \end{macrocode}
%Decrement the group level counter.
%    \begin{macrocode}
   \tl_if_eq:nnT { #2 } { JDRGroup }
     {
       \int_decr:N \l_flowframtkutils_group_level_int
     }
 }
%    \end{macrocode}
%
%Used when the annotation location is set to auto:
%    \begin{macrocode}
\cs_new:Nn \__flowframtkutils_auto_set_annote_location:
 {
   \dim_compare:nNnTF
      { \l__flowframtkutils_object_cx_dim }
       < 
      { \l__flowframtkutils_image_cx_dim }
    {
%    \end{macrocode}
%The centre of the object's bounding box is to the left of the
%centre of the image's bounding box (West).
%    \begin{macrocode}
      \int_set_eq:NN
        \l_flowframtkutils_current_annote_location_int
        \c_flowframtkutils_annote_location_west_int
      \dim_compare:nNnTF
         { \l__flowframtkutils_object_miny_dim }
          > 
         { \l__flowframtkutils_image_cy_dim }
       {
%    \end{macrocode}
%The lowest point of the object's bounding box is higher than the
%middle of the image's bounding box.
%    \begin{macrocode}
         \int_set_eq:NN
           \l_flowframtkutils_current_annote_location_int
           \c_flowframtkutils_annote_location_northwest_int
       }
       {
         \dim_compare:nNnT
            { \l__flowframtkutils_object_maxy_dim }
             < 
            { \l__flowframtkutils_image_cy_dim }
          {
%    \end{macrocode}
%The highest point of the object's bounding box is lower than the
%middle of the image's bounding box.
%    \begin{macrocode}
            \int_set_eq:NN
              \l_flowframtkutils_current_annote_location_int
              \c_flowframtkutils_annote_location_southwest_int
          }
       }
    }
    {
%    \end{macrocode}
%The centre of the object's bounding box is not to the left of the
%centre of the image's bounding box (East).
%    \begin{macrocode}
      \int_set_eq:NN
        \l_flowframtkutils_current_annote_location_int
        \c_flowframtkutils_annote_location_east_int
      \dim_compare:nNnTF
         { \l__flowframtkutils_object_miny_dim }
          > 
         { \l__flowframtkutils_image_cy_dim }
       {
%    \end{macrocode}
%The lowest point of the object's bounding box is higher than the
%middle of the image's bounding box.
%    \begin{macrocode}
         \int_set_eq:NN
           \l_flowframtkutils_current_annote_location_int
           \c_flowframtkutils_annote_location_northeast_int
       }
       {
         \dim_compare:nNnT
            { \l__flowframtkutils_object_maxy_dim }
             < 
            { \l__flowframtkutils_image_cy_dim }
          {
%    \end{macrocode}
%The highest point of the object's bounding box is lower than the
%middle of the image's bounding box.
%    \begin{macrocode}
            \int_set_eq:NN
              \l_flowframtkutils_current_annote_location_int
              \c_flowframtkutils_annote_location_southeast_int
          }
       }
    }
 }
%    \end{macrocode}
%Default arrow colour is black:
%    \begin{macrocode}
\tl_new:N \l_flowframtkutils_annotation_stroke_color_tl
\tl_set:Nn \l_flowframtkutils_annotation_stroke_color_tl
 {
    \pgfsetstrokecolor { black }
 }
%    \end{macrocode}
%Default start arrow head (at the bounding box edge):
%    \begin{macrocode}
\tl_new:N \l_flowframtkutils_annotation_start_arrow_tl
\tl_set:Nn \l_flowframtkutils_annotation_start_arrow_tl
 {
    \pgfsetarrowsstart { < }
 }
%    \end{macrocode}
%No end arrow head by default (the point where the text is placed).
%    \begin{macrocode}
\tl_new:N \l_flowframtkutils_annotation_end_arrow_tl
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn \__flowframtkutils_set_annote_content:n
 {
%    \end{macrocode}
%The code to draw the arrow and text is stored in a token list
%variable.
%    \begin{macrocode}
    \tl_set:Nn \l__flowframtkutils_annotation_tl
     {
        \begin { pgfscope }
        \l_flowframtkutils_annotation_stroke_color_tl
        \l_flowframtkutils_annotation_start_arrow_tl
        \l_flowframtkutils_annotation_end_arrow_tl
     }
%    \end{macrocode}
%The position of the text in relation to the object's bounding box
%is indicated by a numeric id.
%    \begin{macrocode}
    \int_case:nn { \l_flowframtkutils_current_annote_location_int }
     {
       { \c_flowframtkutils_annote_location_north_int }
        {
%    \end{macrocode}
%North (vertical arrow pointing downwards with text on top).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set_eq:NN
             \l__flowframtkutils_x_dim
             \l__flowframtkutils_object_cx_dim
          \dim_set:Nn \l__flowframtkutils_y_dim
           {
              \l__flowframtkutils_object_maxy_dim
                + \l_flowframtkutils_annote_offsety_dim
           }
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_cx_dim }
                       { \dim_use:N \l__flowframtkutils_object_maxy_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               bottom ,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
       { \c_flowframtkutils_annote_location_northeast_int }
        {
%    \end{macrocode}
%North-East (slanted arrow pointing down left with text to the upper right).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_x_dim
           {
              \l__flowframtkutils_object_maxx_dim
                + \l_flowframtkutils_annote_offsetx_dim
           }
          \dim_set:Nn \l__flowframtkutils_y_dim
           {
              \l__flowframtkutils_object_maxy_dim
                + \l_flowframtkutils_annote_offsety_dim
           }
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_maxx_dim }
                       { \dim_use:N \l__flowframtkutils_object_maxy_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               left , bottom ,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
       { \c_flowframtkutils_annote_location_east_int }
        {
%    \end{macrocode}
%East (horizontal arrow pointing leftwards with text to the right).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_x_dim
           {
              \l__flowframtkutils_object_maxx_dim
                + \l_flowframtkutils_annote_offsetx_dim
           }
          \dim_set_eq:NN 
            \l__flowframtkutils_y_dim
            \l__flowframtkutils_object_cy_dim
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_maxx_dim }
                       { \dim_use:N \l__flowframtkutils_object_cy_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               left ,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
       { \c_flowframtkutils_annote_location_southeast_int }
        {
%    \end{macrocode}
%South-East (slanted arrow pointing up left with text to the lower right).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_x_dim
           {
              \l__flowframtkutils_object_maxx_dim
                + \l_flowframtkutils_annote_offsetx_dim
           }
          \dim_set:Nn \l__flowframtkutils_y_dim
           {
              \l__flowframtkutils_object_miny_dim
                - \l_flowframtkutils_annote_offsety_dim
           }
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_maxx_dim }
                       { \dim_use:N \l__flowframtkutils_object_miny_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               top, left ,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
       { \c_flowframtkutils_annote_location_south_int }
        {
%    \end{macrocode}
%South (vertical arrow pointing upwards with text below).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set_eq:NN
             \l__flowframtkutils_x_dim
             \l__flowframtkutils_object_cx_dim
          \dim_set:Nn \l__flowframtkutils_y_dim
           {
              \l__flowframtkutils_object_miny_dim
                - \l_flowframtkutils_annote_offsety_dim
           }
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_cx_dim }
                       { \dim_use:N \l__flowframtkutils_object_miny_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               top,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
       { \c_flowframtkutils_annote_location_southwest_int }
        {
%    \end{macrocode}
%South-West (slanted arrow pointing up right with text to the lower left).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_x_dim
           {
             \l__flowframtkutils_object_minx_dim
              - \l_flowframtkutils_annote_offsetx_dim
           }
          \dim_set:Nn \l__flowframtkutils_y_dim
           {
              \l__flowframtkutils_object_miny_dim
                - \l_flowframtkutils_annote_offsety_dim
           }
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_minx_dim }
                       { \dim_use:N \l__flowframtkutils_object_miny_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               top , right,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
       { \c_flowframtkutils_annote_location_west_int }
        {
%    \end{macrocode}
%West (horizontal arrow pointing rightwards with text to the left).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_x_dim
           {
              \l__flowframtkutils_object_minx_dim
              - \l_flowframtkutils_annote_offsetx_dim
           }
          \dim_set_eq:NN
            \l__flowframtkutils_y_dim
            \l__flowframtkutils_object_cy_dim
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_minx_dim }
                       { \dim_use:N \l__flowframtkutils_object_cy_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               right,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
       { \c_flowframtkutils_annote_location_northwest_int }
        {
%    \end{macrocode}
%North-West (slanted arrow pointing down right with text to the upper left).
%Calculate the co-ordinates of the text (the end of the arrow).
%    \begin{macrocode}
          \dim_set:Nn \l__flowframtkutils_x_dim
           {
             \l__flowframtkutils_object_minx_dim
              - \l_flowframtkutils_annote_offsetx_dim
           }
          \dim_set:Nn \l__flowframtkutils_y_dim
           {
             \l__flowframtkutils_object_maxy_dim
               + \l_flowframtkutils_annote_offsety_dim
           }
%    \end{macrocode}
%Add the code to draw the arrow if applicable.
%    \begin{macrocode}
          \bool_if:NT \l_flowframtkutils_annote_arrow_bool
           {
             \tl_put_right:Ne \l__flowframtkutils_annotation_tl
              {
                 \exp_not:N \pgfpathmoveto
                   {
                     \exp_not:N \pgfpoint
                       { \dim_use:N \l__flowframtkutils_object_minx_dim }
                       { \dim_use:N \l__flowframtkutils_object_maxy_dim }
                   }
                 \exp_not:N \pgfpathlineto
                   {
                     \exp_not:N \pgfpoint
                       {
                         \dim_use:N \l__flowframtkutils_x_dim
                       }
                       {
                         \dim_use:N \l__flowframtkutils_y_dim
                       }
                   }
                  \exp_not:N \pgfusepath { stroke }
              }
           }
%    \end{macrocode}
%Add the code to position text.
%    \begin{macrocode}
          \tl_put_right:Ne \l__flowframtkutils_annotation_tl
           {
             \exp_not:N \pgftext
              [
               bottom, right,
               at = {
                \exp_not:N \pgfpoint
                  {
                    \dim_use:N \l__flowframtkutils_x_dim
                  }
                  {
                    \dim_use:N \l__flowframtkutils_y_dim
                  }
              } ]
              { #1 }
           }
        }
     }
    \tl_put_right:Nn \l__flowframtkutils_annotation_tl
     {
        \end { pgfscope }
     }
 }
%    \end{macrocode}
%
%\begin{macro}{\FlowFramTkUtilsSetOverlayEncap}
%    \begin{macrocode}
\NewDocumentCommand \FlowFramTkUtilsSetOverlayEncap { o }
 {
   \IfValueT { #1 }
    {
      \keys_set:nn { flowframtkutils / overlay } { #1 }
    }
   \renewcommand \flowframtkencapobject
    {
      \flowframtkutils_uncover_encap:nnnnnnnn
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\FlowFramTkUtilsOverlayEncapSetup}
%    \begin{macrocode}
\NewDocumentCommand \FlowFramTkUtilsOverlayEncapSetup { m }
 {
   \keys_set:nn { flowframtkutils / overlay } { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\includeteximage}
%FlowframTk's export to \env{pgfpicture} option just creates a
%".tex" file that contains the \env{pgfpicture} environment. This
%file may simply be \cs{input} but provide a command similar to
%\cs{includegraphics} that can be used with graphics options to
%resize the image. This is just provided as there are other packages
%(e.g.\ \sty{jmlrutils}) that define this command.
%
%NB although it's possible to change \sty{pgf} co-ordinate scaling, 
%the image may include text or bitmaps that may need to be scaled too. 
%    \begin{macrocode}
\ProvideDocumentCommand \includeteximage { o m }
 {
   \group_begin:
    \let\input@path\Ginput@path
    \IfValueTF { #1 }
     {
       \hbox_set:Nn \l__flowframtk_img_box
        { \file_input:n { #2 } }
       \keys_set:nn { flowframtk / img } { #1 }
       \__flowframtk_img_apply_resize:
       \mbox { \box_use:N \l__flowframtk_img_box }
     }
     {
       \file_input:n { #2 }
     }
   \group_end:
 }
%    \end{macrocode}
%\end{macro}
%
%Variables for use in the above.
%    \begin{macrocode}
\box_new:N \l__flowframtk_img_box
\tl_new:N \l__flowframtk_img_width_tl
\tl_new:N \l__flowframtk_img_height_tl
%    \end{macrocode}
%
%Apply resizing options:
%    \begin{macrocode}
\cs_new:Nn \__flowframtk_img_apply_resize:
{
  \tl_if_empty:NTF \l__flowframtk_img_width_tl
  {
    \tl_if_empty:NF \l__flowframtk_img_height_tl
     {
       \box_resize_to_ht:Nn
        \l__flowframtk_img_box { \l__flowframtk_img_height_tl }
     }
    \tl_clear:N \l__flowframtk_img_height_tl
  }
  {
    \tl_if_empty:NTF \l__flowframtk_img_height_tl
     {
       \box_resize_to_wd:Nn 
        \l__flowframtk_img_box { \l__flowframtk_img_width_tl }
     }
     {
       \box_resize_to_wd_and_ht:Nnn 
        \l__flowframtk_img_box
         { \l__flowframtk_img_width_tl }
         { \l__flowframtk_img_height_tl }
       \tl_clear:N \l__flowframtk_img_height_tl
     }
    \tl_clear:N \l__flowframtk_img_width_tl
  }
}
%    \end{macrocode}
%
%    \begin{macrocode}
\keys_define:nn { flowframtk / img }
 {
    scale .code:n =
     {
       \__flowframtk_img_apply_resize:
       \box_scale:Nnn  \l__flowframtk_img_box { #1 } { #1 }
     },
    angle .code:n =
     {
       \__flowframtk_img_apply_resize:
       \box_rotate:Nn  \l__flowframtk_img_box { #1 }
     },
    width .tl_set:N = \l__flowframtk_img_width_tl ,
    height .tl_set:N = \l__flowframtk_img_height_tl ,
    alt .code:n = { }
 }
%    \end{macrocode}
%
%\begin{macro}{\flowframtkimgtitlechar}
%\begin{definition}
%\cs{flowframtkimgtitlechar}\marg{original-char}\marg{PDF-char}
%\end{definition}
%In case it's necessary to use \cs{pdfinfo}, FlowframTk will detect
%and encapsulate problematic characters in the title with this
%command. The first argument is the original character and the
%second is the escaped character suitable for use in a PDF string.
%For example, if the first argument is "(" or ")" then the second
%will be \verb|\(| or \verb|\)|. NB this must be able to expand.
%    \begin{macrocode}
\newcommand \flowframtkimgtitlechar [ 2 ] { #1 }
%    \end{macrocode}
%\end{macro}
%The above will be locally changed to the following when the title
%needs to be written to the "/Title" PDF string.
%    \begin{macrocode}
\cs_new:Nn \__flowframtk_imgtitlechar:nn
 {
   \tl_to_str:n { #2 }
 }
%    \end{macrocode}
%Provide a command to use if \sty{hyperref} hasn't been loaded. This will
%use \cs{pdfinfo} or \cs{pdfextension}, if available.
%    \begin{macrocode}
\cs_if_exist:NTF \pdfinfo
 {
   \cs_new:Nn \__flowframtk_pdfinfo:n
    {
      \pdfinfo { #1 }
    }
 }
 {
   \cs_if_exist:NTF \pdfextension
    {
      \cs_new:Nn \__flowframtk_pdfinfo:n
       {
         \pdfextension info { #1 }
       }
    }
    {
      \cs_new:Nn \__flowframtk_pdfinfo:n { }
    }
 }
%    \end{macrocode}
%Token list variable to hold the title:
%    \begin{macrocode}
\tl_new:N \l_flowframtk_image_title_tl
%    \end{macrocode}
%
%\begin{macro}{\flowframtkSetTitle}
%This command is provided to allow the image's early preamble to
%provide an alternative definition.
%    \begin{macrocode}
\ProvideDocumentCommand \flowframtkSetTitle { m }
 {
   \tl_set:Ne \l_flowframtk_image_title_tl { #1 }
   \cs_if_exist:NTF \hypersetup
    {
      \hypersetup { pdftitle = { \l_flowframtk_image_title_tl } }
    }
    {
      \cs_set_eq:NN \flowframtkimgtitlechar \__flowframtk_imgtitlechar:nn
      \__flowframtk_pdfinfo:n { /Title ( #1 ) }
      \cs_set_eq:NN \flowframtkimgtitlechar \use_i:nn
    }
   \cs_if_exist:NT \title
    {
      \exp_args:NV \title \l_flowframtk_image_title_tl
    }
 }
%    \end{macrocode}
%\end{macro}
%Token list variable to hold the creation date:
%    \begin{macrocode}
\tl_new:N \l_flowframtk_image_creationdate_tl
%    \end{macrocode}
%
%\begin{macro}{\flowframtkSetCreationDate}
%Again, this command is provided to allow the image's early preamble to
%provide an alternative definition.
%    \begin{macrocode}
\ProvideDocumentCommand \flowframtkSetCreationDate { m }
 {
   \tl_set:Ne \l_flowframtk_image_creationdate_tl
     {
       \tl_to_str:n { #1 }
     }
   \cs_if_exist:NTF \hypersetup
    {
      \exp_args:Ne
        \hypersetup
        { pdfcreationdate = { \l_flowframtk_image_creationdate_tl } }
    }
    {
      \exp_args:Ne
        \__flowframtk_pdfinfo:n 
          { /CreationDate (  \l_flowframtk_image_creationdate_tl ) }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\keys_define:nn { flowframtk / imageinfo }
{
   title .code:n = \flowframtkSetTitle { #1 } ,
   creationdate .code:n = \flowframtkSetCreationDate { #1 } ,
}
%    \end{macrocode}
%
%\begin{macro}{\flowframtkimageinfo}
%This is the command that FlowframTk will actually write to the
%exported file, if the export settings request PDF data to be added:
%    \begin{macrocode}
\NewDocumentCommand \flowframtkimageinfo { m }
 {
   \keys_set:nn { flowframtk / imageinfo } { #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%
%The following commands are specifically for export options that
%define flow, static and dynamic frames. The image objects that have
%\sty{flowfram} data assigned to them may either use the associated
%object as a border or simply use the object's bounding box to
%determine the frame's location and size. Where the object should be
%used as a border, a command needs to be defined that can be used as
%the border frame command.
%
%\begin{macro}{\flowframtkNewFrameBorder}
%\begin{definition}
%\cs{flowframtkNewFrameBorder}\marg{label}\marg{pgfpicture-code}
%\end{definition}
%Defines an internal command that takes a single argument, which
%will be the content of the applicable flow, static or dynamic
%frame. This command will then be used as the frame's border
%command (instead of \cs{fbox}). The second argument is the
%\sty{pgf} code needed to replicate the object (path, bitmap etc)
%from the image and position the frame content within the picture
%according to the margins setup in FlowframTk.
%    \begin{macrocode}
\NewDocumentCommand \flowframtkNewFrameBorder { m m }
 {
   \cs_set:cpn { @flf@border@ #1 } ##1 { #2 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkUseFrameBorderCsName}
%Expands to the control sequence name of the custom border frame
%command that was defined by \cs{flowframtkNewFrameBorder}.
%    \begin{macrocode}
\newcommand \flowframtkUseFrameBorderCsName [ 1 ]
 {
   @flf@border@ #1
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkUseFrameBorderCsName}
%Use the custom border frame
%command that was defined by \cs{flowframtkNewFrameBorder}.
%    \begin{macrocode}
\newcommand \flowframtkUseFrameBorderCs [ 1 ]
 {
   \use:n { @flf@border@ #1 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkNewDynamicStyle}
%Create a style command for a dynamic frame
%    \begin{macrocode}
\NewDocumentCommand \flowframtkNewDynamicStyle { m m }
 {
   \cs_set:cpn { @flf@dfstyle@ #1 } { #2 }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkUseDynamicStyleCsName}
%Expands to the control sequence name of a style command for a dynamic frame
%    \begin{macrocode}
\NewDocumentCommand \flowframtkUseDynamicStyleCsName { m  }
 {
   @flf@dfstyle@ #1
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkUseDynamicStyle}
%Expands to the control sequence name of a style command for a dynamic frame
%    \begin{macrocode}
\NewDocumentCommand \flowframtkUseDynamicStyle { m  }
 {
   \use:n { @flf@dfstyle@ #1 } 
 }
%    \end{macrocode}
%\end{macro}
%
%These commands are used instead of \cs{makedfheaderfooter} for 
%a bespoke dynamic headers and footers.
%
%\begin{macro}{\flowframtkSetDynamicOddHead}
%The same header frame is used for both odd and even pages or it's a
%single-sided document.
%    \begin{macrocode}
\NewDocumentCommand \flowframtkSetDynamicOddHead { m }
 {
   \__flowfram_get_dynamic_id:n { #1 }
   \int_set_eq:NN \g__flowfram_dynamic_header_int \l__flowfram_id_int
   \renewcommand \@dothehead { }
   \renewcommand \@dodynamicthehead
    {
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_header_int }
       {
         \flowfram_dynamic_header:n
           { \g__flowfram_dynamic_header_int }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkSetDynamicOddEvenHead}
%There are two dynamic header frames, one for
%odd pages and one for even pages.
%    \begin{macrocode}
\NewDocumentCommand \flowframtkSetDynamicOddEvenHead { m m }
 {
   \__flowfram_get_dynamic_id:n { #1 }
   \int_set_eq:NN \g__flowfram_dynamic_header_int \l__flowfram_id_int
   \__flowfram_get_dynamic_id:n { #2 }
   \int_set_eq:NN \g__flowfram_dynamic_even_header_int \l__flowfram_id_int
   \renewcommand \@dothehead { }
   \renewcommand \@dodynamicthehead
    {
%    \end{macrocode}
%odd head
%    \begin{macrocode}
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_header_int }
       {
         \flowfram_dynamic_odd_header:n
           { \g__flowfram_dynamic_header_int }
       }
%    \end{macrocode}
%even head
%    \begin{macrocode}
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_even_header_int }
       {
         \flowfram_dynamic_even_header:n
           { \g__flowfram_dynamic_even_header_int }
       }
    }
%    \end{macrocode}
%Ensure twoside option is on:
%    \begin{macrocode}
   \@twosidetrue
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkSetDynamicEvenHead}
%Only the header frame for even pages has been defined. NB the
%document must have the twoside setting on.
%    \begin{macrocode}
\NewDocumentCommand \flowframtkSetDynamicEvenHead { m }
 {
   \__flowfram_get_dynamic_id:n { #1 }
   \int_set_eq:NN \g__flowfram_dynamic_even_header_int \l__flowfram_id_int
   \renewcommand \@dothehead { }
   \cs_set:Ne \@dodynamicthehead
    {
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_even_header_int }
       {
         \flowfram_dynamic_even_header:n
           { \g__flowfram_dynamic_even_header_int }
       }
    }
%    \end{macrocode}
%Ensure twoside option is on:
%    \begin{macrocode}
   \@twosidetrue
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkSetDynamicOddFoot}
%The same footer frame is used for both odd and even pages or it's a
%single-sided document.
%    \begin{macrocode}
\NewDocumentCommand \flowframtkSetDynamicOddFoot { m }
 {
   \__flowfram_get_dynamic_id:n { #1 }
   \int_set_eq:NN \g__flowfram_dynamic_footer_int \l__flowfram_id_int
   \renewcommand \@dothefoot { }
   \renewcommand \@dodynamicthefoot
    {
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_footer_int }
       {
          \flowfram_dynamic_footer:n
           { \g__flowfram_dynamic_footer_int }
       }
    }
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkSetDynamicOddEvenFoot}
%There are two dynamic footer frames, one for
%odd pages and one for even pages.
%    \begin{macrocode}
\NewDocumentCommand \flowframtkSetDynamicOddEvenFoot { m m }
 {
   \__flowfram_get_dynamic_id:n { #1 }
   \int_set_eq:NN \g__flowfram_dynamic_footer_int \l__flowfram_id_int
   \__flowfram_get_dynamic_id:n { #2 }
   \int_set_eq:NN \g__flowfram_dynamic_even_footer_int \l__flowfram_id_int
   \renewcommand \@dothefoot { }
   \renewcommand \@dodynamicthefoot
    {
%    \end{macrocode}
%odd foot
%    \begin{macrocode}
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_footer_int }
       {
          \flowfram_dynamic_odd_footer:n
           { \g__flowfram_dynamic_footer_int }
       }
%    \end{macrocode}
%even foot
%    \begin{macrocode}
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_even_footer_int }
       {
          \flowfram_dynamic_even_footer:n
           { \g__flowfram_dynamic_even_footer_int }
       }
    }
%    \end{macrocode}
%Ensure twoside option is on:
%    \begin{macrocode}
   \@twosidetrue
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkSetDynamicEvenFoot}
%Only the footer frame for even pages has been defined. NB the
%document must have the twoside setting on.
%    \begin{macrocode}
\NewDocumentCommand \flowframtkSetDynamicEvenFoot { m }
 {
   \__flowfram_get_dynamic_id:n { #1 }
   \int_set_eq:NN \g__flowfram_dynamic_even_footer_int \l__flowfram_id_int
   \renewcommand \@dothefoot { }
   \renewcommand \@dodynamicthefoot
    {
     \__flowfram_set_dynamic_contents:nn
       { \g__flowfram_dynamic_even_footer_int }
       {
          \flowfram_dynamic_even_footer:n
           { \g__flowfram_dynamic_even_footer_int }
       }
    }
%    \end{macrocode}
%Ensure twoside option is on:
%    \begin{macrocode}
   \@twosidetrue
 }
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowframtkMakeDFHeaderFooter}
%End part of \cs{makedfheaderfooter}:
%    \begin{macrocode}
\NewDocumentCommand \flowframtkMakeDFHeaderFooter { }
 {
  \tl_clear:N \g__flowfram_headercolor_tl
  \tl_clear:N \g__flowfram_footercolor_tl
  \__flowfram_adjust_page_styles:n
   {
      \let \ps@myheadings \ps@ffmyheadings
      \let \ps@headings \ps@ffheadings
      \let \ps@plain \ps@ffplain
      \let \ps@empty \ps@ffempty
   }
  \pagestyle { ffheadings }
  \cs_set:Nn \__flowfram_only_pre_makedfheaderfooter:nn
   {
     \msg_error:nnn { flowfram } { option-too-late } { ##1 }
       { \flowframtkMakeDFHeaderFooter }
   }
 }
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
\ExplSyntaxOff
%    \end{macrocode}
%\iffalse
%    \begin{macrocode}
%</flowframtkutils.sty>
%    \end{macrocode}
%\fi
%\iffalse
%    \begin{macrocode}
%<*flowfram-2014-09-30.sty>
%    \end{macrocode}
%\fi
% \section{Rollback v1.17 (flowfram-2014-09-30)}
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{flowfram}[2014/09/30 v1.17 (NLCT)]
\RequirePackage{ifthen}
\RequirePackage{xkeyval}
\RequirePackage{graphics}
\RequirePackage{afterpage}
\RequirePackage{xfor}
\RequirePackage{etoolbox}
\@ifundefined{@ldc@l@r}{\RequirePackage{color}}{}
\newcommand{\setffdraftcolor}{\color[gray]{0.8}}
\newcommand{\setffdrafttypeblockcolor}{\color[gray]{0.9}}
\newlength\fflabelsep
\fflabelsep=1pt
\newcommand*{\fflabelfont}{\small\sffamily}
\newif\ifshowtypeblock
\newif\ifshowmargins
\newif\ifshowframebbox
\newcommand*{\@ffdraft}{%
  \showtypeblocktrue
  \showmarginstrue
  \showframebboxtrue
}
\newcommand*{\@ffnodraft}{%
  \showtypeblockfalse
  \showmarginsfalse
  \showframebboxfalse
}
\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]}}%
  }%
}%
\newcommand*{\@s@tffcol}{}
\newcommand*{\@s@tfftextcol}{}
\newcommand*{\@ffbackground}[1]{#1}
\DeclareOptionX{draft}{\@ffdraft}
\DeclareOptionX{final}{\@ffnodraft}
\@ffnodraft
\define@choicekey{flowfram.sty}%
  {verbose}[\val\nr]%
  {true,false}[true]%
  {%
    \ifcase\nr\relax
      \renewcommand*{\flf@doifverbose}[1]{##1}%
      \renewcommand*{\flf@message}[1]{\PackageInfo{flowfram}{##1}}%
    \or
      \renewcommand*{\flf@doifverbose}[1]{}%
      \renewcommand*{\flf@message}[1]{}%
    \fi
  }
\newcommand*{\flf@message}[1]{%
  \flf@doifverbose
  {%
    \PackageInfo{flowfram}{##1}%
  }%
}
\newcommand*{\flf@doifverbose}[1]{}
\define@boolkey{flowfram.sty}[@ttb@]{rotate}[true]{}
\@ttb@rotatetrue
\DeclareOptionX{norotate}{\@ttb@rotatefalse}
\newcommand{\rotateframe}[2]{%
  \if@ttb@rotate
    \rotatebox{#1}{#2}%
  \else
    #2%
  \fi
}
\newif\if@ttb@num
\@ttb@numfalse
\newif\if@ttb@title
\@ttb@titletrue
\define@choicekey{flowfram.sty}%
  {thumbtabs}[\val\nr]%
  {title,number,both,none}[title]%
  {%
    \ifcase\nr\relax
       \@ttb@numfalse
       \@ttb@titletrue
    \or
       \@ttb@numtrue
       \@ttb@titlefalse
    \or
       \@ttb@numtrue
       \@ttb@titletrue
    \or
       \@ttb@numfalse
       \@ttb@titlefalse
    \fi
  }
\DeclareOptionX{ttbtitle}{\@ttb@titletrue}
\DeclareOptionX{ttbnotitle}{\@ttb@titlefalse}
\DeclareOptionX{ttbnum}{\@ttb@numtrue}
\DeclareOptionX{ttbnonum}{\@ttb@numfalse}
\define@choicekey{flowfram.sty}{pages}[\val\nr]%
  {relative,absolute}%
  {%
    \ifcase\nr\relax
      \renewcommand*{\@ff@pages@countreg}{\c@page}%
    \or
      \renewcommand*{\@ff@pages@countreg}{\c@absolutepage}%
    \fi
  }
\newcommand*{\@ff@pages@countreg}{\c@page}
\newcounter{absolutepage}
\define@choicekey{flowfram.sty}{color}[\val\nr]{true,false}[true]{%
  \ifcase\nr\relax
    \@ff@enablecolor
  \or
    \@ff@disablecolor
  \fi
}
\DeclareOptionX{nocolor}{%
  \@ff@disablecolor
}
\newcommand*{\@ff@enablecolor}{%
  \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}}%
      }%
    }%
}
\newcommand*{\@ff@disablecolor}{%
  \def\flowframetextcol{}%
  \def\flowframecol{}%
  \renewcommand{\@s@tffcol}{}\renewcommand{\@s@tfftextcol}{}%
  \renewcommand{\@ffbackground}[1]{##1}%
}
\newif\iflefttorightcolumns
\lefttorightcolumnstrue
\DeclareOptionX{LR}{\lefttorightcolumnstrue}
\DeclareOptionX{RL}{\lefttorightcolumnsfalse}
\ifx\normalcolor\relax
  \@ff@disablecolor
\else
  \@ff@enablecolor
\fi
\ProcessOptionsX
\ifx\normalcolor\relax
  \ifthenelse{\equal{\flowframetextcol}{}}%
  {}%
  {%
    \RequirePackage{color}%
  }
\fi
\@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
  }%
  \newcommand*{\ffprechapterhook}{}
  \let\@ff@OLD@ch@pter\chapter
  \renewcommand{\chapter}{%
    \ffprechapterhook
    \@ff@OLD@ch@pter
  }
}
\newcounter{maxflow}
\c@maxflow=0\relax
\newcounter{thisframe}
\c@thisframe=0\relax
\@ifpackageloaded{hyperref}
{%
  \def\theHthisframe{\thepage.\arabic{thisframe}}%
}%
{}
\newcommand*{\labelflowidn}[1]{%
  {%
    \def\@currentlabel{\thethisframe}%
    \label{#1}%
  }%
}
\newcounter{displayedframe}
\c@displayedframe=0
\@ifpackageloaded{hyperref}%
{%
  \def\theHdisplayedframe{\thepage.\arabic{displayedframe}}%
}%
{}
\newcommand*{\labelflow}[1]{%
  {%
    \def\@currentlabel{\thedisplayedframe}%
    \label{#1}%
  }%
}
\newcounter{maxstatic}
\c@maxstatic=0\relax
\newcounter{maxdynamic}
\c@maxdynamic=0\relax
\newcount\@colN
\newcount\@ff@tmpN
\newcount\ff@id
\newlength\@ff@offset
\newlength\@ff@tmp@x
\newlength\@ff@tmp@x@even
\newlength\@ff@tmp@y
\newlength\sdfparindent
\newlength\flowframesep
\flowframesep=\fboxsep
\newlength\flowframerule
\flowframerule=\fboxrule
\newcommand*{\flowframeshowlayout}{%
  \finishthispage
  {%
    \@ffdraft\mbox{}\finishthispage\clearpage
  }%
}
\newif\ifusedframebreak
\newcommand{\framebreak}[1][4]{%
  \global\usedframebreaktrue
  {%
    \parfillskip=0pt\pagebreak[#1]\parskip=0pt\par\noindent
  }%
}
\newcommand{\finishthispage}{%
  \ifvmode
    \@colN=\c@thisframe\relax
    \count@=\c@absolutepage\relax
    \ifdim \pagetotal<\topskip
      \hbox{}%
    \fi
    \newpage \write \m@ne {}\vbox {}\penalty -\@Mi
    \ifnum\count@=\c@absolutepage\relax
      \whiledo{\@colN<\c@maxflow \OR \@colN=\c@maxflow}%
      {%
        \@ff@chckifthispg{\@ff@pages@countreg}{\@colN}%
        \if@notthiscol
        \else
          \c@thisframe=\@colN\relax
          \hbox{}\newpage
        \fi
        \advance\@colN by 1\relax
      }%
    \fi
  \fi
}
\def\cleardoublepage{%
  \clearpage
  \if@twoside
    \ifodd\c@page
    \else
      \hbox{}%
      \clearpage
    \fi
  \fi
}
\preto\newpage{\global\usedframebreaktrue}
\@twocolumnfalse
\@mparswitchfalse
\newcommand{\globalreversemargin}{%
  \global\@mparbottom\z@
  \global\@reversemargintrue
}
\newcommand{\globalnormalmargin}{%
  \global\@mparbottom\z@\global
  \@reversemarginfalse
}
\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}%
  }%
 }%
}
\newcommand{\setmargin}{%
 \@getmarginpos
 {%
   \csname @ff@margin@\romannumeral\c@thisframe\endcsname
 }%
 \ifthenelse{\equal{\ff@margin}{left}}%
 {\globalreversemargin}%
 {\globalnormalmargin}%
}
\newcommand{\newflowframe}{\@n@wflowframe}
\@onlypreamble{\newflowframe}
\newcommand{\@n@wflowframe}{%
  \global\advance\c@maxflow by 1\relax
  \expandafter\global\expandafter
  \newif\csname ifcolumnframe\romannumeral\c@maxflow\endcsname
  \@ifstar\@snewflowframe\@newflowframe
}
\newcommand{\@snewflowframe}{%
  \expandafter\global\expandafter
  \let\csname ifcolumnframe\romannumeral\c@maxflow\endcsname\iftrue
  \@@newflowframe
}
\newcommand{\@newflowframe}{%
  \expandafter\global\expandafter
  \let\csname ifcolumnframe\romannumeral\c@maxflow\endcsname\iffalse
  \@@newflowframe
}
\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@xpages@\romannumeral\c@maxflow\endcsname{}%
  \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\relax
            \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]%
  }%
}
\def\@s@tflowframeid#1[#2]{%
  \edef\ff@label{#2}%
  \@ff@checkuniqueidl{#1}{\ff@label}%
  \expandafter
    \xdef\csname @col@id@\romannumeral#1\endcsname{\ff@label}%
}
\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
    }%
  }%
}
\newcommand*{\getflowlabel}[1]{%
  \csname @col@id@\romannumeral#1\endcsname
}
\newcommand*{\getflowid}[2]{%
  \@flowframeid{#2}%
  \edef#1{\number\ff@id}%
}
\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
      \@colN=\c@maxflow
    }%
    {}%
  }%
  \ifnum\ff@id=0\relax
    \PackageError{flowfram}{Can't find flow frame id '#1'}{}%
  \fi
}
\define@key{flowframe}{width}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'width' key}{}%
  }%
  {}%
  \def\ff@width{#1}%
}
\define@key{flowframe}{height}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'height' key}{}%
  }%
  {}%
  \def\ff@height{#1}%
}
\define@key{flowframe}{x}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'x' key}{}%
  }%
  {}%
  \def\ff@x{#1}%
}
\define@key{flowframe}{y}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'y' key}{}%
  }%
  {}%
  \def\ff@y{#1}%
}
\define@key{flowframe}{evenx}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'evenx' key}{}%
  }%
  {}%
  \def\ff@evenx{#1}%
}
\define@key{flowframe}{eveny}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'eveny' key}{}%
  }%
  {}%
  \def\ff@eveny{#1}%
}
\define@key{flowframe}{oddx}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'oddx' key}{}%
  }%
  {}%
  \def\ff@oddx{#1}%
}
\define@key{flowframe}{oddy}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'oddy' key}{}%
  }%
  {}%
  \def\ff@oddy{#1}%
}
\define@key{flowframe}{label}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'label' key}{}%
  }%
  {}%
  \def\ff@label{#1}%
}
\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}%
    }%
  }%
}
\define@key{flowframe}{bordercolor}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'bordercolor' key}{}%
  }%
  {}%
  \def\ff@col{#1}%
}
\define@key{flowframe}{textcolor}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'textcolor' key}{}%
  }%
  {}%
  \def\ff@txtcol{#1}%
}
\define@key{flowframe}{backcolor}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'backcolor' key}{}%
  }%
  {}%
  \def\ff@backcol{#1}%
}
\define@key{flowframe}{pages}%
{%
  \ifthenelse{\equal{#1}{}}%
  {%
    \PackageError{flowfram}{Missing value for 'pages' key}{}%
  }%
  {}%
  \def\ff@pages{#1}%
}
\define@key{flowframe}{excludepages}%
{%
  \def\ff@xpages{#1}%
}
\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%
    }%
  }%
  {}%
}
\define@key{flowframe}{angle}{\def\ff@angle{#1}%
}
\define@choicekey{flowframe}{margin}{left,right,inner,outer}%
{%
  \def\ff@margin{#1}%
}
\define@choicekey{flowframe}{clear}{true,false}[true]{%
  \def\ff@clear{#1}%
}
\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}%
  }%
}
\define@key{flowframe}{shape}%
{%
  \def\ff@shape{#1}%
}
\define@choicekey{flowframe}{valign}{c,t,b}%
{%
  \def\ff@valign{#1}%
}
\define@choicekey{flowframe}{hide}{true,false}[true]{%
  \def\ff@hide{#1}%
}
\define@choicekey{flowframe}{hidethis}{true,false}[true]{%
  \def\ff@hidethis{#1}%
}
\newcommand*{\setallflowframes}[1]{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxflow}%
  {%
    \advance\@colN by 1\relax
    \@@setflowframe{\@colN}{#1}%
  }%
}
\newcommand*{\setflowframe}{\@ifstar\@ssetflowframe\@setflowframe}
\newcommand{\@ssetflowframe}[2]{%
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \@@setflowframe{\ff@id}{#2}%
  }%
}
\newcommand*{\@setflowframe}[2]{%
  \ifthenelse{\equal{#1}{all}}%
  {%
    \setallflowframes{#2}%
  }%
  {%
    \ifthenelse{\equal{#1}{odd} \TE@or \equal{#1}{even}}%
    {%
      \ifthenelse{\equal{#1}{odd}}%
      {%
        \@colN=1\relax
      }%
      {%
        \@colN=2\relax
      }%
      \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
        }%
      }%
    }%
  }%
}
\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@hide{}\def\ff@hidethis{}%
  \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{}%
  \let\ff@xpages\undefined
  \let\ff@shape\undefined
  \setkeys{flowframe}{#2}%
  \ifdefempty{\ff@frame}{}%
  {%
    \setboolean{columnframe\romannumeral#1}{\ff@frame}%
  }%
  \ifdefempty{\ff@width}{}%
  {%
    \expandafter
      \setlength\csname colwidth\romannumeral#1\endcsname
      {\ff@width}%
  }%
  \ifdefempty{\ff@height}{}%
  {%
    \expandafter
      \setlength\csname colheight\romannumeral#1\endcsname
      {\ff@height}%
  }%
  \ifdefempty{\ff@x}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posx\endcsname
      {\ff@x}%
    \expandafter
      \setlength\csname col@\romannumeral#1@evenx\endcsname
      {\ff@x}%
  }
  \ifdefempty{\ff@y}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posy\endcsname
      {\ff@y}%
    \expandafter
      \setlength\csname col@\romannumeral#1@eveny\endcsname
      {\ff@y}%
  }%
  \ifdefempty{\ff@evenx}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@evenx\endcsname
      {\ff@evenx}%
  }%
  \ifdefempty{\ff@eveny}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@eveny\endcsname
      {\ff@eveny}%
  }%
  \ifdefempty{\ff@oddx}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posx\endcsname
      {\ff@oddx}%
  }%
  \ifdefempty{\ff@oddy}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posy\endcsname
      {\ff@oddy}%
  }%
  \ifdefempty{\ff@label}{}%
  {%
    \@s@tflowframeid{#1}[\ff@label]%
  }%
  \ifdefempty{\ff@frametype}{}%
  {%
    \expandafter
      \edef\csname @ff@frametype@\romannumeral#1\endcsname{%
        \ff@frametype}%
  }%
  \ifdefempty{\ff@col}{}%
  {%
    \expandafter\@setframecol\ff@col\end{#1}{col}{ff}%
  }%
  \ifdefempty{\ff@txtcol}{}%
  {%
    \expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{ff}%
  }%
  \ifdefempty{\ff@backcol}{}%
  {%
    \expandafter\@setframecol\ff@backcol\end{#1}{backcol}{ff}%
  }%
  \ifdefempty{\ff@margin}{}%
  {%
    \expandafter
      \xdef\csname @ff@margin@\romannumeral#1\endcsname{%
        \ff@margin}%
  }%
  \ifdefempty{\ff@pages}{}%
  {%
    \flowsetpagelist{#1}{\ff@pages}%
  }%
  \ifundef{\ff@xpages}{}%
  {%
    \flowsetexclusion{#1}{\ff@xpages}%
  }%
  \ifdefempty{\ff@offset}{}%
  {%
    \expandafter
      \xdef\csname @ff@offset@\romannumeral#1\endcsname{%
        \ff@offset}%
  }%
  \ifdefempty{\ff@angle}{}%
  {%
    \expandafter
      \xdef\csname @ff@angle@\romannumeral#1\endcsname{%
        \ff@angle}%
  }%
  \ifdefempty{\ff@clear}{}%
  {%
    \PackageError{flowfram}%
      {Key 'clear' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@style}{}%
  {%
    \PackageError{flowfram}%
      {Key 'style' not available for flow frames}{}%
  }%
  \ifundef{\ff@shape}{}%
  {%
    \PackageError{flowfram}%
    {Key 'shape' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@valign}{}%
  {%
    \PackageError{flowfram}%
    {Key 'valign' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@hide}{}%
  {%
    \PackageError{flowfram}%
      {Key 'hide' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@hidethis}{}%
  {%
    \PackageError{flowfram}%
      {Key 'hidethis' not available for flow frames}{}%
  }%
}
\newcommand*{\flowsetpagelist}[2]{%
  \expandafter
    \xdef\csname @ff@pages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting page range for flow frame
    \number#1\space\space to "#2"}%
}
\newcommand*{\flowsetexclusion}[2]{%
  \expandafter
    \xdef\csname @ff@xpages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting exclusion for flow frame
    \number#1\space\space to "#2"}%
}
\newcommand*{\flowaddexclusion}[2]{%
  \ifcsempty{@ff@xpages@\romannumeral#1}
  {%
    \expandafter
      \xdef\csname @ff@xpages@\romannumeral#1\endcsname{#2}%
  }%
  {%
    \expandafter
      \xdef\csname @ff@xpages@\romannumeral#1\endcsname{%
       \csname @ff@xpages@\romannumeral#1\endcsname,#2}%
  }%
  \flf@message{Setting exclusion for flow frame
    \number#1\space\space to
    "\csname @ff@xpages@\romannumeral#1\endcsname"}%
}
\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}%
}
\newcommand*{\ffswapoddeven}{%
  \@ifstar\@sflowframeswapcoords\@flowframeswapcoords
}
\newcommand*{\@sflowframeswapcoords}[1]{%
  \@for\@ff@id:=#1\do
  {%
    \@flowframeid{\@ff@id}%
    \@@flowframeswapcoords{\ff@id}%
  }%
}
\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{100000}%
        \@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
        }%
      }%
    }%
  }%
}
\newcommand*{\flowframex}[1]{%
  \csname col@\romannumeral#1@posx\endcsname
}
\newcommand*{\flowframey}[1]{%
  \csname col@\romannumeral#1@posy\endcsname
}
\newcommand*{\flowframeevenx}[1]{%
  \csname col@\romannumeral#1@evenx\endcsname
}
\newcommand*{\flowframeeveny}[1]{%
  \csname col@\romannumeral#1@eveny\endcsname
}
\newcommand{\flowframewidth}[1]{%
  \csname colwidth\romannumeral#1\endcsname
}
\newcommand*{\flowframeheight}[1]{%
  \csname colheight\romannumeral#1\endcsname
}
\def\@setframecol{\@ifnextchar[\@@setframecol\@@setfr@mecol}
\def\@@setframecol[#1]#2\end#3#4#5{%
  \expandafter\edef\csname @#5@#4@\romannumeral#3\endcsname{%
    [#1]{#2}}%
}
\def\@@setfr@mecol#1\end#2#3#4{%
  \expandafter\edef\csname @#4@#3@\romannumeral#2\endcsname{{#1}}%
}
\newcommand*{\newstaticframe}{\@n@wstaticframe}
\newcommand*{\@n@wstaticframe}{%
  \global\advance\c@maxstatic by 1\relax
  \newboolean{staticframe\romannumeral\c@maxstatic}%
  \@ifstar\@snewstaticframe\@newstaticframe
}
\newcommand{\@snewstaticframe}{%
  \setboolean{staticframe\romannumeral\c@maxstatic}{true}%
  \@@newstaticframe
}
\newcommand{\@newstaticframe}{%
  \setboolean{staticframe\romannumeral\c@maxstatic}{false}%
  \@@newstaticframe
}
\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@xpages@\romannumeral\c@maxflow\endcsname{}%
  \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}
  \newboolean{@sf@hide@\romannumeral\c@maxstatic}%
  \setboolean{@sf@hide@\romannumeral\c@maxstatic}{false}%
  \newboolean{@sf@hidethis@\romannumeral\c@maxstatic}%
  \setboolean{@sf@hidethis@\romannumeral\c@maxstatic}{false}%
  \@ifnextchar[{\@s@tstaticframeid{\c@maxstatic}}%
  {\@s@tstaticframeid{\c@maxstatic}[\number\c@maxstatic]}%
}
\def\@s@tstaticframeid#1[#2]{%
  \edef\ff@label{#2}%
  \@sf@checkuniqueidl{#1}{\ff@label}%
  \expandafter
    \xdef\csname @sf@id@\romannumeral#1\endcsname{\ff@label}%
}
\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
  }%
}
\newcommand*{\getstaticlabel}[1]{%
  \csname @sf@id@\romannumeral#1\endcsname
}
\newcommand*{\getstaticid}[2]{%
  \@staticframeid{#2}\edef#1{\number\ff@id}%
}
\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
      \@colN=\c@maxstatic
    }%
    {}%
  }%
  \ifnum\ff@id=0\relax
    \PackageError{flowfram}%
    {Can't find static frame id '#1'}{}%
  \fi
}
\newcommand*{\staticframex}[1]{%
  \csname @sf@\romannumeral#1@posx\endcsname
}
\newcommand*{\staticframey}[1]{%
  \csname @sf@\romannumeral#1@posy\endcsname
}
\newcommand*{\staticframeevenx}[1]{%
  \csname @sf@\romannumeral#1@evenx\endcsname
}
\newcommand*{\staticframeeveny}[1]{%
  \csname @sf@\romannumeral#1@eveny\endcsname
}
\newcommand*{\setallstaticframes}[1]{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxstatic}%
  {%
    \advance\@colN by 1\relax
    \@@setstaticframe{\@colN}{#1}%
  }%
}
\newcommand*{\setstaticframe}{%
  \@ifstar\@ssetstaticframe\@setstaticframe
}
\newcommand*{\@ssetstaticframe}[2]{%
  \@for\@ff@id:=#1\do
  {%
    \@staticframeid{\@ff@id}%
    \@@setstaticframe{\ff@id}{#2}%
  }%
}
\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
        }%
      }%
    }%
  }%
}
\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@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@hide{}\def\ff@hidethis{}%
  \let\ff@shape\undefined
  \let\ff@xpages\undefined
  \setkeys{flowframe}{#2}%
  \ifdefempty{\ff@frame}{}%
  {%
    \setboolean{staticframe\romannumeral#1}{\ff@frame}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\ff@evenx}{}%
  {%
    \expandafter\global\expandafter
      \setlength\csname @sf@\romannumeral#1@evenx\endcsname
        {\ff@evenx}%
  }%
  \ifdefempty{\ff@eveny}{}%
  {%
    \expandafter\global\expandafter
      \setlength\csname @sf@\romannumeral#1@eveny\endcsname
      {\ff@eveny}%
  }%
  \ifdefempty{\ff@oddx}{}%
  {%
    \expandafter\global\expandafter
      \setlength\csname @sf@\romannumeral#1@posx\endcsname
      {\ff@oddx}%
  }%
  \ifdefempty{\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}}%
  \ifdefempty{\ff@frametype}{}%
  {%
    \expandafter
      \xdef\csname @sf@frametype@\romannumeral#1\endcsname{%
        \ff@frametype}%
  }%
  \ifdefempty{\ff@label}{}%
  {%
    \@s@tstaticframeid{#1}[\ff@label]%
  }
  \ifdefempty{\ff@col}{}%
  {%
    \expandafter\@setframecol\ff@col\end{#1}{col}{sf}%
  }%
  \ifdefempty{\ff@txtcol}{}%
  {%
    \expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{sf}%
  }%
  \ifdefempty{\ff@backcol}{}%
  {%
    \expandafter\@setframecol\ff@backcol\end{#1}{backcol}{sf}%
  }%
  \ifdefempty{\ff@offset}{}%
  {%
    \expandafter
      \xdef\csname @sf@offset@\romannumeral#1\endcsname{\ff@offset}%
  }%
  \ifdefempty{\ff@angle}{}%
  {%
    \expandafter
      \xdef\csname @sf@angle@\romannumeral#1\endcsname{\ff@angle}%
  }%
  \ifundef{\ff@shape}{}%
  {%
    \expandafter\global\expandafter
      \let\csname @sf@shape@\romannumeral#1\endcsname\ff@shape
  }%
  \ifdefempty{\ff@pages}{}%
  {%
     \staticsetpagelist{#1}{\ff@pages}%
  }%
  \ifundef{\ff@xpages}{}%
  {%
     \staticsetexclusion{#1}{\ff@xpages}%
  }%
  \ifdefempty{\ff@hide}{}%
  {%
    \setboolean{@sf@hide@\romannumeral#1}{\ff@hide}%
  }%
  \ifdefempty{\ff@hidethis}{}%
  {%
    \global\csletcs{if@sf@hidethis@\romannumeral#1}{if\ff@hidethis}%
  }%
  \ifdefempty{\ff@clear}{}%
  {%
    \setboolean{@sf@clear@\romannumeral#1}{\ff@clear}%
  }%
  \ifdefempty{\ff@margin}{}%
  {%
    \PackageError{flowfram}%
    {Key 'margin' not available for static frames}%
    {Static frames don't have marginal notes}%
  }%
  \ifdefempty{\ff@style}{}%
  {%
    \PackageError{flowfram}%
    {Key 'style' not available for static frames}{}%
  }%
}
 %\newcommand*{\simpar}{\hfil\vadjust{\vskip\parskip}\break\indent}
\newcommand*{\simpar}{\hfill\\\indent\mbox{}}
\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
}
\def\@ff@parshape{\parshape=0}
\newcommand*{\@ff@sectionhead}[1]{%
  \def\ff@sechead{#1}%
  \ffpshpar
  \@ifstar{\@s@ff@heading}{\@dblarg\@ff@heading}%
}
\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
}
\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
}
\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}}%
}
\def\@ff@getshape#1#2\relax{%
  \ifdefequal{#1}{\parshape}%
  {%
    \def\ff@shape{1}%
  }%
  {%
    \ifdefequal{#1}{\shapepar}%
    {%
      \def\ff@shape{2}%
    }%
    {%
       \ifdefequal{#1}{\Shapepar}%
       {%
         \def\ff@shape{2}%
       }%
       {%
         \ifx#1\relax
           \def\ff@shape{0}%
         \else
           \PackageError{flowfram}{Unknown shape \string#1}{}%
           \def\ff@shape{2}%
         \fi
      }%
    }%
  }%
}
\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}{}%
  }%
}
\newbox\staticframe
\newenvironment{staticcontents}[1]{%
  \let\continueonframe=\@staticcontinueonframe
  \@beginstaticcontents{#1}%
}%
{%
  \@endstaticcontents
  \ignorespaces
}
\newenvironment{staticcontents*}[1]{%
  \@staticframeid{#1}%
  \let\continueonframe=\@staticscontinueonframe
  \@beginstaticcontents{\ff@id}%
}%
{%
  \@endstaticcontents
  \ignorespaces
}
\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
    \edef\@sf@mpg{%
      \noexpand
      \begin{minipage}\csname @sf@dim@\romannumeral#1\endcsname
        \noexpand\begingroup
        \noexpand\let\noexpand\FLForgpar=\noexpand\par
    }%
  \or
    \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
    \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
}
\newcommand*{\@endstaticcontents}{%
  \ifnum\ff@shape=2\relax
    \par
  \else
    \FLForgpar
  \fi
  \endgroup
  \end{minipage}%
  \end{lrbox}%
  \expandafter\global\expandafter
    \sbox\@sf@thisframe{\usebox\staticframe}%
}
\newcommand{\setstaticcontents}{%
  \@ifstar\@sstaticconts\@staticconts
}
\newcommand{\@sstaticconts}[2]{%
  \begin{staticcontents*}{#1}%
    #2%
  \end{staticcontents*}%
}
\newcommand{\@staticconts}[2]{%
  \begin{staticcontents}{#1}%
  #2%
  \end{staticcontents}%
}
\newcommand*{\staticsetpagelist}[2]{%
  \expandafter
    \xdef\csname @sf@pages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting page range for static frame
    \number#1\space\space to "#2"}%
}
\newcommand*{\staticsetexclusion}[2]{%
  \expandafter
    \xdef\csname @sf@xpages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting exclusion for static frame
    \number#1\space\space to "#2"}%
}
\newcommand*{\staticaddexclusion}[2]{%
  \ifcsempty{@sf@xpages@\romannumeral#1}
  {%
    \expandafter
      \xdef\csname @sf@xpages@\romannumeral#1\endcsname{#2}%
  }%
  {%
    \expandafter
      \xdef\csname @sf@xpages@\romannumeral#1\endcsname{%
       \csname @sf@xpages@\romannumeral#1\endcsname,#2}%
  }%
  \flf@message{Setting exclusion for static frame
    \number#1\space\space to
    "\csname @sf@xpages@\romannumeral#1\endcsname"}%
}
\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}%
}
\newcommand*{\sfswapoddeven}{%
  \@ifstar\@sstaticframeswapcoords\@staticframeswapcoords
}
\newcommand*{\@sstaticframeswapcoords}[1]{%
  \@for\@ff@id:=#1\do
  {%
    \@staticframeid{\@ff@id}%
    \@@staticframeswapcoords{\ff@id}%
  }%
}
\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{100000}%
        \@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
        }%
      }%
    }%
  }%
}
\newcommand*{\newdynamicframe}{%
  \@n@wdynamicframe
}
\newcommand*{\@n@wdynamicframe}{%
  \global\advance\c@maxdynamic by 1\relax
  \newboolean{dynamicframe\romannumeral\c@maxdynamic}
  \@ifstar\@snewdynamicframe\@newdynamicframe
}
\newcommand*{\@snewdynamicframe}{%
  \setboolean{dynamicframe\romannumeral\c@maxdynamic}{true}%
  \@@newdynamicframe
}
\newcommand*{\@newdynamicframe}{%
  \setboolean{dynamicframe\romannumeral\c@maxdynamic}{false}%
  \@@newdynamicframe
}
\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@xpages@\romannumeral\c@maxflow\endcsname{}%
  \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}%
  \newboolean{@df@hide@\romannumeral\c@maxdynamic}%
  \setboolean{@df@hide@\romannumeral\c@maxdynamic}{false}%
  \newboolean{@df@hidethis@\romannumeral\c@maxdynamic}%
  \setboolean{@df@hidethis@\romannumeral\c@maxdynamic}{false}%
  \@ifnextchar[{\@s@tdynamicframeid{\c@maxdynamic}}%
    {\@s@tdynamicframeid{\c@maxdynamic}[\number\c@maxdynamic]}%
}
\def\@s@tdynamicframeid#1[#2]{%
  \edef\ff@label{#2}%
  \@df@checkuniqueidl{#1}{\ff@label}%
  \expandafter
    \xdef\csname @df@id@\romannumeral#1\endcsname{\ff@label}%
}
\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
  }%
}
\newcommand*{\getdynamiclabel}[1]{%
  \csname @df@id@\romannumeral#1\endcsname
}
\newcommand*{\getdynamicid}[2]{%
  \@dynamicframeid{#2}\edef#1{\number\ff@id}%
}
\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
      \@colN=\c@maxdynamic
    }%
    {}%
  }%
  \ifnum\ff@id=0\relax
    \PackageError{flowfram}%
    {Can't find dynamic frame id '#1'}{}%
  \fi
}
\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}%
  }%
}
\newcommand*{\dynamicframex}[1]{%
  \csname @df@\romannumeral#1@posx\endcsname
}
\newcommand*{\dynamicframey}[1]{%
  \csname @df@\romannumeral#1@posy\endcsname
}
\newcommand*{\dynamicframeevenx}[1]{%
  \csname @df@\romannumeral#1@evenx\endcsname
}
\newcommand*{\dynamicframeeveny}[1]{%
  \csname @df@\romannumeral#1@eveny\endcsname
}
\newcommand*{\setalldynamicframes}[1]{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxdynamic}%
  {%
    \advance\@colN by 1\relax
    \@@setdynamicframe{\@colN}{#1}%
  }%
}
\newcommand*{\setdynamicframe}{%
  \@ifstar\@ssetdynamicframe\@setdynamicframe
}
\newcommand*{\@ssetdynamicframe}[2]{%
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \@@setdynamicframe{\ff@id}{#2}%
  }%
}
\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
        }%
      }%
    }%
  }%
}
\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@hide{}\def\ff@hidethis{}%
  \let\ff@shape\undefined
  \let\ff@xpages\undefined
  \setkeys{flowframe}{#2}%
  \ifdefempty{\ff@frame}%
  {}%
  {%
    \setboolean{dynamicframe\romannumeral#1}{\ff@frame}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\ff@evenx}%
  {}%
  {%
    \expandafter\global\expandafter\setlength
      \csname @df@\romannumeral#1@evenx\endcsname{\ff@evenx}%
  }%
  \ifdefempty{\ff@eveny}%
  {}%
  {%
    \expandafter\global\expandafter\setlength
      \csname @df@\romannumeral#1@eveny\endcsname{\ff@eveny}%
  }%
  \ifdefempty{\ff@oddx}%
  {}%
  {%
    \expandafter\global\expandafter\setlength
      \csname @df@\romannumeral#1@posx\endcsname{\ff@oddx}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\ff@label}%
  {}%
  {%
    \@s@tdynamicframeid{#1}[\ff@label]%
  }%
  \ifdefempty{\ff@frametype}%
  {}%
  {%
    \expandafter
      \xdef\csname @df@frametype@\romannumeral#1\endcsname{%
        \ff@frametype
      }%
  }%
  \ifdefempty{\ff@col}%
  {}%
  {%
    \expandafter\@setframecol\ff@col\end{#1}{col}{df}%
  }%
  \ifdefempty{\ff@txtcol}%
  {}%
  {%
    \expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{df}%
  }%
  \ifdefempty{\ff@backcol}%
  {}%
  {%
    \expandafter\@setframecol\ff@backcol\end{#1}{backcol}{df}%
  }%
  \ifdefempty{\ff@offset}%
  {}%
  {%
    \expandafter
      \xdef\csname @df@offset@\romannumeral#1\endcsname{\ff@offset}%
  }%
  \ifdefempty{\ff@angle}%
  {}%
  {%
    \expandafter
      \xdef\csname @df@angle@\romannumeral#1\endcsname{\ff@angle}%
  }%
  \ifundef{\ff@shape}{}%
  {%
    \expandafter\global\expandafter
      \let\csname @df@shape@\romannumeral#1\endcsname\ff@shape
  }%
  \ifdefempty{\ff@pages}%
  {}%
  {%
    \dynamicsetpagelist{#1}{\ff@pages}%
  }%
  \ifundef{\ff@xpages}{}%
  {%
    \dynamicsetexclusion{#1}{\ff@xpages}%
  }%
  \ifdefempty{\ff@style}%
  {}%
  {%
    \ifcsundef{\ff@style}%
    {%
      \PackageError{flowfram}%
      {Unknown style '\ff@style'}%
      {%
        The command \expandafter\@gobble\string\\\ff@style
        \space has not been defined%
      }%
    }%
    {%
      \expandafter
        \xdef\csname @df@style@\romannumeral#1\endcsname{\ff@style}%
    }%
  }%
  \ifdefempty{\ff@clear}%
  {}%
  {%
    \setboolean{@df@clear@\romannumeral#1}{\ff@clear}%
  }%
  \ifdefempty{\ff@margin}%
  {}%
  {%
    \PackageError{flowfram}%
    {%
      Key 'margin' not available for dynamic frames%
    }%
    {dynamic frames don't have marginal notes}%
  }%
  \ifdefempty{\ff@hide}{}%
  {%
    \setboolean{@df@hide@\romannumeral#1}{\ff@hide}%
  }%
  \ifdefempty{\ff@hidethis}{}%
  {%
    \global\csletcs{if@df@hidethis@\romannumeral#1}{if\ff@hidethis}%
  }%
}
\newcommand*{\dynamicsetpagelist}[2]{%
  \expandafter
    \xdef\csname @df@pages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting page range for dynamic frame
    \number#1\space\space to "#2"}%
}
\newcommand*{\dynamicsetexclusion}[2]{%
  \expandafter
    \xdef\csname @df@xpages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting exclusion for dynamic frame
    \number#1\space\space to "#2"}%
}
\newcommand*{\dynamicaddexclusion}[2]{%
  \ifcsempty{@df@xpages@\romannumeral#1}
  {%
    \expandafter
      \xdef\csname @df@xpages@\romannumeral#1\endcsname{#2}%
  }%
  {%
    \expandafter
      \xdef\csname @df@xpages@\romannumeral#1\endcsname{%
       \csname @df@xpages@\romannumeral#1\endcsname,#2}%
  }%
  \flf@message{Setting exclusion for dynamic frame
    \number#1\space\space to
    "\csname @df@xpages@\romannumeral#1\endcsname"}%
}
\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}%
}
\newcommand*{\dfswapoddeven}{%
\@ifstar\@sdynamicframeswapcoords\@dynamicframeswapcoords}
\newcommand*{\@sdynamicframeswapcoords}[1]{%
  \@for\@ff@id:=#1\do{%
  \@dynamicframeid{\@ff@id}%
  \@@dynamicframeswapcoords{\ff@id}}%
}
\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
        }%
      }%
    }%
  }%
}
\newenvironment{dynamiccontents}[1]{%
  \def\@flf@{dynamiccontents}%
  \xdynamiccontents{#1}}{%
  \endxdynamiccontents
}
\newtoks\@dynamictok
\def\xdynamiccontents#1{%
  \def\@flf@idn{#1}%
  \@dynamictok{}\@flf@get@body
}
\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
}
\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
}
\long\def\@lempty{}
\def\flf@getcontargs{%
  \@ifnextchar[{\@flf@getcontargs}{\@flf@getcontargs[]}%
}
\long\def\@flf@getcontargs[#1]#2#3\continueonframe#4#5#6{%
  \def#4{#1}\def#5{#2}\def#6{#3}%
}
\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
}
\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@}%
}
\newenvironment{dynamiccontents*}[1]{%
  \def\@flf@{dynamiccontents*}%
  \@dynamicframeid{#1}%
  \xdynamiccontents{\ff@id}}{%
  \enddynamiccontents
}
\newcommand{\setdynamiccontents}{%
  \@ifstar\@ssetdynamiccontents\@setdynamiccontents
}
\newcommand{\@ssetdynamiccontents}[2]{%
  \@dynamicframeid{#1}\@setdynamiccontents{\ff@id}{#2}%
}
\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
}
\newcommand{\appenddynamiccontents}{%
  \@ifstar\@sappenddynamic\@appenddynamic
}
\newcommand{\@sappenddynamic}[2]{%
  \@dynamicframeid{#1}\@appenddynamic{\ff@id}{#2}%
}
\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
}
\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}%
}
\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 (or their starred versions)%
  }%
}
\newcommand*{\@staticscontinueonframe}[2][]{%
  \ffcontinuedtextlayout{#1}%
  \end{staticcontents*}%
  \begin{staticcontents*}{#2}\par\noindent\ignorespaces
}
\newcommand*{\@staticcontinueonframe}[2][]{%
  \ffcontinuedtextlayout{#1}%
  \end{staticcontents}%
  \begin{staticcontents}{#2}\par\noindent\ignorespaces
}
\newcommand{\ffcontinuedtextlayout}[1]{%
  \parfillskip=0pt\par\hfill
  \ffcontinuedtextfont{#1}%
}
\newcommand*{\ffcontinuedtextfont}[1]{\emph{\small #1}}
\newcommand*{\computeleftedgeodd}[1]{%
  \setlength{#1}{-1in}%
  \addtolength{#1}{-\hoffset}%
  \addtolength{#1}{-\oddsidemargin}%
}
\newcommand*{\computeleftedgeeven}[1]{%
  \setlength{#1}{-1in}%
  \addtolength{#1}{-\hoffset}%
  \addtolength{#1}{-\evensidemargin}%
}
\newcommand*{\computetopedge}[1]{%
  \setlength{#1}{\textheight}%
  \addtolength{#1}{\headheight}%
  \addtolength{#1}{\headsep}%
  \addtolength{#1}{1in}%
  \addtolength{#1}{\voffset}%
  \addtolength{#1}{\topmargin}%
}
\newcommand*{\computebottomedge}[1]{%
  \computetopedge{#1}%
  \addtolength{#1}{-\paperheight}%
}
\newcommand*{\computerightedgeodd}[1]{%
  \computeleftedgeodd{#1}%
  \addtolength{#1}{\paperwidth}%
}
\newcommand*{\computerightedgeeven}[1]{%
  \computeleftedgeeven{#1}%
  \addtolength{#1}{\paperwidth}%
}
\newlength\ffareawidth
\newlength\ffareaheight
\newlength\ffareax
\newlength\ffareay
\newlength\ffareaevenx
\newlength\ffareaeveny
\newcommand*{\computeflowframearea}{%
  \@ifstar\@scomputeffarea\@computeffarea
}
\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}%
    \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}%
}
\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}%
}
\newcommand*{\@ff@swaplen}[2]{%
  \setlength{\@ff@tmp@x}{#1}%
  \setlength{#1}{#2}%
  \setlength{#2}{\@ff@tmp@x}%
}
\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
}
\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
}
\newcommand*{\getstaticbounds}{%
  \@ifstar\@sgetstaticbounds\@getstaticbounds
}
\newcommand*{\@sgetstaticbounds}[1]{%
  \@staticframeid{#1}\@getstaticbounds{\ff@id}%
}
\newcommand*{\@getstaticbounds}[1]{\@ff@getdim{2}{#1}}
\newcommand*{\getstaticevenbounds}{%
  \@ifstar\@sgetstaticevenbounds\@getstaticevenbounds
}
\newcommand*{\@sgetstaticevenbounds}[1]{%
  \@staticframeid{#1}\@getstaticevenbounds{\ff@id}%
}
\newcommand*{\@getstaticevenbounds}[1]{\@ff@getevendim{2}{#1}}
\newcommand*{\getflowbounds}{%
  \@ifstar\@sgetflowbounds\@getflowbounds
}
\newcommand*{\@sgetflowbounds}[1]{%
  \@flowframeid{#1}\@getflowbounds{\ff@id}%
}
\newcommand*{\@getflowbounds}[1]{\@ff@getdim{1}{#1}}
\newcommand*{\getflowevenbounds}{%
  \@ifstar\@sgetflowevenbounds\@getflowevenbounds
}
\newcommand*{\@sgetflowevenbounds}[1]{%
  \@flowframeid{#1}\@getflowevenbounds{\ff@id}%
}
\newcommand*{\@getflowevenbounds}[1]{\@ff@getevendim{1}{#1}}
\newcommand*{\getdynamicbounds}{%
  \@ifstar\@sgetdynamicbounds\@getdynamicbounds
}
\newcommand*{\@sgetdynamicbounds}[1]{%
  \@dynamicframeid{#1}\@getdynamicbounds{\ff@id}%
}
\newcommand*{\@getdynamicbounds}[1]{\@ff@getdim{3}{#1}}
\newcommand*{\getdynamicevenbounds}{%
  \@ifstar\@sgetdynamicevenbounds\@getdynamicevenbounds
}
\newcommand*{\@sgetdynamicevenbounds}[1]{%
  \@dynamicframeid{#1}\@getdynamicevenbounds{\ff@id}%
}
\newcommand*{\@getdynamicevenbounds}[1]{\@ff@getevendim{3}{#1}}
\newif\ifFLFabove
\newif\ifFLFbelow
\newif\ifFLFleft
\newif\ifFLFright
\newcommand*{\checkifframeabove}{%
  \@ifstar\@scheckifframeabove\@checkifframeabove
}
\newcommand*{\@scheckifframeabove}[4]{%
  \ifodd\c@page
    \@soddcheckifframeabove{#1}{#2}{#3}{#4}%
  \else
    \@sevencheckifframeabove{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\@checkifframeabove}[4]{%
  \ifodd\c@page
    \@oddcheckifframeabove{#1}{#2}{#3}{#4}%
  \else
    \@evencheckifframeabove{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\oddcheckifframeabove}{%
  \@ifstar\@soddcheckifframeabove\@oddcheckifframeabove
}
\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
}
\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
}
\newcommand*{\checkifframebelow}{%
  \@ifstar\@scheckifframebelow\@checkifframebelow
}
\newcommand*{\@scheckifframebelow}[4]{%
  \ifodd\c@page
    \@soddcheckifframebelow{#1}{#2}{#3}{#4}%
  \else
    \@sevencheckifframebelow{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\@checkifframebelow}[4]{%
  \ifodd\c@page
    \@oddcheckifframebelow{#1}{#2}{#3}{#4}%
  \else
    \@evencheckifframebelow{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\oddcheckifframebelow}{%
  \@ifstar\@soddcheckifframebelow\@oddcheckifframebelow
}
\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
}
\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
}
\newcommand*{\checkifframeleft}{%
  \@ifstar\@scheckifframeleft\@checkifframeleft
}
\newcommand*{\@scheckifframeleft}[4]{%
  \ifodd\c@page
    \@soddcheckifframeleft{#1}{#2}{#3}{#4}%
  \else
    \@sevencheckifframeleft{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\@checkifframeleft}[4]{%
  \ifodd\c@page
    \@oddcheckifframeleft{#1}{#2}{#3}{#4}%
  \else
    \@evencheckifframeleft{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\oddcheckifframeleft}{%
  \@ifstar\@soddcheckifframeleft\@oddcheckifframeleft
}
\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
}
\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
}
\newcommand*{\checkifframeright}{%
  \@ifstar\@scheckifframeright\@checkifframeright
}
\newcommand*{\@scheckifframeright}[4]{%
  \ifodd\c@page
    \@soddcheckifframeright{#1}{#2}{#3}{#4}%
  \else
    \@sevencheckifframeright{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\@checkifframeright}[4]{%
  \ifodd\c@page
    \@oddcheckifframeright{#1}{#2}{#3}{#4}%
  \else
    \@evencheckifframeright{#1}{#2}{#3}{#4}%
  \fi
}
\newcommand*{\oddcheckifframeright}{%
  \@ifstar\@soddcheckifframeright\@oddcheckifframeright
}
\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
}
\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
}
\newcommand*{\evencheckifframeabove}{%
  \@ifstar\@sevencheckifframeabove\@evencheckifframeabove
}
\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
}
\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
}
\newcommand*{\evencheckifframebelow}{%
  \@ifstar\@sevencheckifframebelow\@evencheckifframebelow
}
\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
}
\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
}
\newcommand*{\evencheckifframeleft}{%
  \@ifstar\@sevencheckifframeleft\@evencheckifframeleft
}
\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
}
\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
}
\newcommand*{\evencheckifframeright}{%
  \@ifstar\@sevencheckifframeright\@evencheckifframeright
}
\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
}
\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
}
\newcommand*{\FFaboveleft}{above left}
\newcommand*{\FFaboveright}{above right}
\newcommand*{\FFbelowleft}{below left}
\newcommand*{\FFbelowright}{below right}
\newcommand*{\FFleft}{on the left}
\newcommand*{\FFright}{on the right}
\newcommand*{\FFabove}{above}
\newcommand*{\FFbelow}{below}
\newcommand*{\FFoverlap}{overlap}
\DeclareRobustCommand*{\relativeframelocation}{%
  \@ifstar\@srelativeframelocation\@relativeframelocation
}
\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
}
\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
}
\DeclareRobustCommand*{\reldynamicloc}{%
  \@ifstar\@sreldynamicloc\@reldynamicloc
}
\newcommand*{\@sreldynamicloc}[2]{%
  \@srelativeframelocation{dynamic}{#1}{dynamic}{#2}%
}
\newcommand*{\@reldynamicloc}[2]{%
  \@relativeframelocation{dynamic}{#1}{dynamic}{#2}%
}
\DeclareRobustCommand*{\relstaticloc}{%
  \@ifstar\@srelstaticloc\@relstaticloc
}
\newcommand*{\@srelstaticloc}[2]{%
  \@srelativeframelocation{static}{#1}{static}{#2}%
}
\newcommand*{\@relstaticloc}[2]{%
  \@relativeframelocation{static}{#1}{static}{#2}%
}
\DeclareRobustCommand*{\relflowloc}{%
  \@ifstar\@srelflowloc\@relflowloc
}
\newcommand*{\@srelflowloc}[2]{%
  \@srelativeframelocation{flow}{#1}{flow}{#2}%
}
\newcommand*{\@relflowloc}[2]{%
  \@relativeframelocation{flow}{#1}{flow}{#2}%
}
\newcommand*{\setinitialframe}[1]{%
  \c@thisframe=#1%
  \global\usedframebreaktrue
  \global\setlength{\hsize}
  {%
    \csname colwidth\romannumeral\c@thisframe\endcsname
  }%
}
\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}%
    \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
}
\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[\@ff@pages@countreg]{\@ff@staticH}%
    \c@thisframe=\c@maxflow
    \advance\c@thisframe by -1\relax
    \@twocolumn[>\@ff@pages@countreg]%
      \setstaticcontents{\c@maxstatic}{#1}%
  \else
      \@twocolumn
      \c@thisframe=\c@maxflow
      \advance\c@thisframe by -1\relax
  \fi
  \@setcol{\c@thisframe}%
  \relax
}
\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[\@ff@pages@countreg]{\@ff@staticH}%
    \c@thisframe=\c@maxflow
    \advance\c@thisframe by -1\relax
    \@onecolumn[>\@ff@pages@countreg]%
    \setstaticcontents{\c@maxstatic}{#1}%
  \else
    \@twocolumn
    \c@thisframe=\c@maxflow
    \advance\c@thisframe by -1\relax
  \fi
  \@setcol{\c@thisframe}%
  \relax
}
\AtBeginDocument{%
  \c@absolutepage=1\relax
  \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%
  }%
}
\newlength\fftolerance
\setlength\fftolerance{2pt}
\newcommand{\@setcol}[1]{%
  \ifnum\c@maxflow<#1\relax
    \PackageError{flowfram}%
    {Can't set frame '\number#1', doesn't exist}{}%
  \else
    \flf@message{Switching to flow frame \number#1\space on page
      \number\@ff@pages@countreg}%
    \expandafter\global\expandafter\columnwidth
     \csname colwidth\romannumeral#1\endcsname
    \dimen@\columnwidth
    \advance\dimen@ by -\hsize\relax
    \ifdim\dimen@<0pt\relax
      \dimen@=-\dimen@
    \fi
    \ifdim\dimen@>\fftolerance
      \ifusedframebreak
      \else
        \PackageWarning{flowfram}%
        {Moving to flow frame of unequal
        width,\MessageBreak use of \string\framebreak\space advised,
        or text might not appear correctly (difference =
        \the\dimen@, tolerance = \the\fftolerance)}%
      \fi
    \fi
    \global\usedframebreakfalse
    \global\hsize\columnwidth
    \expandafter\global
    \expandafter\vsize\csname colheight\romannumeral#1\endcsname
    \global\@colht\vsize
    \global\@colroom\@colht
    \ifnum\@listdepth>0\relax
      \ifnum\linewidth>\columnwidth
        \global\linewidth\columnwidth
      \fi
    \else
      \global\linewidth\columnwidth
    \fi
    %\global\textwidth\columnwidth
    \setmargin
  \fi
  \stepcounter{displayedframe}%
}
\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
}
\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
}
\newcommand{\@dothehead}{%
  \vbox to \headheight
  {%
    \color@hbox\normalcolor\hbox to \textwidth{\@thehead}%
    \color@endbox
  }%
}
\newcommand{\@dothefoot}{%
  \color@hbox\normalcolor\hbox to \textwidth{\@thefoot}%
  \color@endbox
}
\newcommand{\@dodynamicthehead}{}
\newcommand{\@dodynamicthefoot}{}
\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}%
    \stepcounter{absolutepage}%
    \setcounter{displayedframe}{0}%
    \let\firstmark\botmark
}
\newcommand*{\makedfheaderfooter}{%
  \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
     }%
  }%
}
\@onlypreamble{\makedfheaderfooter}
\newcommand{\footnotecolor}{%
  \@ifundefined{@ff@txtcol@\romannumeral\c@thisframe}%
  {%
    \normalcolor
  }%
  {%
    \edef\ff@txtcol{%
      \csname @ff@txtcol@\romannumeral\c@thisframe\endcsname
    }%
    \@s@tfftextcol
  }%
}
\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
}
\def\@opcol{%
  \@outputdblcol
  \global\@mparbottom\z@
  \global\@textfloatsheight\z@
  \@floatplacement
}
\newif\if@ff@moreframes
\newcommand*{\@ff@checkifmoreframes}{%
  \@ff@moreframesfalse
  \@colN=\c@thisframe
  \whiledo{\@colN<\c@maxflow}%
  {%
    \advance\@colN by 1\relax
    \edef\ff@xpages{\csname @ff@xpages@\romannumeral\@colN\endcsname}%
    \@for\@ff@pp:=\ff@xpages\do
    {%
      \ifnum0\@ff@pp=\@ff@pages@countreg\relax
        \@endfortrue
      \fi
    }%
    \if@endfor
    \else
      \edef\ff@pages{\csname @ff@pages@\romannumeral\@colN\endcsname}%
      \@ff@checkpages{\ff@pages}%
      \if@ff@moreframes
        \@colN=\c@maxflow\relax
      \fi
    \fi
  }%
  \if@ff@moreframes
  \else
    \@ff@tmpN=\@ff@pages@countreg
    \count@=0\relax
    \loop
      \advance\@ff@tmpN by 1\relax
      \@colN=0\relax
      \whiledo{\@colN<\c@maxflow}%
      {%
        \advance\@colN by 1\relax
        \edef\ff@xpages{\csname @ff@xpages@\romannumeral\@colN\endcsname}%
        \@for\@ff@pp:=\ff@xpages\do
        {%
          \ifnum0\@ff@pp=\@ff@tmpN\relax
            \@endfortrue
          \fi
        }%
        \if@endfor
        \else
          \edef\ff@pages{\csname @ff@pages@\romannumeral\@colN\endcsname}%
          \@ff@checkpages[\@ff@tmpN]{\ff@pages}%
          \if@ff@moreframes
            \@colN=\c@maxflow\relax
          \fi
        \fi
      }%
      \if@ff@moreframes
        \count@=4\relax
      \else
        \advance\count@ by 1\relax
      \fi
    \ifnum\count@<4
    \repeat
  \fi
}
\newcommand*{\@ff@checkpages}[2][\@ff@pages@countreg]{%
  \@for\@ff@pp:=#2\do{%
    \@ff@checkthispage{#1}{\@ff@pp}%
  }%
}
\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}%
    }%
  }%
}
\newcommand*{\@ff@checknumrange}[2]{%
  \def\@ff@numstart{0}%
  \def\@ff@numend{100000}%
  \@ff@getrange{#2}%
  \ifnum\@ff@numend>#1\relax
    \@ff@moreframestrue
  \else
    \ifnum\@ff@numend=#1\relax
      \@ff@moreframestrue
    \fi
  \fi
}
\newcount\c@ffrangenum
\newcommand*{\@ff@getrange}[1]{%
  \expandafter\@ff@@getrange#1-\relax\end
}
\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
}
\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}%
}
\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{100000}%
}
\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
}
\def\@@@ff@getrange#1-\relax\end{%
  \def\@ff@numend{#1}%
}
\newcommand*{\@ff@output@adjustframes}{}
\newcommand*{\flowswitchonnext}{%
  \@ifstar\@sflowswitchonnext\@flowswitchonnext
}
\newcommand{\@sflowswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
\newcommand{\@flowswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}%
           {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
\newcommand*{\flowswitchonnextodd}{%
  \@ifstar\@sflowswitchonnextodd\@flowswitchonnextodd
}
\newcommand{\@sflowswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
    \@ff@chckifthispg{\count@}{\ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
\newcommand{\@flowswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
    \@ff@chckifthispg{\count@}{\@ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
\newcommand*{\flowswitchoffnext}{%
  \@ifstar\@sflowswitchoffnext\@flowswitchoffnext
}
\newcommand{\@sflowswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand{\@flowswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand*{\flowswitchoffnextodd}{%
  \@ifstar\@sflowswitchoffnextodd\@flowswitchoffnextodd
}
\newcommand{\@sflowswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \if@notthiscol
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{none}%
      \else
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{none}%
        \else
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}{\@ff@nextpages}%
    }%
  }%
}
\newcommand{\@flowswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \if@notthiscol
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{none}%
      \else
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{none}%
        \else
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}{\@ff@nextpages}%
    }%
  }%
}
\newcommand*{\flowswitchonnextonly}{%
  \@ifstar\@sflowswitchonnextonly\@flowswitchonnextonly
}
\newcommand{\@sflowswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}{\number\count@}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
\newcommand{\@flowswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}{\number\count@}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
\newcommand*{\flowswitchonnextoddonly}{%
  \@ifstar\@sflowswitchonnextoddonly\@flowswitchonnextoddonly
}
\newcommand{\@sflowswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \if@notthiscol
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand{\@flowswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \if@notthiscol
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand*{\flowswitchoffnextonly}{%
  \@ifstar\@sflowswitchoffnextonly\@flowswitchoffnextonly
}
\newcommand{\@sflowswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
\newcommand{\@flowswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
\newcommand*{\flowswitchoffnextoddonly}{%
  \@ifstar\@sflowswitchoffnextoddonly\@flowswitchoffnextoddonly
}
\newcommand{\@sflowswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
\newcommand{\@flowswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
\newcommand*{\dynamicswitchonnext}{%
  \@ifstar\@sdynamicswitchonnext\@dynamicswitchonnext
}
\newcommand{\@sdynamicswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
\newcommand{\@dynamicswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}%
           {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
\newcommand*{\dynamicswitchonnextodd}{%
  \@ifstar\@sdynamicswitchonnextodd\@dynamicswitchonnextodd
}
\newcommand{\@sdynamicswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
    \@df@chckifthispg[\count@]{\ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
\newcommand{\@dynamicswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
    \@df@chckifthispg[\count@]{\@ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
\newcommand*{\dynamicswitchoffnext}{%
  \@ifstar\@sdynamicswitchoffnext\@dynamicswitchoffnext
}
\newcommand{\@sdynamicswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand{\@dynamicswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand*{\dynamicswitchoffnextodd}{%
  \@ifstar\@sdynamicswitchoffnextodd\@dynamicswitchoffnextodd
}
\newcommand{\@sdynamicswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{none}%
      \else
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{none}%
        \else
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}{\@ff@nextpages}%
    }%
  }%
}
\newcommand{\@dynamicswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{none}%
      \else
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{none}%
        \else
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}{\@ff@nextpages}%
    }%
  }%
}
\newcommand*{\dynamicswitchonnextonly}{%
  \@ifstar\@sdynamicswitchonnextonly\@dynamicswitchonnextonly
}
\newcommand{\@sdynamicswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}{\number\count@}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
\newcommand{\@dynamicswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}{\number\count@}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
\newcommand*{\dynamicswitchonnextoddonly}{%
  \@ifstar\@sdynamicswitchonnextoddonly\@dynamicswitchonnextoddonly
}
\newcommand{\@sdynamicswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand{\@dynamicswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand*{\dynamicswitchoffnextonly}{%
  \@ifstar\@sdynamicswitchoffnextonly\@dynamicswitchoffnextonly
}
\newcommand{\@sdynamicswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
\newcommand{\@dynamicswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
\newcommand*{\dynamicswitchoffnextoddonly}{%
  \@ifstar\@sdynamicswitchoffnextoddonly\@dynamicswitchoffnextoddonly
}
\newcommand{\@sdynamicswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
\newcommand{\@dynamicswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
\newcommand*{\staticswitchonnext}{%
  \@ifstar\@sstaticswitchonnext\@staticswitchonnext
}
\newcommand{\@sstaticswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
\newcommand{\@staticswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}%
           {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
\newcommand*{\staticswitchonnextodd}{%
  \@ifstar\@sstaticswitchonnextodd\@staticswitchonnextodd
}
\newcommand{\@sstaticswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
    \@sf@chckifthispg[\count@]{\ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
\newcommand{\@staticswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
    \@sf@chckifthispg[\count@]{\@ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
\newcommand*{\staticswitchoffnext}{%
  \@ifstar\@sstaticswitchoffnext\@staticswitchoffnext
}
\newcommand{\@sstaticswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand{\@staticswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand*{\staticswitchoffnextodd}{%
  \@ifstar\@sstaticswitchoffnextodd\@staticswitchoffnextodd
}
\newcommand{\@sstaticswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{none}%
      \else
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{none}%
        \else
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}{\@ff@nextpages}%
    }%
  }%
}
\newcommand{\@staticswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{none}%
      \else
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{none}%
        \else
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
      \ifnum\@ff@pages@countreg=\count@\relax
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}{\@ff@nextpages}%
    }%
  }%
}
\newcommand*{\staticswitchonnextonly}{%
  \@ifstar\@sstaticswitchonnextonly\@staticswitchonnextonly
}
\newcommand{\@sstaticswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}{\number\count@}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
\newcommand{\@staticswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}{\number\count@}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
\newcommand*{\staticswitchonnextoddonly}{%
  \@ifstar\@sstaticswitchonnextoddonly\@staticswitchonnextoddonly
}
\newcommand{\@sstaticswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand{\@staticswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
      \ifodd\@ff@pages@countreg
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
\newcommand*{\staticswitchoffnextonly}{%
  \@ifstar\@sstaticswitchoffnextonly\@staticswitchoffnextonly
}
\newcommand{\@sstaticswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
\newcommand{\@staticswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
\newcommand*{\staticswitchoffnextoddonly}{%
  \@ifstar\@sstaticswitchoffnextoddonly\@staticswitchoffnextoddonly
}
\newcommand{\@sstaticswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
\newcommand{\@staticswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
\newcommand*{\ffaddtoadjustframeshook}[1]{%
  \@ff@addtolist\@ff@output@adjustframes\entry{#1}%
}
\newif\if@notthiscol
\newif\if@ff@nwpg
\newcount\c@curpg
\newcommand*{\@g@tnextcol}[1]{%
  \@ff@output@adjustframes
  \global\let\@ff@output@adjustframes\@empty
  \@ff@checkifmoreframes
  \if@ff@moreframes
  \else
    \PackageWarning{flowfram}%
    {Run out of flows frames on page \number\@ff@pages@countreg, adding new one}%
    \flf@doifverbose
    {%
      \def\flf@messinfo{Here's the list of flow frames:}%
      \count@=0\relax
      \loop
        \advance\count@ by 1\relax
        \expandafter\toks@\expandafter{\flf@messinfo\MessageBreak}%
        \edef\flf@messinfo{\the\toks@
          \number\count@.
           Pages: \csname @ff@pages@\romannumeral\count@\endcsname.
           Exclusions: \csname @ff@xpages@\romannumeral\count@\endcsname.
        }%
      \ifnum\count@<\c@maxflow
      \repeat
      \PackageInfo{flowfram}{\flf@messinfo\@gobbletwo}%
    }%
    \@onecolumn
    #1=\c@maxflow
  \fi
  \@notthiscoltrue
  \@ff@nwpgfalse
  \@colN=#1\relax
  \c@curpg=\@ff@pages@countreg
  \loop
    \ifnum\@colN=\c@maxflow
      \@colN=1\relax
      \@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\relax
}
\newcommand*{\@ff@chckifthispg}[2]{%
  \@notthiscolfalse
  \edef\ff@xpages{\csname @ff@xpages@\romannumeral#2\endcsname}%
  \@for\@ff@pp:=\ff@xpages\do
  {%
    \ifnum0\@ff@pp=#1\relax
      \@notthiscoltrue
      \@endfortrue
    \fi
  }%
  \if@notthiscol
  \else
    \@notthiscoltrue
    \edef\ff@pages{\csname @ff@pages@\romannumeral#2\endcsname}%
    \@@ff@chckifthispg{#1}%
  \fi
}
\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
        }%
        {%
          \@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
            }%
          }%
        }%
      }%
    }%
  }%
}
\newcommand*{\@sf@chckifthispg}[2][\@ff@pages@countreg]{%
  \@notthiscoltrue
  \edef\ff@pages{\csname @sf@pages@\romannumeral#2\endcsname}%
  \@@ff@chckifthispg{#1}%
}
\newcommand*{\@df@chckifthispg}[2][\@ff@pages@countreg]{%
  \@notthiscoltrue
  \edef\ff@pages{\csname @df@pages@\romannumeral#2\endcsname}%
  \@@ff@chckifthispg{#1}%
}
\newcommand*{\@setcolbox}[1]{%
  \flf@message{Setting contents of box for flow frame \number#1}%
  \expandafter\global\expandafter\setbox
    \csname column\romannumeral#1\endcsname\box\@outputbox
}
\newcommand*{\@docolbox}[1]{%
  \flf@message{Doing flow frame \number#1\space
    (page \number\@ff@pages@countreg)}%
  \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
        }%
    }%
  }%
}
\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}%
}
\newcommand{\@ff@fbox}[4]{%
  {%
    \fboxsep=\flowframesep
    \fboxrule=\flowframerule
    \@s@tffcol
    \kern\@ff@offset
    #4{\@ff@box{#1}{#2}{#3}}%
  }%
}
\newcommand{\@ff@box}[3]{%
  {%
    \@ffbackground
    {%
      \vbox to#2 {\hb@xt@ #1{\hss{\@s@tfftextcol #3}\hss}\vss\kern\z@}%
    }%
  }%
}
\newcommand*{\@putcolbox}[1]{%
  \@ff@chckifthispg{\@ff@pages@countreg}{#1}%
  \if@notthiscol
    \expandafter\ifvoid\csname column\romannumeral#1\endcsname
    \else
      \PackageWarning{flowfram}{Box \number#1\space is not void.
       Dumping. This page: \number\@ff@pages@countreg.
       Page list: "\csname @ff@pages@\romannumeral#1\endcsname".
       Exclusion list: "\csname @ff@xpages@\romannumeral#1\endcsname".
       (Maybe the page list was changed after this frame was
       selected or maybe you should use package option pages=absolute)}%
      \@notthiscolfalse
    \fi
  \fi
  \if@notthiscol
    \flf@message{Flow frame \number#1\space is not required on page
      \number\@ff@pages@countreg}%
  \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
}
\newcommand*{\@putcolbbox}[1]{%
  \@ff@chckifthispg{\@ff@pages@countreg}{#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
}
\newcommand*{\@ff@s@t@doubleboxoffset}{%
  \setlength{\@ff@offset}{-\flowframesep}%
  \addtolength{\@ff@offset}{-3.75\flowframerule}%
  \addtolength{\@ff@offset}{-.5pt}%
}
\newcommand*{\@ff@s@t@ovalboxoffset}{%
  \@ff@offset=-\fontdimen 8\tenln\relax
  \advance\@ff@offset by -\flowframesep\relax
}
\newcommand*{\@ff@s@t@Ovalboxoffset}{%
  \@ff@offset=-\fontdimen 8\tenlnw\relax
  \advance\@ff@offset by -\flowframesep\relax
}
\newcommand*{\@ff@s@t@defaultoffset}{%
  \@ff@offset=-\flowframesep\relax
  \addtolength{\@ff@offset}{-\flowframerule}%
}
\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}%
  }%
}
\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}%
  }%
}
\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}%
  }%
}
\newcommand*{\@putmarginbox}[1]{%
  \@ff@chckifthispg{\@ff@pages@countreg}{#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
}
\newcommand*{\@ff@drawmargins}{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxflow}%
  {%
    \advance\@colN by 1\relax
    \makebox[0pt][l]{\@putmarginbox{\@colN}}%
  }%
}
\def\@ff@getstaticpos[#1][#2][#3]#4{%
  \@ff@tmp@x=#4\relax
  \@ff@tmp@y=#2\relax
  \def\ff@valign{#3}%
}
\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
        }%
      }%
   }%
}
\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}%
}
\newcommand*{\@putstaticbox}[1]{%
  \ifthenelse{\boolean{@sf@hidethis@\romannumeral#1}}%
  {%
    \@notthiscoltrue
    \global\csletcs{if@sf@hidethis@\romannumeral#1}{iffalse}%
  }%
  {%
    \ifthenelse{\boolean{@sf@hide@\romannumeral#1}}%
    {%
      \@notthiscoltrue
    }%
    {%
      \@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
}
\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
}
\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
      }%
      {}%
    }%
    {}%
  }%
}
\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{}%
    }%
    {}%
  }%
}
\newcommand*{\@dodfparbox}[1]{%
  \expandafter\let\expandafter
    \@ff@parshape\csname @df@shape@\romannumeral#1\endcsname
  \expandafter\@ff@getshape\@ff@parshape\relax
  \ifcase\ff@shape
    \expandafter\expandafter\expandafter
    \parbox\csname @df@dim@\romannumeral#1\endcsname
    {%
      \setlength\parindent\sdfparindent
      \csname\ff@style\endcsname{\ff@contents}%
    }%
  \or
    \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
    \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
}
\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}%
      }%
    }%
  }%
}
\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}%
}
\newcommand*{\@putdynamicbox}[1]{%
  \ifthenelse{\boolean{@df@hidethis@\romannumeral#1}}%
  {%
    \@notthiscoltrue
    \global\csletcs{if@df@hidethis@\romannumeral#1}{iffalse}%
  }%
  {%
    \ifthenelse{\boolean{@df@hide@\romannumeral#1}}%
    {%
      \@notthiscoltrue
    }%
    {%
      \@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
}
\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
}
\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}}%
}
\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}}%
}
\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}%
  }%
}
\newcommand*{\@ff@doallflowframes}{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxflow}%
  {%
    \advance\@colN by 1\relax
    \@putcolbox{\@colN}%
  }%
}
\newcommand*{\@ff@doallflowframesbbox}{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxflow}%
  {%
    \advance\@colN by 1\relax
    \@putcolbbox{\@colN}%
  }%
}
\newcommand*{\@ff@doallstatics}{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxstatic}%
  {%
    \advance\@colN by 1\relax
    \@putstaticbox{\@colN}%
  }%
}
\newcommand*{\@ff@doallstaticsbbox}{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxstatic}%
  {%
    \advance\@colN by 1\relax
    \@putstaticbbox{\@colN}%
  }%
}
\newcommand*{\@ff@doalldynamics}{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxdynamic}%
  {%
    \advance\@colN by 1\relax
    \@putdynamicbox{\@colN}%
  }%
}
\newcommand*{\@ff@doalldynamicsbbox}{%
  \@colN=0\relax
  \whiledo{\@colN<\c@maxdynamic}%
  {%
    \advance\@colN by 1\relax
    \@putdynamicbbox{\@colN}%
  }%
}
\newcommand*{\@ff@dotypeblock}{%
  \makebox[0pt][l]%
  {%
    \@fr@meifdraft[\setffdrafttypeblockcolor]%
    {%
      \vbox to \textheight{\hbox to \textwidth{}}%
    }%
    {}%
  }%
}
\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
    }%
  }%
}
\newcount\@nxtcol
\def\@outputdblcol{%
  \@nxtcol=\c@thisframe
  \c@curpg=\@ff@pages@countreg
  \@g@tnextcol{\@nxtcol}%
  \if@ff@nwpg
    \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
    \advance\c@curpg by -\@ff@pages@countreg\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
    \global\@firstcolumnfalse
    \@setcolbox\c@thisframe
  \fi
  \global\c@thisframe=\@nxtcol
  \@setcol{\c@thisframe}\relax
  \global\@colht\vsize
}
\def\@dblfloatplacement{%
  \global\@dbltopnum\c@dbltopnumber
  \global\@dbltoproom\dbltopfraction\@colht\@textmin
  \@colht\advance\@textmin -\@dbltoproom
  \@fpmin\dblfloatpagefraction\vsize
  \@fptop \@dblfptop \@fpsep \@dblfpsep \@fpbot \@dblfpbot
}
\newenvironment{statictable}{\def\@captype{table}}{}
\newenvironment{staticfigure}{\def\@captype{figure}}{}
\newif\ifffvadjust
\ffvadjusttrue
\renewcommand*{\onecolumn}{\@onecolumn}
\newcommand*{\@onecolumn}[1][all]{%
  \@onecolumninarea[#1]{\textwidth}{\textheight}{0pt}{0pt}%
}
\newlength\columnheight
\newcommand*{\onecolumninarea}{\@onecolumninarea}
\@onlypreamble{\onecolumninarea}
\newcommand*{\@onecolumninarea}[5][all]{%
  \setlength{\columnheight}{#3}%
  \ifffvadjust
    \adjustheight{\columnheight}%
  \fi
  \@n@wflowframe[#1]{#2}{\columnheight}{#4}{#5}%
}
\renewcommand*{\twocolumn}{\@twocolumn}
\newcommand*{\@twocolumn}[1][all]{%
  \@twocolumninarea[#1]{\textwidth}{\textheight}{0pt}{0pt}%
}
\newcommand*{\twocolumninarea}{\@twocolumninarea}
\@onlypreamble{\twocolumninarea}
\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
}
\newcommand*{\Ncolumn}[2][all]{%
  \Ncolumninarea[#1]{#2}{\textwidth}{\textheight}{0pt}{0pt}%
}
\@onlypreamble{\Ncolumn}
\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}
\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
}
\newlength{\vcolumnsep}
\setlength{\vcolumnsep}{\columnsep}
\newcommand*{\onecolumntop}[3][all]{%
  \onecolumntopinarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}%
}
\@onlypreamble{\onecolumntop}
\newcommand*{\onecolumnStop}[2][all]{%
  \onecolumntopinarea[#1]{static}{#2}{\textwidth}{\textheight}{0pt}{0pt}%
}
\newcommand*{\onecolumnDtop}[2][all]{%
  \onecolumntopinarea[#1]{dynamic}{#2}{\textwidth}{\textheight}{0pt}{0pt}%
}
\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'%
        }%
      }%
    }%
  }%
}
\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}
\newcommand*{\onecolumnStopinarea}[6][all]{%
  \onecolumntopinarea[#1]{static}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\onecolumnDtopinarea}[6][all]{%
  \onecolumntopinarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\twocolumntop}[3][all]{%
  \twocolumntopinarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}%
}
\@onlypreamble{\twocolumntop}
\newcommand*{\twocolumnStop}[2][all]{%
  \@twocolumntopinarea[#1]{static}{#2}{\textwidth}{\textheight}{0pt}{0pt}%
}
\newcommand*{\twocolumnDtop}[2][all]{%
  \twocolumntop[#1]{dynamic}{#2}%
}
\newcommand*{\twocolumntopinarea}{\@twocolumntopinarea}
\newcommand*{\@twocolumntopinarea}[7][all]{%
  \setlength{\@ff@staticH}{#3}%
  \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}%
  \addtolength{\columnheight}{-\vcolumnsep}%
  \ifffvadjust\adjustheight{\columnheight}\fi
  \setlength{\columnwidth}{#4}%
  \addtolength{\columnwidth}{-\columnsep}%
  \divide\columnwidth by 2\relax
  \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}
\newcommand*{\twocolumnStopinarea}[6][all]{%
  \twocolumntopinarea[#1]{static}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\twocolumnDtopinarea}[6][all]{%
  \twocolumntopinarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\Ncolumntop}[4][all]{%
  \Ncolumntopinarea[#1]{#2}{#3}{#4}{\textwidth}{\textheight}{0pt}{0pt}%
}
\@onlypreamble{\Ncolumntop}
\newcommand*{\NcolumnStop}[3][all]{%
  \Ncolumntop[#1]{static}{#2}{#3}%
}
\newcommand*{\NcolumnDtop}[3][all]{%
  \Ncolumntop[#1]{dynamic}{#2}{#3}%
}
\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}
\newcommand*{\@Ncolumntopinarea}[8][all]{%
  \setlength{\@ff@staticH}{#4}%
  \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}%
  \addtolength{\columnheight}{-\vcolumnsep}%
  \ifffvadjust
    \adjustheight{\columnheight}%
  \fi
  \@colN=#3\relax
  \advance\@colN by -1\relax
  \setlength{\columnwidth}{#5}%
  \addtolength{\columnwidth}{-\@colN\columnsep}%
  \divide\columnwidth by #3\relax
  \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}%
    \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
}
\newcommand*{\NcolumnStopinarea}[7][all]{%
  \Ncolumntopinarea[#1]{static}{#2}{#3}{#4}{#5}{#6}{#7}%
}
\newcommand*{\NcolumnDtopinarea}[7][all]{%
  \Ncolumntopinarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}{#7}%
}
\newcommand*{\onecolumnbottom}[3][all]{%
  \onecolumnbottominarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}%
}
\@onlypreamble{\onecolumnbottom}
\newcommand*{\onecolumnSbottom}[2][all]{%
  \onecolumnbottom[#1]{static}{#2}%
}
\newcommand*{\onecolumnDbottom}[2][all]{%
  \onecolumnbottom[#1]{dynamic}{#2}%
}
\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}%
}
\@onlypreamble{\onecolumnbottominarea}
\newcommand*{\onecolumnSbottominarea}[6][all]{%
  \onecolumnbottominarea[#1]{static}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\onecolumnDbottominarea}[6][all]{%
  \onecolumnbottominarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\twocolumnbottom}[3][all]{%
  \twocolumnSbottominarea[#1]{#2}{#3}{\textwidth}{\textheight}{0pt}{0pt}%
}
\@onlypreamble{\twocolumnbottom}
\newcommand*{\twocolumnSbottom}[2][all]{%
  \twocolumnbottom[#1]{static}{#2}%
}
\newcommand*{\twocolumnDbottom}[2][all]{%
  \twocolumnbottom[#1]{dynamic}{#2}%
}
\newcommand*{\twocolumnbottominarea}[7][all]{%
  \setlength{\@ff@staticW}{#4}%
  \setlength{\@ff@staticH}{#3}%
  \setlength{\columnheight}{#5}%
  \addtolength{\columnheight}{-\@ff@staticH}%
  \addtolength{\columnheight}{-\vcolumnsep}%
  \ifffvadjust\adjustheight{\columnheight}\fi%
  \newframe[#1]{#2}{\@ff@staticW}{\@ff@staticH}{#6}{#7}%
  \setlength{\@ff@tmp@y}{#5}%
  \addtolength{\@ff@tmp@y}{-\columnheight}%
  \addtolength{\@ff@tmp@y}{#7}%
  \setlength{\columnwidth}{\@ff@staticW}%
  \addtolength{\columnwidth}{-\columnsep}%
  \divide\columnwidth by 2\relax
  \setlength{\@ff@tmp@x}{\columnwidth}%
  \addtolength{\@ff@tmp@x}{\columnsep}%
  \addtolength{\@ff@tmp@x}{#6}%
  \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}
\newcommand*{\twocolumnSbottominarea}[6][all]{%
  \twocolumnbottominarea[#1]{static}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\twocolumnDbottominarea}[6][all]{%
  \twocolumnbottominarea[#1]{dynamic}{#2}{#3}{#4}{#5}{#6}%
}
\newcommand*{\Ncolumnbottom}[4][all]{%
  \Ncolumnbottominarea[#1]{#2}{#3}{#4}{\textwidth}{\textheight}{0pt}{0pt}%
}
\@onlypreamble{\Ncolumnbottom}
\newcommand*{\NcolumnSbottom}[3][all]{%
  \Ncolumnbottom[#1]{static}{#2}{#3}%
}
\newcommand*{\NcolumnDbottom}[3][all]{%
  \Ncolumnbottom[#1]{dynamic}{#2}{#3}%
}
\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}
\newcommand*{\@NcolumnSbottominarea}[8][all]{%
  \setlength{\@ff@staticH}{#4}%
  \setlength{\columnheight}{#6}%
  \addtolength{\columnheight}{-\@ff@staticH}%
  \addtolength{\columnheight}{-\vcolumnsep}%
  \ifffvadjust
    \adjustheight{\columnheight}%
  \fi
  \newframe[#1]{#2}{#5}{\@ff@staticH}{#7}{#8}%
  \setlength{\@ff@tmp@y}{#6}%
  \addtolength{\@ff@tmp@y}{-\columnheight}%
  \addtolength{\@ff@tmp@y}{#8}%
  \@colN=#3\relax
  \advance\@colN by -1\relax
  \setlength{\columnwidth}{#5}%
  \addtolength{\columnwidth}{-\@colN\columnsep}%
  \divide\columnwidth by #3\relax
  \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}%
    \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
}
\newcommand*{\NcolumnSbottominarea}[1][all]{%
  \Ncolumnbottominarea[#1]{static}%
}
\newcommand*{\NcolumnDbottominarea}[1][all]{%
  \Ncolumnbottominarea[#1]{dynamic}%
}
\newcount\@ff@adjh
\newcommand*{\adjustheight}[1]{%
  \@ff@adjh=#1\relax
  \divide\@ff@adjh by \baselineskip\relax
  #1=\baselineskip\relax
  \multiply#1 by \@ff@adjh\relax
}
\newcommand*{\adjustcolsep}{%
  \multiply\columnsep by 2\relax
  \addtolength{\columnsep}{\marginparwidth}%
}
\newlength\@ff@staticW
\newcommand*{\vtwotone}[1][all]{%
  \def\ff@pages{#1}%
  \@vtwotone
}

\newcommand*{\@vtwotone}[1][0pt]{\@@vtwotonebottom{#1}{\paperheight}}
\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}
\newcommand*{\vtwotonebottom}[1][all]{%
  \def\ff@pages{#1}%
  \@vtwotonebottom
}

\@onlypreamble{\vtwotonebottom}

\newcommand*{\@vtwotonebottom}[2][0pt]{\@@vtwotonebottom{#1}{#2}}
\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}%
}
\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}%
}
\newcount\@thisstrip
\newcommand*{\vNtone}[1][all]{%
  \def\ff@pages{#1}%
  \@vNtone
}
\newcommand*{\@vNtone}[2][0pt]{%
  \@@vNtone{#1}{#2}{\paperheight}%
}
\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
}
\newcommand*{\@nextvNband}{%
  \ifnum\@thisstrip>0\relax
   \let\flf@next\@@nextvNband
  \else
   \let\flf@next\relax
  \fi
  \advance\@thisstrip by -1\relax
  \flf@next
}
\newcommand*{\@@nextvNband}[3]{%
  \@nextvband{\ff@pages}{\@ff@staticH}{#1}{#2}{#3}%
  \@nextvNband
}

\@onlypreamble{\vNtone}
\newcommand*{\vNtonebottom}[1][all]{%
  \def\ff@pages{#1}%
  \@vNtonebottom
}
\@onlypreamble{\vNtonebottom}
\newcommand*{\@vNtonebottom}[3][0pt]{%
  \@@vNtone{#1}{#2}{#3}%
}
\newcommand*{\vNtonetop}[1][all]{%
  \def\ff@pages{#1}%
  \@vNtonetop
}
\@onlypreamble{\vNtonetop}
\newcommand*{\@vNtonetop}[3][0pt]{%
  \@@vNtonetop{#1}{#2}{#3}%
}
\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%
}
\newcommand*{\htwotone}[1][all]{%
  \def\ff@pages{#1}%
  \@htwotone
}
\newcommand*{\@htwotone}[1][0pt]{\@@htwotoneleft{#1}{\paperwidth}}
\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}
\newcommand*{\htwotoneleft}[1][all]{%
  \def\ff@pages{#1}%
  \@htwotoneleft
}
\@onlypreamble{\htwotoneleft}
\newcommand*{\@htwotoneleft}[2][0pt]{\@@htwotoneleft{#1}{#2}}
\newcommand*{\htwotoneright}[1][all]{%
  \def\ff@pages{#1}%
  \@htwotoneright
}
\@onlypreamble{\htwotoneright}
\newcommand*{\@htwotoneright}[2][0pt]{\@@htwotoneright{#1}{#2}}
\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}%
}
\newcommand*{\hNtone}[1][all]{%
  \def\ff@pages{#1}%
  \@hNtone
}
\@onlypreamble{\hNtone}
\newcommand*{\@hNtone}[2][0pt]{%
  \@@hNtone{#1}{#2}{\paperwidth}%
}
\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
}
\newcommand*{\hNtoneleft}[1][all]{%
  \def\ff@pages{#1}%
  \@hNtoneleft
}
\@onlypreamble{\hNtoneleft}
\newcommand*{\@hNtoneleft}[3][0pt]{%
  \@@hNtone{#1}{#2}{#3}%
}
\newcommand*{\hNtoneright}[1][all]{%
  \def\ff@pages{#1}%
  \@hNtoneright
}
\@onlypreamble{\hNtoneright}
\newcommand*{\@hNtoneright}[3][0pt]{%
  \@@hNtoneright{#1}{#2}{#3}%
}
\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
}
\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}%
}
\newcommand*{\@nexthNband}{%
  \ifnum\@thisstrip>0\relax
   \let\flf@next\@@nexthNband
  \else
   \let\flf@next\relax
  \fi
  \advance\@thisstrip by -1\relax
  \flf@next
}
\newcommand*{\@@nexthNband}[3]{%
  \@nexthband{\ff@pages}{\@ff@staticW}{#1}{#2}{#3}%
  \@nexthNband
}
\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}%
}
\newlength\ffcolumnseprule
\setlength{\ffcolumnseprule}{2pt}
\newcommand*{\ffruledeclarations}{}
\newcommand*{\insertvrule}{\@ifstar\@sinsertvrule\@insertvrule}
\newcommand*{\@insertvrule}[1][0pt]{%
  \@ifnextchar[{\@@insertvrule[#1]}{\@@insertvrule[#1][0pt]}%
}
\newlength\@ff@left@x
\newlength\@ff@left@y
\newlength\@ff@left@evenx
\newlength\@ff@left@eveny
\newlength\@ff@left@width
\newlength\@ff@left@height
\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}%
}
\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}%
  \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}%
}
\newcommand*{\ffvrule}[3]{%
  \hfill \rule[-#1]{#2}{#3}\hfill\mbox{}%
}
\newcommand*{\@sinsertvrule}[1][0pt]{%
  \@ifnextchar[{\@@sinsertvrule[#1]}{\@@sinsertvrule[#1][0pt]}%
}
\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}%
}
\newcommand*{\inserthrule}{\@ifstar\@sinserthrule\@inserthrule}
\newcommand*{\@inserthrule}[1][0pt]{%
  \@ifnextchar[{\@@inserthrule[#1]}{\@@inserthrule[#1][0pt]}%
}
\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}%
}
\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}%
}
\newcommand*{\ffhrule}[3]{%
  \hspace*{-#1}\rule{#2}{#3}%
}
\newcommand*{\@sinserthrule}[1][0pt]{%
  \@ifnextchar[{\@@sinserthrule[#1]}{\@@sinserthrule[#1][0pt]}%
}
\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}%
}
\newcommand*{\dfchaphead}{%
  \@ifstar\@sdynamicchap\@dynamicchap
}
\newcommand{\DFchapterstyle}[1]{#1}
\newcommand{\DFschapterstyle}[1]{#1}
\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}%
      }%
    }%
  }%
}
\newcommand{\@sdynamicchap}[1]{%
  \@dynamicframeid{#1}%
  \@dynamicchap{\ff@id}%
}
\newcounter{maxthumbtabs}
\@ifundefined{chapter}%
{%
  \newcommand*{\defaultthumbtabtype}{section}%
}%
{%
  \newcommand*{\defaultthumbtabtype}{chapter}%
}
\newcommand*{\@ttb@type}{\defaultthumbtabtype}
\newcommand*{\makethumbtabs}[2][0pt]{%
  \@ifnextchar[%
  {\@makethumbtabs[#1]{#2}}%
  {%
    \@makethumbtabs[#1]{#2}[\defaultthumbtabtype]%
  }%
}
\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}%
}
\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
  }%
}
\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
    }%
  }%
}
\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
    }%
    {}%
  }%
}
\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}%
}
\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}%
}
\newlength{\thumbtabwidth}
\setlength{\thumbtabwidth}{1cm}
\@ifundefined{hyperlink}%
{%
  \newcommand{\thumbtabindexformat}[3]{%
    \thumbtabformat{#2}{#3}%
  }%
}%
{%
  \newcommand{\thumbtabindexformat}[3]{%
    \hyperlink{#1}{\thumbtabformat{#2}{#3}}%
  }%
}
\newcommand{\thumbtabformat}[2]{%
  \if@ttb@rotate
    \rotatebox{-90}%
    {%
      \parbox[c][\thumbtabwidth]{#2}{%
        \centering#1%
      }%
    }%
  \else
    \parbox[c][#2]{\thumbtabwidth}{%
      \centering\@ttb@stack{#1}%
    }%
  \fi
}
\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}%
}
\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}%
}
\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}%
}
\newcount\@greyscale
\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}%
    \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}%
    \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}}
    \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
    \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}%
  }%
}%
\newcommand*{\enablethumbtabs}{%
  \ifnum\c@maxthumbtabs>0\relax
    \@ff@tmpN=0\relax
    \@dynamicframeid{thumbtab1}%
    \whiledo{\@ff@tmpN<\c@maxthumbtabs}%
    {%
      \advance\@ff@tmpN by 1\relax
      \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
}
\newcommand*{\disablethumbtabs}{%
  \ifnum\c@maxthumbtabs>0\relax
    \@ff@tmpN=0\relax
    \@dynamicframeid{thumbtab1}%
    \whiledo{\@ff@tmpN<\c@maxthumbtabs}%
    {%
      \advance\@ff@tmpN by 1\relax
      \expandafter\xdef\csname @df@pages@\romannumeral\ff@id\endcsname
        {none}%
      \advance\ff@id by 1\relax
      \expandafter\xdef\csname @df@pages@\romannumeral\ff@id\endcsname
        {none}%
      \advance\ff@id by 1\relax
    }%
  \fi
}
\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
}
\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}}%
  }%
}
\newcommand{\@setthumbtab}[2]{%
  \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}%
  }%
}
\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}}%
  }%
}
\newcommand{\@setthumbtabindex}[2]{%
  \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}%
  }%
}
\newcommand*{\tocandthumbtabindex}{%
  \aligntoctrue
  \tableofcontents
  \thumbtabindex
  \aligntocfalse
}
\newcommand*{\@ttb@minitoctype}{\@ttb@type}
\let\@ttb@old@starttoc\@starttoc
\newif\if@storetoc
\@storetocfalse
\renewcommand*{\@starttoc}[1]{%
  \if@storetoc
    \@ttb@storetoc{#1}%
  \else
    \@ttb@old@starttoc{#1}%
  \fi
}
\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
}
\newcommand*{\@storefileconts}[1]{%
  \IfFileExists{#1}%
  {%
    \@@storefileconts\@filef@und
  }%
  {%
    \PackageInfo{flowfram}{No file #1.}%
  }%
}
\newcount\c@maxtocunits
\newcount\c@maxminitoc
\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
}
\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}%
  }%
  \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
}
\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}
\long\def\@checkcontentsline#1#2\end{%
  \ifx#1\contentsline
    \@contslinetrue
  \else
    \@contslinefalse
  \fi
}
\def\@gettype\contentsline#1#2\end{%
  \def\@ttb@contstype{#1}%
}
\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
}
\newlength\beforeminitocskip
\setlength{\beforeminitocskip}{0pt}
\newlength\afterminitocskip
\setlength{\afterminitocskip}{\baselineskip}
\newcommand*{\dominitoc}[1]{%
  \if@minitoc
    \@dominitoc{#1}%
  \fi
}
\newcommand*{\@dominitoc}[1]{\@@dominitoc{#1}}
\newcommand{\minitocstyle}[1]{%
  \normalfont\normalsize\normalcolor
  #1%
}
\newcommand*{\@@dominitoc}[1]{%
  {%
    \minitocstyle
    {%
      \vskip\beforeminitocskip
      \csname @minitoc@\romannumeral#1\endcsname
    }%
  }%
  \vskip\afterminitocskip
}
\newcommand*{\appenddfminitoc}{%
  \renewcommand{\beforeminitocskip}{\baselineskip}%
  \@ifstar\@sappendminitocdf\@appendminitocdf
}
\newcommand*{\@sappendminitocdf}[1]{%
  \renewcommand{\@dominitoc}[1]{%
    \@sappenddynamic{#1}{\@@dominitoc{##1}}%
  }%
}
\newcommand*{\@appendminitocdf}[1]{%
  \renewcommand{\@dominitoc}[1]{%
    \@appenddynamic{#1}{\@@dominitoc{##1}}%
  }%
}
\newcommand*{\@printtoc}{%
  \@colN=0\relax
  \csname @toc@\romannumeral\@colN\endcsname
  \whiledo{\@colN<\c@maxtocunits}%
  {%
    \advance\@colN by 1\relax
    \csname @toc@\romannumeral\@colN\endcsname
  }%
}
\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
  }%
}
\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}%
      }%
    }%
  }%
}
\@onlypreamble{\enableminitoc}
\newcommand{\@makeminitocchapter}{%
  \let\@mtoc@old@chapter\@chapter
  \def\@chapter[##1]##2{%
    \@mtoc@old@chapter[##1]{##2}%
    \stepcounter{minitoc}%
    \dominitoc{\c@minitoc}%
    \@afterheading
  }%
}
\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
    }%
  }%
}
\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}
%\iffalse
%    \begin{macrocode}
%</flowfram-2014-09-30.sty>
%    \end{macrocode}
%\fi
%\iffalse
%    \begin{macrocode}
%<*flowfram-2025-08-23.sty>
%    \end{macrocode}
%\fi
% \section{Rollback v1.18 (flowfram-2025-08-23)}
% Declare package, and identify it as a \LaTeXe\ package.
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
%    \end{macrocode}
% Rollback release:
%    \begin{macrocode}
\DeclareRelease{v1.17}{2014-09-30}{flowfram-2014-09-30.sty}
\DeclareCurrentRelease{v1.18}{2025-08-23}
%    \end{macrocode}
%Declare package:
%    \begin{macrocode}
\ProvidesPackage{flowfram}[2025/08/23 v1.18 (NLCT)]
%    \end{macrocode}
% Load packages needed by this package
%    \begin{macrocode}
\RequirePackage{ifthen}
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{now loading xkeyval instead of keyval}
%    \begin{macrocode}
\RequirePackage{xkeyval}
\RequirePackage{graphics}
\RequirePackage{afterpage}
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{now loading xfor and etoolbox}
%    \begin{macrocode}
\RequirePackage{xfor}
\RequirePackage{etoolbox}
%    \end{macrocode}
%    \begin{macrocode}
\@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. 
%\begin{option}{draft}
% If draft, switch to draft definitions.
%    \begin{macrocode}
\DeclareOptionX{draft}{\@ffdraft}
%    \end{macrocode}
%\end{option}
%\begin{option}{final}
% If not draft, reset commands so that no \glspl{bbox}
% are drawn.
%    \begin{macrocode}
\DeclareOptionX{final}{\@ffnodraft}
%    \end{macrocode}
%\end{option}
% Set the default to \opt{final}:
%    \begin{macrocode}
\@ffnodraft
%    \end{macrocode}
%
%\begin{option}{verbose}
%\changes{1.14}{2012-11-10}{new}
% Verbose mode is primarily for debug messages.
%    \begin{macrocode}
\define@choicekey{flowfram.sty}%
  {verbose}[\@flf@val\@flf@nr]%
  {true,false}[true]%
  {%
    \ifcase\@flf@nr\relax
      \renewcommand*{\flf@doifverbose}[1]{##1}%
      \renewcommand*{\flf@message}[1]{\PackageInfo{flowfram}{##1}}%
    \or
      \renewcommand*{\flf@doifverbose}[1]{}%
      \renewcommand*{\flf@message}[1]{}%
    \fi
  }
%    \end{macrocode}
%\end{option}
%\begin{macro}{\flf@message}
% Messaging system (to help debugging):
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\flf@message}[1]{%
  \flf@doifverbose
  {%
    \PackageInfo{flowfram}{##1}%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flf@doifverbose}
%\changes{1.14}{2012-11-10}{new}
% Initialise:
%    \begin{macrocode}
\newcommand*{\flf@doifverbose}[1]{}
%    \end{macrocode}
%\end{macro}
%
%\begin{option}{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}.
%\changes{1.14}{2012-11-10}{changed to boolean key}
%    \begin{macrocode}
\define@boolkey{flowfram.sty}[@ttb@]{rotate}[true]{}
\@ttb@rotatetrue
%    \end{macrocode}
%\end{option}
%\begin{option}{norotate}
% Provide \opt{norotate} option for backward compatibility
%    \begin{macrocode}
\DeclareOptionX{norotate}{\@ttb@rotatefalse}
%    \end{macrocode}
%\end{option}
%\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%
  \fi
}
%    \end{macrocode}
%\end{macro}
% Should the thumbtabs include number, title, both or
% neither?
%\begin{macro}{\if@ttb@num}
%    \begin{macrocode}
\newif\if@ttb@num
\@ttb@numfalse
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\if@ttb@title}
%    \begin{macrocode}
\newif\if@ttb@title
\@ttb@titletrue
%    \end{macrocode}
%\begin{option}{thumbtabs}
%\changes{1.14}{2012-11-10}{new}
% The \opt{thumbtabs} option replaces the \opt{ttbtitle},
% \opt{ttbnotitle}, \opt{ttbnum} and \opt{ttbnonum}
% options.
%    \begin{macrocode}
\define@choicekey{flowfram.sty}%
  {thumbtabs}[\@flf@val\@flf@nr]%
  {title,number,both,none}[title]%
  {%
    \ifcase\@flf@nr\relax
%    \end{macrocode}
% Thumbtabs to only include title
%    \begin{macrocode}
       \@ttb@numfalse
       \@ttb@titletrue
    \or
%    \end{macrocode}
% Thumbtabs to only include number
%    \begin{macrocode}
       \@ttb@numtrue
       \@ttb@titlefalse
    \or
%    \end{macrocode}
% Thumbtabs to include title and number
%    \begin{macrocode}
       \@ttb@numtrue
       \@ttb@titletrue
    \or
%    \end{macrocode}
% Thumbtabs don't have title or number
%    \begin{macrocode}
       \@ttb@numfalse
       \@ttb@titlefalse
    \fi
  }
%    \end{macrocode}
%\end{option}
% Provide old options for backward compatibility:
%\begin{option}{ttbtitle}
%    \begin{macrocode}
\DeclareOptionX{ttbtitle}{\@ttb@titletrue}
%    \end{macrocode}
%\end{option}
%\begin{option}{ttbnotitle}
%    \begin{macrocode}
\DeclareOptionX{ttbnotitle}{\@ttb@titlefalse}
%    \end{macrocode}
%\end{option}
%\begin{option}{ttbnum}
%    \begin{macrocode}
\DeclareOptionX{ttbnum}{\@ttb@numtrue}
%    \end{macrocode}
%\end{option}
%\begin{option}{ttbnonum}
%    \begin{macrocode}
\DeclareOptionX{ttbnonum}{\@ttb@numfalse}
%    \end{macrocode}
%\end{option}
%
%\begin{option}{pages}
%\changes{1.14}{2012-11-10}{new}
% Determine whether the pages key when defining frames refers to the
% page number as given by \cs{c@page} or the absolute
% page number as given by \cs{c@absolutepage}.
%    \begin{macrocode}
\define@choicekey{flowfram.sty}{pages}[\@flf@val\@flf@nr]%
  {relative,absolute}%
  {%
    \ifcase\@flf@nr\relax
%    \end{macrocode}
% Relative (use \cs{c@page}):
%    \begin{macrocode}
      \renewcommand*{\@ff@pages@countreg}{\c@page}%
    \or
%    \end{macrocode}
% Absolute (use \cs{c@absolutepage}):
%    \begin{macrocode}
      \renewcommand*{\@ff@pages@countreg}{\c@absolutepage}%
    \fi
  }
%    \end{macrocode}
%\end{option}
%\begin{macro}{\@ff@pages@countreg}
%\changes{1.14}{2012-11-10}{new}
% The default is relative (for backwards compatibility).
%    \begin{macrocode}
\newcommand*{\@ff@pages@countreg}{\c@page}
%    \end{macrocode}
%\end{macro}
%\begin{counter}{absolutepage}
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcounter{absolutepage}
%    \end{macrocode}
%\end{counter}
%
%\begin{option}{color}
%\changes{1.14}{2012-11-10}{changed to boolean option}
% If \opt[true]{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 \cs{flowframecol} and \cs{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 \cs{@s@tffcol} and \cs{@s@tfftextcol}
% switch to the border and text colour, respectively. They
% both assume that \cs{ff@col} has been set to the 
% relevant colour before use.
%    \begin{macrocode}
\define@choicekey{flowfram.sty}{color}[\@flf@val\@flf@nr]{true,false}[true]{%
  \ifcase\@flf@nr\relax
%    \end{macrocode}
% Option set to true:
%    \begin{macrocode}
    \@ff@enablecolor
  \or
%    \end{macrocode}
% Option set to false, ensure that the colour changing
% commands do nothing:
%    \begin{macrocode}
    \@ff@disablecolor
  \fi
}
%    \end{macrocode}
%\end{option}
% Provide \opt{nocolor} option for backward compatibility:
%    \begin{macrocode}
\DeclareOptionX{nocolor}{%
  \@ff@disablecolor
}
%    \end{macrocode}
%\begin{macro}{\@ff@enablecolor}
%\changes{1.14}{2012-11-10}{new}
% Enable colour commands.
%    \begin{macrocode}
\newcommand*{\@ff@enablecolor}{%
  \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}
%\end{macro}
%\begin{macro}{\@ff@disablecolor}
%\changes{1.14}{2012-11-10}{new}
% Disable colour commands.
%    \begin{macrocode}
\newcommand*{\@ff@disablecolor}{%
  \def\flowframetextcol{}%
  \def\flowframecol{}%
  \renewcommand{\@s@tffcol}{}\renewcommand{\@s@tfftextcol}{}%
  \renewcommand{\@ffbackground}[1]{##1}%
}
%    \end{macrocode}
%\end{macro}
%
%\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{option}{LR}
%    \begin{macrocode}
\DeclareOptionX{LR}{\lefttorightcolumnstrue}
%    \end{macrocode}
%\end{option}
%\begin{option}{RL}
%    \begin{macrocode}
\DeclareOptionX{RL}{\lefttorightcolumnsfalse}
%    \end{macrocode}
%\end{option}
% If the \cs{normalcolor} command is something other than 
% \cs{relax}, then implement
% the \opt[true]{color} option as the default, otherwise implement the
% \opt[false]{color} option as the default.
%    \begin{macrocode}
\ifx\normalcolor\relax
  \@ff@disablecolor
\else
  \@ff@enablecolor
\fi
%    \end{macrocode}
% Now the defaults have all been set, the package options
% specified by the user can be processed:
%    \begin{macrocode}
\ProcessOptionsX
%    \end{macrocode}
% If \opt[true]{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}
%
%    \begin{macrocode}
\@ifundefined{chapter}{}%
{%
%    \end{macrocode}
%\begin{macro}{\chapterfirstpagestyle}
% User may want a non standard style for the first page of 
% each chapter, so modify chapter commands to take this into 
% account.
%    \begin{macrocode}
  \newcommand*{\chapterfirstpagestyle}{plain}%
%    \end{macrocode}
%\end{macro}
%
%    \begin{macrocode}
  \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}
%\end{macro}
%
%\begin{macro}{\ffprechapterhook}
%\changes{1.14}{2012-11-10}{new}
% Hook at start of chapter (before page break issued)
%    \begin{macrocode}
  \newcommand*{\ffprechapterhook}{}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\chapter}
% Modify \cs{chapter} so the hook is called at the start:
%    \begin{macrocode}
  \let\@ff@OLD@ch@pter\chapter
  \renewcommand{\chapter}{%
    \ffprechapterhook
    \@ff@OLD@ch@pter
  }
%    \end{macrocode}
%\end{macro}
%
% End of test if \cs{chapter} defined:
%    \begin{macrocode}
}
%    \end{macrocode}
%
%\begin{counter}{maxflow}
% 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}
%\end{counter}
%
%\begin{counter}{thisframe}
% 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}
%\end{counter}
%\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}
%\begin{counter}{displayedframe}
% 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}
%\end{counter}
%
%\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}
%\begin{counter}{maxstatic}
% Define a counter to store the total number of \glspl{static}:
%    \begin{macrocode}
\newcounter{maxstatic}
\c@maxstatic=0\relax
%    \end{macrocode}
%\end{counter}
%\begin{counter}{maxdynamic}
% Define a counter to store the total number of \glspl{dynamic}:
%    \begin{macrocode}
\newcounter{maxdynamic}
\c@maxdynamic=0\relax
%    \end{macrocode}
%\end{counter}
% 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".
%\changes{1.14}{2012-11-10}{made change to switch global}
%    \begin{macrocode}
\newif\ifusedframebreak
\newcommand{\framebreak}[1][4]{%
  \global\usedframebreaktrue
  {%
    \parfillskip=0pt\pagebreak[#1]\parskip=0pt\par\noindent
  }%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\finishthispage}
% The commands \cs{newpage} and
% \cs{pagebreak} can be used to move on to the next
% \gls{flow}, but to finish the entire page, use 
% "\finishthispage". This is (loosely) based on the code for
% \cs{clearpage}. (\cs{@dbltopnum} not required as we can't have
% column-spanning floats.)
%\changes{1.14}{2012-11-10}{change \cs{c@page} to
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
\newcommand{\finishthispage}{%
  \ifvmode
    \@colN=\c@thisframe\relax
    \count@=\c@absolutepage\relax
    \ifdim \pagetotal<\topskip
      \hbox{}%
    \fi
    \newpage \write \m@ne {}\vbox {}\penalty -\@Mi
%    \end{macrocode}
% If that was the last \gls{flow} on the page, then we're done,
% otherwise iterate through the remaining \glspl{flow}.
%    \begin{macrocode}
    \ifnum\count@=\c@absolutepage\relax
      \whiledo{\@colN<\c@maxflow \OR \@colN=\c@maxflow}%
      {%
        \@ff@chckifthispg{\@ff@pages@countreg}{\@colN}%
        \if@notthiscol
        \else
          \c@thisframe=\@colN\relax
          \hbox{}\newpage
        \fi
        \advance\@colN by 1\relax
      }%
    \fi
  \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{%
  \clearpage
  \if@twoside
    \ifodd\c@page
    \else
      \hbox{}%
      \clearpage
    \fi
  \fi
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\newpage}
% Modify the definition of \cs{newpage} so that it sets the
% "usedframebreak" flag.
%\changes{1.14}{2012-11-10}{Modified definition of \cs{newpage}}
%    \begin{macrocode}
\preto\newpage{\global\usedframebreaktrue}
%    \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
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\globalnormalmargin}
%    \begin{macrocode}
\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}%
%    \end{macrocode}
% Page exclusion list:
%\changes{1.14}{2012-11-10}{added page exclusion list}
%    \begin{macrocode}
  \expandafter
    \gdef\csname @ff@xpages@\romannumeral\c@maxflow\endcsname{}%
  \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\relax
            \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
%    \end{macrocode}
% Break out of loop
%    \begin{macrocode}
      \@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}
% Exclusion list:
%    \begin{macrocode}
\define@key{flowframe}{excludepages}%
{%
  \def\ff@xpages{#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@choicekey{flowframe}{margin}{left,right,inner,outer}%
{%
  \def\ff@margin{#1}%
}
%    \end{macrocode}
% This key is only for \glspl{static}:
%    \begin{macrocode}
\define@choicekey{flowframe}{clear}{true,false}[true]{%
  \def\ff@clear{#1}%
}
%    \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@choicekey{flowframe}{valign}{c,t,b}%
{%
  \def\ff@valign{#1}%
}
%    \end{macrocode}
% This key is only for \glspl{static} and \glspl{dynamic}:
%\changes{2014-06-04}{1.16}{added `hide' and `hidethis' keys}
%    \begin{macrocode}
\define@choicekey{flowframe}{hide}{true,false}[true]{%
  \def\ff@hide{#1}%
}
%    \end{macrocode}
% This key is only for \glspl{static} and \glspl{dynamic}:
%    \begin{macrocode}
\define@choicekey{flowframe}{hidethis}{true,false}[true]{%
  \def\ff@hidethis{#1}%
}
%    \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\relax
  \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\relax
      }%
      {%
        \@colN=2\relax
      }%
      \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@hide{}\def\ff@hidethis{}%
  \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{}%
  \let\ff@xpages\undefined
  \let\ff@shape\undefined
  \setkeys{flowframe}{#2}%
  \ifdefempty{\ff@frame}{}%
  {%
    \setboolean{columnframe\romannumeral#1}{\ff@frame}%
  }%
  \ifdefempty{\ff@width}{}%
  {%
    \expandafter
      \setlength\csname colwidth\romannumeral#1\endcsname
      {\ff@width}%
  }%
  \ifdefempty{\ff@height}{}%
  {%
    \expandafter
      \setlength\csname colheight\romannumeral#1\endcsname
      {\ff@height}%
  }%
  \ifdefempty{\ff@x}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posx\endcsname
      {\ff@x}%
    \expandafter
      \setlength\csname col@\romannumeral#1@evenx\endcsname
      {\ff@x}%
  }
  \ifdefempty{\ff@y}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posy\endcsname
      {\ff@y}%
    \expandafter
      \setlength\csname col@\romannumeral#1@eveny\endcsname
      {\ff@y}%
  }%
  \ifdefempty{\ff@evenx}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@evenx\endcsname
      {\ff@evenx}%
  }%
  \ifdefempty{\ff@eveny}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@eveny\endcsname
      {\ff@eveny}%
  }%
  \ifdefempty{\ff@oddx}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posx\endcsname
      {\ff@oddx}%
  }%
  \ifdefempty{\ff@oddy}{}%
  {%
    \expandafter
      \setlength\csname col@\romannumeral#1@posy\endcsname
      {\ff@oddy}%
  }%
  \ifdefempty{\ff@label}{}%
  {%
    \@s@tflowframeid{#1}[\ff@label]%
  }%
  \ifdefempty{\ff@frametype}{}%
  {%
    \expandafter
      \edef\csname @ff@frametype@\romannumeral#1\endcsname{%
        \ff@frametype}%
  }%
  \ifdefempty{\ff@col}{}%
  {%
    \expandafter\@setframecol\ff@col\end{#1}{col}{ff}%
  }%
  \ifdefempty{\ff@txtcol}{}%
  {%
    \expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{ff}%
  }%
  \ifdefempty{\ff@backcol}{}%
  {%
    \expandafter\@setframecol\ff@backcol\end{#1}{backcol}{ff}%
  }%
  \ifdefempty{\ff@margin}{}%
  {%
    \expandafter
      \xdef\csname @ff@margin@\romannumeral#1\endcsname{%
        \ff@margin}%
  }%
  \ifdefempty{\ff@pages}{}%
  {%
    \flowsetpagelist{#1}{\ff@pages}%
  }%
  \ifundef{\ff@xpages}{}%
  {%
    \flowsetexclusion{#1}{\ff@xpages}%
  }%
  \ifdefempty{\ff@offset}{}%
  {%
    \expandafter
      \xdef\csname @ff@offset@\romannumeral#1\endcsname{%
        \ff@offset}%
  }%
  \ifdefempty{\ff@angle}{}%
  {%
    \expandafter
      \xdef\csname @ff@angle@\romannumeral#1\endcsname{%
        \ff@angle}%
  }%
  \ifdefempty{\ff@clear}{}%
  {%
    \PackageError{flowfram}%
      {Key 'clear' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@style}{}%
  {%
    \PackageError{flowfram}%
      {Key 'style' not available for flow frames}{}%
  }%
  \ifundef{\ff@shape}{}%
  {%
    \PackageError{flowfram}%
    {Key 'shape' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@valign}{}%
  {%
    \PackageError{flowfram}%
    {Key 'valign' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@hide}{}%
  {%
    \PackageError{flowfram}%
      {Key 'hide' not available for flow frames}{}%
  }%
  \ifdefempty{\ff@hidethis}{}%
  {%
    \PackageError{flowfram}%
      {Key 'hidethis' not available for flow frames}{}%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowsetpagelist}
% Sets the page list for the \gls{flow} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\flowsetpagelist}[2]{%
  \expandafter
    \xdef\csname @ff@pages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting page range for flow frame
    \number#1\space\space to "#2"}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowsetexclusion}
% Sets the exclusion list for the \gls{flow} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\flowsetexclusion}[2]{%
  \expandafter
    \xdef\csname @ff@xpages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting exclusion for flow frame
    \number#1\space\space to "#2"}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\flowaddexclusion}
% Adds to the exclusion list for the \gls{flow} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\flowaddexclusion}[2]{%
  \ifcsempty{@ff@xpages@\romannumeral#1}
  {%
    \expandafter
      \xdef\csname @ff@xpages@\romannumeral#1\endcsname{#2}%
  }%
  {%
    \expandafter
      \xdef\csname @ff@xpages@\romannumeral#1\endcsname{%
       \csname @ff@xpages@\romannumeral#1\endcsname,#2}%
  }%
  \flf@message{Setting exclusion for flow frame
    \number#1\space\space to 
    "\csname @ff@xpages@\romannumeral#1\endcsname"}%
}
%    \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{100000}%
        \@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}%
%    \end{macrocode}
% Page exclusion list:
%\changes{1.14}{2012-11-10}{added page exclusion list}
%    \begin{macrocode}
  \expandafter
    \gdef\csname @sf@xpages@\romannumeral\c@maxflow\endcsname{}%
  \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}
%    \end{macrocode}
%\changes{2014-06-04}{1.16}{added `hide' and `hidethis' attributes}
%    \begin{macrocode}
  \newboolean{@sf@hide@\romannumeral\c@maxstatic}%
  \setboolean{@sf@hide@\romannumeral\c@maxstatic}{false}%
  \newboolean{@sf@hidethis@\romannumeral\c@maxstatic}%
  \setboolean{@sf@hidethis@\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
%    \end{macrocode}
% Break out of loop
%    \begin{macrocode}
      \@colN=\c@maxstatic
    }%
    {}%
  }%
  \ifnum\ff@id=0\relax
    \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\relax
  \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@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@hide{}\def\ff@hidethis{}%
  \let\ff@shape\undefined
  \let\ff@xpages\undefined
  \setkeys{flowframe}{#2}%
  \ifdefempty{\ff@frame}{}%
  {%
    \setboolean{staticframe\romannumeral#1}{\ff@frame}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\ff@evenx}{}%
  {%
    \expandafter\global\expandafter
      \setlength\csname @sf@\romannumeral#1@evenx\endcsname
        {\ff@evenx}%
  }%
  \ifdefempty{\ff@eveny}{}%
  {%
    \expandafter\global\expandafter
      \setlength\csname @sf@\romannumeral#1@eveny\endcsname
      {\ff@eveny}%
  }%
  \ifdefempty{\ff@oddx}{}%
  {%
    \expandafter\global\expandafter
      \setlength\csname @sf@\romannumeral#1@posx\endcsname
      {\ff@oddx}%
  }%
  \ifdefempty{\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}}%
  \ifdefempty{\ff@frametype}{}%
  {%
    \expandafter
      \xdef\csname @sf@frametype@\romannumeral#1\endcsname{%
        \ff@frametype}%
  }%
  \ifdefempty{\ff@label}{}%
  {%
    \@s@tstaticframeid{#1}[\ff@label]%
  }
  \ifdefempty{\ff@col}{}%
  {%
    \expandafter\@setframecol\ff@col\end{#1}{col}{sf}%
  }%
  \ifdefempty{\ff@txtcol}{}%
  {%
    \expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{sf}%
  }%
  \ifdefempty{\ff@backcol}{}%
  {%
    \expandafter\@setframecol\ff@backcol\end{#1}{backcol}{sf}%
  }%
  \ifdefempty{\ff@offset}{}%
  {%
    \expandafter
      \xdef\csname @sf@offset@\romannumeral#1\endcsname{\ff@offset}%
  }%
  \ifdefempty{\ff@angle}{}%
  {%
    \expandafter
      \xdef\csname @sf@angle@\romannumeral#1\endcsname{\ff@angle}%
  }%
  \ifundef{\ff@shape}{}%
  {%
    \expandafter\global\expandafter
      \let\csname @sf@shape@\romannumeral#1\endcsname\ff@shape
  }%
  \ifdefempty{\ff@pages}{}%
  {%
     \staticsetpagelist{#1}{\ff@pages}%
  }%
  \ifundef{\ff@xpages}{}%
  {%
     \staticsetexclusion{#1}{\ff@xpages}%
  }%
  \ifdefempty{\ff@hide}{}%
  {%
    \setboolean{@sf@hide@\romannumeral#1}{\ff@hide}%
  }%
  \ifdefempty{\ff@hidethis}{}%
  {%
    \global\csletcs{if@sf@hidethis@\romannumeral#1}{if\ff@hidethis}%
  }%
  \ifdefempty{\ff@clear}{}%
  {%
    \setboolean{@sf@clear@\romannumeral#1}{\ff@clear}%
  }%
  \ifdefempty{\ff@margin}{}%
  {%
    \PackageError{flowfram}%
    {Key 'margin' not available for static frames}%
    {Static frames don't have marginal notes}%
  }%
  \ifdefempty{\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{%
  \ifdefequal{#1}{\parshape}%
  {%
    \def\ff@shape{1}%
  }%
  {%
    \ifdefequal{#1}{\shapepar}%
    {%
      \def\ff@shape{2}%
    }%
    {%
%    \end{macrocode}
%\changes{1.15}{2014-05-15}{added check for \cs{Shapepar}}
%    \begin{macrocode}
       \ifdefequal{#1}{\Shapepar}%
       {%
         \def\ff@shape{2}%
       }%
       {%
         \ifx#1\relax
           \def\ff@shape{0}%
         \else
           \PackageError{flowfram}{Unknown shape \string#1}{}%
           \def\ff@shape{2}%
         \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
%    \end{macrocode}
% no shape:
%    \begin{macrocode}
    \edef\@sf@mpg{%
      \noexpand
      \begin{minipage}\csname @sf@dim@\romannumeral#1\endcsname
        \noexpand\begingroup
        \noexpand\let\noexpand\FLForgpar=\noexpand\par
    }%
  \or
%    \end{macrocode}
% \cs{parshape}:
%    \begin{macrocode}
    \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
%    \end{macrocode}
% \cs{shapepar} or \cs{Shapepar}:
%    \begin{macrocode}
    \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\relax
    \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}{\staticsetpagelist}
% Sets the page list for the \gls{static} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\staticsetpagelist}[2]{%
  \expandafter
    \xdef\csname @sf@pages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting page range for static frame
    \number#1\space\space to "#2"}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticsetexclusion}
% Sets the exclusion list for the \gls{static} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\staticsetexclusion}[2]{%
  \expandafter
    \xdef\csname @sf@xpages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting exclusion for static frame
    \number#1\space\space to "#2"}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\staticaddexclusion}
% Adds to the exclusion list for the \gls{static} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\staticaddexclusion}[2]{%
  \ifcsempty{@sf@xpages@\romannumeral#1}
  {%
    \expandafter
      \xdef\csname @sf@xpages@\romannumeral#1\endcsname{#2}%
  }%
  {%
    \expandafter
      \xdef\csname @sf@xpages@\romannumeral#1\endcsname{%
       \csname @sf@xpages@\romannumeral#1\endcsname,#2}%
  }%
  \flf@message{Setting exclusion for static frame
    \number#1\space\space to 
    "\csname @sf@xpages@\romannumeral#1\endcsname"}%
}
%    \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{100000}%
        \@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}%
%    \end{macrocode}
% Page exclusion list:
%\changes{1.14}{2012-11-10}{added page exclusion list}
%    \begin{macrocode}
  \expandafter
    \gdef\csname @df@xpages@\romannumeral\c@maxflow\endcsname{}%
  \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}%
%    \end{macrocode}
%\changes{1.16}{2014-06-04}{added `hide' and `hidethis' attributes}
%    \begin{macrocode}
  \newboolean{@df@hide@\romannumeral\c@maxdynamic}%
  \setboolean{@df@hide@\romannumeral\c@maxdynamic}{false}%
  \newboolean{@df@hidethis@\romannumeral\c@maxdynamic}%
  \setboolean{@df@hidethis@\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
%    \end{macrocode}
% Break out of loop
%    \begin{macrocode}
      \@colN=\c@maxdynamic
    }%
    {}%
  }%
  \ifnum\ff@id=0\relax
    \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\relax
  \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@hide{}\def\ff@hidethis{}%
  \let\ff@shape\undefined
  \let\ff@xpages\undefined
  \setkeys{flowframe}{#2}%
  \ifdefempty{\ff@frame}%
  {}%
  {%
    \setboolean{dynamicframe\romannumeral#1}{\ff@frame}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\ff@evenx}%
  {}%
  {%
    \expandafter\global\expandafter\setlength
      \csname @df@\romannumeral#1@evenx\endcsname{\ff@evenx}%
  }%
  \ifdefempty{\ff@eveny}%
  {}%
  {%
    \expandafter\global\expandafter\setlength
      \csname @df@\romannumeral#1@eveny\endcsname{\ff@eveny}%
  }%
  \ifdefempty{\ff@oddx}%
  {}%
  {%
    \expandafter\global\expandafter\setlength
      \csname @df@\romannumeral#1@posx\endcsname{\ff@oddx}%
  }%
  \ifdefempty{\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}%
  }%
  \ifdefempty{\ff@label}%
  {}%
  {%
    \@s@tdynamicframeid{#1}[\ff@label]%
  }%
  \ifdefempty{\ff@frametype}%
  {}%
  {%
    \expandafter
      \xdef\csname @df@frametype@\romannumeral#1\endcsname{%
        \ff@frametype
      }%
  }%
  \ifdefempty{\ff@col}%
  {}%
  {%
    \expandafter\@setframecol\ff@col\end{#1}{col}{df}%
  }%
  \ifdefempty{\ff@txtcol}%
  {}%
  {%
    \expandafter\@setframecol\ff@txtcol\end{#1}{txtcol}{df}%
  }%
  \ifdefempty{\ff@backcol}%
  {}%
  {%
    \expandafter\@setframecol\ff@backcol\end{#1}{backcol}{df}%
  }%
  \ifdefempty{\ff@offset}%
  {}%
  {%
    \expandafter
      \xdef\csname @df@offset@\romannumeral#1\endcsname{\ff@offset}%
  }%
  \ifdefempty{\ff@angle}%
  {}%
  {%
    \expandafter
      \xdef\csname @df@angle@\romannumeral#1\endcsname{\ff@angle}%
  }%
  \ifundef{\ff@shape}{}%
  {%
    \expandafter\global\expandafter
      \let\csname @df@shape@\romannumeral#1\endcsname\ff@shape
  }%
  \ifdefempty{\ff@pages}%
  {}%
  {%
    \dynamicsetpagelist{#1}{\ff@pages}%
  }%
  \ifundef{\ff@xpages}{}%
  {%
    \dynamicsetexclusion{#1}{\ff@xpages}%
  }%
  \ifdefempty{\ff@style}%
  {}%
  {%
    \ifcsundef{\ff@style}%
    {%
      \PackageError{flowfram}%
      {Unknown style '\ff@style'}%
      {%
        The command \expandafter\@gobble\string\\\ff@style
        \space has not been defined%
      }%
    }%
    {%
      \expandafter
        \xdef\csname @df@style@\romannumeral#1\endcsname{\ff@style}%
    }%
  }%
  \ifdefempty{\ff@clear}%
  {}%
  {%
    \setboolean{@df@clear@\romannumeral#1}{\ff@clear}%
  }%
  \ifdefempty{\ff@margin}%
  {}%
  {%
    \PackageError{flowfram}%
    {%
      Key 'margin' not available for dynamic frames%
    }%
    {dynamic frames don't have marginal notes}%
  }%
  \ifdefempty{\ff@hide}{}%
  {%
    \setboolean{@df@hide@\romannumeral#1}{\ff@hide}%
  }%
  \ifdefempty{\ff@hidethis}{}%
  {%
    \global\csletcs{if@df@hidethis@\romannumeral#1}{if\ff@hidethis}%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicsetpagelist}
% Sets the page list for the \gls{dynamic} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\dynamicsetpagelist}[2]{%
  \expandafter
    \xdef\csname @df@pages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting page range for dynamic frame
    \number#1\space\space to "#2"}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicsetexclusion}
% Sets the exclusion list for the \gls{dynamic} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\dynamicsetexclusion}[2]{%
  \expandafter
    \xdef\csname @df@xpages@\romannumeral#1\endcsname{#2}%
  \flf@message{Setting exclusion for dynamic frame
    \number#1\space\space to "#2"}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\dynamicaddexclusion}
% Adds to the exclusion list for the \gls{dynamic} given by "#1" (the
% \gls{idn}).
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newcommand*{\dynamicaddexclusion}[2]{%
  \ifcsempty{@df@xpages@\romannumeral#1}
  {%
    \expandafter
      \xdef\csname @df@xpages@\romannumeral#1\endcsname{#2}%
  }%
  {%
    \expandafter
      \xdef\csname @df@xpages@\romannumeral#1\endcsname{%
       \csname @df@xpages@\romannumeral#1\endcsname,#2}%
  }%
  \flf@message{Setting exclusion for dynamic frame
    \number#1\space\space to 
    "\csname @df@xpages@\romannumeral#1\endcsname"}%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@@dynamicframeswapcoords}
% Swap odd and even offsets for a given \gls{dynamic}. Do the main stuff for 
% a given \gls{dynamic} \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 (or 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}%
%    \end{macrocode}
%\cs{ff@id} is the IDN
%    \begin{macrocode}
    \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 
%    \end{macrocode}
% Flow frame
%    \begin{macrocode}
    \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
%    \end{macrocode}
% Static frame
%    \begin{macrocode}
    \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 
%    \end{macrocode}
% Dynamic frame
%    \begin{macrocode}
    \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 
%    \end{macrocode}
% Flow frame
%    \begin{macrocode}
    \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
%    \end{macrocode}
% Static frame
%    \begin{macrocode}
    \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 
%    \end{macrocode}
% Dynamic frame
%    \begin{macrocode}
    \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.
%
%\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}
%\changes{1.14}{2012-11-10}{removed unwanted spaces}
%\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}
%\changes{1.14}{2012-11-10}{removed unwanted spaces}
%\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}
%\changes{1.14}{2012-11-10}{removed unwanted spaces}
%\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 compatibility, 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[\@ff@pages@countreg]{\@ff@staticH}%
    \c@thisframe=\c@maxflow
    \advance\c@thisframe by -1\relax
    \@twocolumn[>\@ff@pages@countreg]%
      \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 compatibility, 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[\@ff@pages@countreg]{\@ff@staticH}%
    \c@thisframe=\c@maxflow
    \advance\c@thisframe by -1\relax
    \@onecolumn[>\@ff@pages@countreg]%
    \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{%
  \c@absolutepage=1\relax
  \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}
%
%\subsection{Output Routine}
%
%\begin{macro}{\fftolerance}
% The \sty{flowfram} package does a check to see if text has
% flowed between frames of different widths, which will cause a
% discrepancy in the line widths of the paragraph spanning the break.
% Before version~1.14, the output routine just checked if the widths
% were different, but this means that warning messages will be
% generated even if there's only a tiny difference that can be
% caused by rounding errors (for example, if the frames were created
% using jpgfdraw). So add a tolerance and only complain if the
% difference exceeds this value.
%\changes{1.14}{2012-11-10}{new}
%    \begin{macrocode}
\newlength\fftolerance
\setlength\fftolerance{2pt}
%    \end{macrocode}
%\end{macro}
%
%\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}
%\changes{1.14}{2012-11-10}{changed check to use tolerance rather
%than testing if hsize and columnwidth are equal}
%    \begin{macrocode}
\newcommand{\@setcol}[1]{%
  \ifnum\c@maxflow<#1\relax
    \PackageError{flowfram}%
    {Can't set frame '\number#1', doesn't exist}{}%
  \else
    \flf@message{Switching to flow frame \number#1\space on page
      \number\@ff@pages@countreg}%
    \expandafter\global\expandafter\columnwidth
     \csname colwidth\romannumeral#1\endcsname
    \dimen@\columnwidth
    \advance\dimen@ by -\hsize\relax
    \ifdim\dimen@<0pt\relax
      \dimen@=-\dimen@
    \fi
    \ifdim\dimen@>\fftolerance
      \ifusedframebreak
      \else
        \PackageWarning{flowfram}%
        {Moving to flow frame of unequal
        width,\MessageBreak use of \string\framebreak\space advised, 
        or text might not appear correctly (difference =
        \the\dimen@, tolerance = \the\fftolerance)}%
      \fi
    \fi
    \global\usedframebreakfalse
    \global\hsize\columnwidth
    \expandafter\global
    \expandafter\vsize\csname colheight\romannumeral#1\endcsname
    \global\@colht\vsize
    \global\@colroom\@colht
%    \end{macrocode}
% We may be inside an environment that has modified the line
% width, such as one of the list environments so we can't just set
% \cs{linewidth} to \cs{columnwidth}. Test if we're in a list
% environment by checking if \cs{@listdepth} is greater than 0. If
% true,  only modify \cs{linewidth} if
% it's larger than the new column width.
%\changes{1.15}{2014-05-15}{set \cs{linewidth} as well as \cs{textwidth}}
%\changes{1.17}{2014-09-30}{added check for list}
%    \begin{macrocode}
    \ifnum\@listdepth>0\relax
      \ifnum\linewidth>\columnwidth
        \global\linewidth\columnwidth
      \fi
    \else
      \global\linewidth\columnwidth
    \fi
%    \end{macrocode}
%\changes{1.16}{2014-06-04}{Removed assignment of \cs{textwidth}}
%    \begin{macrocode}
    %\global\textwidth\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}%
%    \end{macrocode}
% Also increment absolutepage counter.
%\changes{1.14}{2012-11-10}{added absolutepage increment}
%    \begin{macrocode}
    \stepcounter{absolutepage}%
    \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}{%
%    \end{macrocode}
% create dynamic frames at the standard location
%    \begin{macrocode}
  \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
%    \end{macrocode}
% Skip if this page is in this frame's exclusion list.
%\changes{1.14}{2012-11-10}{added check for exclusion list}
%    \begin{macrocode}
    \edef\ff@xpages{\csname @ff@xpages@\romannumeral\@colN\endcsname}%
    \@for\@ff@pp:=\ff@xpages\do
    {%
      \ifnum0\@ff@pp=\@ff@pages@countreg\relax
        \@endfortrue
      \fi
    }%
    \if@endfor
%    \end{macrocode}
% If for loop was terminated prematurely, then this page is in this
% frame's exclusion list.
%    \begin{macrocode}
    \else
      \edef\ff@pages{\csname @ff@pages@\romannumeral\@colN\endcsname}%
      \@ff@checkpages{\ff@pages}%
%    \end{macrocode}
% If found a frame, break out of loop.
%    \begin{macrocode}
      \if@ff@moreframes
        \@colN=\c@maxflow\relax
      \fi
    \fi
  }%
  \if@ff@moreframes
  \else
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
    \@ff@tmpN=\@ff@pages@countreg
%    \end{macrocode}
% Look ahead up to a maximum of 4 pages.
%    \begin{macrocode}
    \count@=0\relax
    \loop
      \advance\@ff@tmpN by 1\relax
      \@colN=0\relax
      \whiledo{\@colN<\c@maxflow}%
      {%
        \advance\@colN by 1\relax
%    \end{macrocode}
% Skip if page is in this frame's exclusion list.
%    \begin{macrocode}
        \edef\ff@xpages{\csname @ff@xpages@\romannumeral\@colN\endcsname}%
        \@for\@ff@pp:=\ff@xpages\do
        {%
          \ifnum0\@ff@pp=\@ff@tmpN\relax
            \@endfortrue
          \fi
        }%
        \if@endfor
%    \end{macrocode}
% If for loop was terminated prematurely, then page is in this
% frame's exclusion list.
%    \begin{macrocode}
        \else
          \edef\ff@pages{\csname @ff@pages@\romannumeral\@colN\endcsname}%
          \@ff@checkpages[\@ff@tmpN]{\ff@pages}%
%    \end{macrocode}
% If found a frame, break out of loop.
%    \begin{macrocode}
          \if@ff@moreframes
            \@colN=\c@maxflow\relax
          \fi
        \fi
      }%
      \if@ff@moreframes
        \count@=4\relax
      \else
        \advance\count@ by 1\relax
      \fi
    \ifnum\count@<4
    \repeat
  \fi
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@ff@checkpages}
% Check to see if the current page lies in the \gls{pglist}
% given by "#1".
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
\newcommand*{\@ff@checkpages}[2][\@ff@pages@countreg]{%
  \@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{100000}%
  \@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 "100000" 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{100000}%
}
%    \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}{\@ff@output@adjustframes}
%\changes{1.14}{2012-11-10}{new}
% Provide a hook to adjust frame settings in the output routine.
%    \begin{macrocode}
\newcommand*{\@ff@output@adjustframes}{}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowswitchonnext}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed flow frames from the next page onwards
%    \begin{macrocode}
\newcommand*{\flowswitchonnext}{%
  \@ifstar\@sflowswitchonnext\@flowswitchonnext
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchonnext}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnext}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}%
           {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowswitchonnextodd}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed flow frames from the next odd page onwards
%    \begin{macrocode}
\newcommand*{\flowswitchonnextodd}{%
  \@ifstar\@sflowswitchonnextodd\@flowswitchonnextodd
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchonnextodd}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \@ff@chckifthispg{\count@}{\ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnextodd}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \@ff@chckifthispg{\count@}{\@ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowswitchoffnext}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed flow frames from the next page onwards
%    \begin{macrocode}
\newcommand*{\flowswitchoffnext}{%
  \@ifstar\@sflowswitchoffnext\@flowswitchoffnext
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchoffnext}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnext}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowswitchoffnextodd}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed flow frames from the next odd page onwards
%    \begin{macrocode}
\newcommand*{\flowswitchoffnextodd}{%
  \@ifstar\@sflowswitchoffnextodd\@flowswitchoffnextodd
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchoffnextodd}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \if@notthiscol
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
        \def\@ff@nextpages{none}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
          \def\@ff@nextpages{none}%
        \else
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}{\@ff@nextpages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnextodd}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \if@notthiscol
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
        \def\@ff@nextpages{none}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
          \def\@ff@nextpages{none}%
        \else
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}{\@ff@nextpages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowswitchonnextonly}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed flow frames for just the next page
%    \begin{macrocode}
\newcommand*{\flowswitchonnextonly}{%
  \@ifstar\@sflowswitchonnextonly\@flowswitchonnextonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchonnextonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}{\number\count@}%
      }%
    \else
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnextonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}{\number\count@}%
      }%
    \else
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\flowsetpagelist{\number\@ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowswitchonnextoddonly}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed flow frames for just the next odd page
%    \begin{macrocode}
\newcommand*{\flowswitchonnextoddonly}{%
  \@ifstar\@sflowswitchonnextoddonly\@flowswitchonnextoddonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchonnextoddonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\ff@id}%
    \if@notthiscol
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchonnextoddonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@ff@chckifthispg{\@ff@pages@countreg}{\@ff@id}%
    \if@notthiscol
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@ff@chckifthispg{\count@}{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%
%\begin{macro}{\flowswitchoffnextonly}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed flow frames for just the next page
%    \begin{macrocode}
\newcommand*{\flowswitchoffnextonly}{%
  \@ifstar\@sflowswitchoffnextonly\@flowswitchoffnextonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchoffnextonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnextonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\flowswitchoffnextoddonly}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed flow frames for just the next odd page
%    \begin{macrocode}
\newcommand*{\flowswitchoffnextoddonly}{%
  \@ifstar\@sflowswitchoffnextoddonly\@flowswitchoffnextoddonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sflowswitchoffnextoddonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sflowswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@flowframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@flowswitchoffnextoddonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@flowswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\flowaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnext}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed dynamic frames from the next page onwards
%    \begin{macrocode}
\newcommand*{\dynamicswitchonnext}{%
  \@ifstar\@sdynamicswitchonnext\@dynamicswitchonnext
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchonnext}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnext}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}%
           {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnextodd}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed dynamic frames from the next odd page onwards
%    \begin{macrocode}
\newcommand*{\dynamicswitchonnextodd}{%
  \@ifstar\@sdynamicswitchonnextodd\@dynamicswitchonnextodd
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchonnextodd}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \@df@chckifthispg[\count@]{\ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnextodd}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \@df@chckifthispg[\count@]{\@ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicswitchoffnext}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed dynamic frames from the next page onwards
%    \begin{macrocode}
\newcommand*{\dynamicswitchoffnext}{%
  \@ifstar\@sdynamicswitchoffnext\@dynamicswitchoffnext
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchoffnext}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnext}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicswitchoffnextodd}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed dynamic frames from the next odd page onwards
%    \begin{macrocode}
\newcommand*{\dynamicswitchoffnextodd}{%
  \@ifstar\@sdynamicswitchoffnextodd\@dynamicswitchoffnextodd
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchoffnextodd}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
        \def\@ff@nextpages{none}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
          \def\@ff@nextpages{none}%
        \else
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}{\@ff@nextpages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnextodd}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
        \def\@ff@nextpages{none}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
          \def\@ff@nextpages{none}%
        \else
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}{\@ff@nextpages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnextonly}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed dynamic frames for just the next page
%    \begin{macrocode}
\newcommand*{\dynamicswitchonnextonly}{%
  \@ifstar\@sdynamicswitchonnextonly\@dynamicswitchonnextonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchonnextonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}{\number\count@}%
      }%
    \else
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnextonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}{\number\count@}%
      }%
    \else
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\dynamicsetpagelist{\number\@ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicswitchonnextoddonly}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed dynamic frames for just the next odd page
%    \begin{macrocode}
\newcommand*{\dynamicswitchonnextoddonly}{%
  \@ifstar\@sdynamicswitchonnextoddonly\@dynamicswitchonnextoddonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchonnextoddonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchonnextoddonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@df@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@df@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%
%\begin{macro}{\dynamicswitchoffnextonly}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed dynamic frames for just the next page
%    \begin{macrocode}
\newcommand*{\dynamicswitchoffnextonly}{%
  \@ifstar\@sdynamicswitchoffnextonly\@dynamicswitchoffnextonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchoffnextonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnextonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\dynamicswitchoffnextoddonly}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed dynamic frames for just the next odd page
%    \begin{macrocode}
\newcommand*{\dynamicswitchoffnextoddonly}{%
  \@ifstar\@sdynamicswitchoffnextoddonly\@dynamicswitchoffnextoddonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sdynamicswitchoffnextoddonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sdynamicswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@dynamicframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@dynamicswitchoffnextoddonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@dynamicswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\dynamicaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticswitchonnext}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed static frames from the next page onwards
%    \begin{macrocode}
\newcommand*{\staticswitchonnext}{%
  \@ifstar\@sstaticswitchonnext\@staticswitchonnext
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchonnext}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnext}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchonnext}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}{>\number\@ff@pages@countreg}%
      }%
    \else
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}%
           {\number\@ff@pages@countreg,>\number\@ff@pages@countreg}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticswitchonnextodd}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed static frames from the next odd page onwards
%    \begin{macrocode}
\newcommand*{\staticswitchonnextodd}{%
  \@ifstar\@sstaticswitchonnextodd\@staticswitchonnextodd
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchonnextodd}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \@sf@chckifthispg[\count@]{\ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnextodd}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchonnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\count@\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \def\@ff@prepages{}%
    \if@notthiscol
    \else
       \def\@ff@prepages{\number\@ff@pages@countreg,}%
    \fi
%    \end{macrocode}
% Is this frame already switched on for the next page?
%    \begin{macrocode}
    \@sf@chckifthispg[\count@]{\@ff@id}%
    \ifnum\count@=\@ff@pages@countreg\relax
    \else
      \if@notthiscol
      \else
         \edef\@ff@prepages{\@ff@prepages\number\count@,}%
      \fi
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}%
        {\@ff@prepages>\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticswitchoffnext}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed static frames from the next page onwards
%    \begin{macrocode}
\newcommand*{\staticswitchoffnext}{%
  \@ifstar\@sstaticswitchoffnext\@staticswitchoffnext
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchoffnext}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnext}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchoffnext}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
       \def\@ff@pages{none}%
    \else
       \def\@ff@pages{\number\@ff@pages@countreg}%
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticswitchoffnextodd}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed static frames from the next odd page onwards
%    \begin{macrocode}
\newcommand*{\staticswitchoffnextodd}{%
  \@ifstar\@sstaticswitchoffnextodd\@staticswitchoffnextodd
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchoffnextodd}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
        \def\@ff@nextpages{none}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
          \def\@ff@nextpages{none}%
        \else
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}{\@ff@nextpages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnextodd}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchoffnextodd}[1]{%
  \count@=\@ff@pages@countreg\relax
  \ifodd\@ff@pages@countreg\relax
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already off on this page?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
%    \end{macrocode}
% It's off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is off on this page, so set to
% none.
%    \begin{macrocode}
        \def\@ff@nextpages{none}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page as well, so set to none.
%    \begin{macrocode}
          \def\@ff@nextpages{none}%
        \else
%    \end{macrocode}
% Not off on the next page, so set to next page only.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\count@}%
        \fi
      \fi
    \else
%    \end{macrocode}
% It's not off on this page. Is it on or off on the next page, if this
% page is odd? First, is this page odd?
%    \begin{macrocode}
      \ifnum\@ff@pages@countreg=\count@\relax
%    \end{macrocode}
% This page is even and the frame is not off on this page, so set to
% this page.
%    \begin{macrocode}
        \def\@ff@nextpages{\number\@ff@pages@countreg}%
      \else
%    \end{macrocode}
% This page is odd. Is the frame on or off on the next page?
%    \begin{macrocode}
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Off on the next page but not off on this page. So set to just this
% page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg}%
        \else
%    \end{macrocode}
% Not off on the next page as well, so set to this page and next page.
%    \begin{macrocode}
          \def\@ff@nextpages{\number\@ff@pages@countreg,\number\count@}%
        \fi
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}{\@ff@nextpages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticswitchonnextonly}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed static frames for just the next page
%    \begin{macrocode}
\newcommand*{\staticswitchonnextonly}{%
  \@ifstar\@sstaticswitchonnextonly\@staticswitchonnextonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchonnextonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}{\number\count@}%
      }%
    \else
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnextonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchonnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \if@notthiscol
%    \end{macrocode}
% Not, it isn't, so just set to the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}{\number\count@}%
      }%
    \else
%    \end{macrocode}
% Yes, it is, so set to this page and the next page:
%    \begin{macrocode}
      \xdef\@ff@output@adjustframes{%
        \the\toks@
        \noexpand\staticsetpagelist{\number\@ff@id}%
          {\number\@ff@pages@countreg,\number\count@}%
      }%
    \fi
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticswitchonnextoddonly}
%\changes{1.14}{2012-11-10}{new}
% Switch on the listed static frames for just the next odd page
%    \begin{macrocode}
\newcommand*{\staticswitchonnextoddonly}{%
  \@ifstar\@sstaticswitchonnextoddonly\@staticswitchonnextoddonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchonnextoddonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\ff@id}%
    \if@notthiscol
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchonnextoddonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchonnextoddonly}[1]{%
  \@for\@ff@id:=#1\do{%
%    \end{macrocode}
% Is this frame already on?
%    \begin{macrocode}
    \@sf@chckifthispg[\@ff@pages@countreg]{\@ff@id}%
    \if@notthiscol
%    \end{macrocode}
% No, it isn't. If this is an odd page, is it on or off on the next
% page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. So this frame isn't on this page, but is it on or
% off on the next page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% It's not switched on either on this (odd) page or the next (even) page. So
% the page list should be just the next odd page after this one.
%    \begin{macrocode}
         \advance\count@ by 1\relax
         \edef\@ff@pages{\number\count@}%
        \else
%    \end{macrocode}
% It's not switched on for this (odd) page but it is for the next (even) page. So
% the page list should be the next even and odd pages after this
% page.
%    \begin{macrocode}
         \edef\@ff@pages{\number\count@}%
         \advance\count@ by 1\relax
         \edef\@ff@pages{\@ff@pages,\number\count@}%
        \fi
      \else
%    \end{macrocode}
% No, it's even. So it's not on this (even) page, but needs to be on
% for the following (odd) page.
%    \begin{macrocode}
       \count@=\@ff@pages@countreg\relax
       \advance\count@ by 1\relax
       \edef\@ff@pages{\number\count@}%
      \fi
    \else
%    \end{macrocode}
% Frame is on this page. If this is an odd page, is it on or off on
% the next page? First, is this an odd page?
%    \begin{macrocode}
      \ifodd\@ff@pages@countreg
%    \end{macrocode}
% Yes, it's odd. Is the frame on or off for the next (even) page?
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \@sf@chckifthispg[\count@]{\@ff@id}%
        \if@notthiscol
%    \end{macrocode}
% Frame is off. So the frame is switched on for this (odd) page but
% is off for the next (even) page. So the page list needs to be this
% (odd) page and the following odd page, skipping the even page in
% between.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
        \else
%    \end{macrocode}
% Frame is on. So the frame is switched on for this (odd) page and 
% the next (even) page. So the page list needs to be this
% (odd) page, the next even page and the following odd page.
%    \begin{macrocode}
          \advance\count@ by 1\relax
          \edef\@ff@pages{\number\@ff@pages@countreg-\number\count@}%
        \fi
      \else
%    \end{macrocode}
% Frame is switched on for this page and this page is even. So the
% page list needs to be this (even) page and the next (odd) page.
%    \begin{macrocode}
        \count@=\@ff@pages@countreg\relax
        \advance\count@ by 1\relax
        \edef\@ff@pages{\number\@ff@pages@countreg,\number\count@}%
      \fi
%    \end{macrocode}
%    \begin{macrocode}
    \fi
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticsetpagelist{\number\@ff@id}{\@ff@pages}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%
%\begin{macro}{\staticswitchoffnextonly}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed static frames for just the next page
%    \begin{macrocode}
\newcommand*{\staticswitchoffnextonly}{%
  \@ifstar\@sstaticswitchoffnextonly\@staticswitchoffnextonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchoffnextonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnextonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchoffnextonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\staticswitchoffnextoddonly}
%\changes{1.14}{2012-11-10}{new}
% Switch off the listed static frames for just the next odd page
%    \begin{macrocode}
\newcommand*{\staticswitchoffnextoddonly}{%
  \@ifstar\@sstaticswitchoffnextoddonly\@staticswitchoffnextoddonly
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@sstaticswitchoffnextoddonly}
% The starred version uses \glspl{idl}.
%    \begin{macrocode}
\newcommand{\@sstaticswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \@staticframeid{\@ff@id}%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\@staticswitchoffnextoddonly}
% The unstarred version uses \glspl{idn}.
%    \begin{macrocode}
\newcommand{\@staticswitchoffnextoddonly}[1]{%
  \count@=\@ff@pages@countreg\relax
  \advance\count@ by 1\relax
  \ifodd\count@\relax
  \else
    \advance\count@ by 1\relax
  \fi
  \@for\@ff@id:=#1\do{%
    \expandafter\toks@\expandafter{\@ff@output@adjustframes}%
    \xdef\@ff@output@adjustframes{%
      \the\toks@
      \noexpand\staticaddexclusion{\number\@ff@id}{\number\count@}%
    }%
  }%
}
%    \end{macrocode}
%\end{macro}
%
%\begin{macro}{\ffaddtoadjustframeshook}
%\changes{1.14}{2012-11-10}{new}
% Add stuff to the output hook.
%    \begin{macrocode}
\newcommand*{\ffaddtoadjustframeshook}[1]{%
  \@ff@addtolist\@ff@output@adjustframes\entry{#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]{%
%    \end{macrocode}
% Do any frame adjustments
%    \begin{macrocode}
  \@ff@output@adjustframes
%    \end{macrocode}
% Now clear the hook
%    \begin{macrocode}
  \global\let\@ff@output@adjustframes\@empty
%    \end{macrocode}
% Now check for any more frames.
%    \begin{macrocode}
  \@ff@checkifmoreframes
  \if@ff@moreframes
  \else
%    \end{macrocode}
% No more frames, add new frame
%    \begin{macrocode}
    \PackageWarning{flowfram}%
    {Run out of flows frames on page \number\@ff@pages@countreg, adding new one}%
    \flf@doifverbose
    {%
      \def\flf@messinfo{Here's the list of flow frames:}%
      \count@=0\relax
      \loop
        \advance\count@ by 1\relax
        \expandafter\toks@\expandafter{\flf@messinfo\MessageBreak}%
        \edef\flf@messinfo{\the\toks@
          \number\count@. 
           Pages: \csname @ff@pages@\romannumeral\count@\endcsname.
           Exclusions: \csname @ff@xpages@\romannumeral\count@\endcsname.
        }%
      \ifnum\count@<\c@maxflow
      \repeat
      \PackageInfo{flowfram}{\flf@messinfo\@gobbletwo}%
    }%
    \@onecolumn
    #1=\c@maxflow
  \fi
  \@notthiscoltrue
  \@ff@nwpgfalse
  \@colN=#1\relax
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \c@curpg=\@ff@pages@countreg
  \loop
    \ifnum\@colN=\c@maxflow
%    \end{macrocode}
% Reached the end of the page. Try the next one.
%    \begin{macrocode}
      \@colN=1\relax
      \@ff@nwpgtrue
      \advance\c@curpg by 1\relax
    \else
%    \end{macrocode}
% Move on to the next flow frame on this page.
%    \begin{macrocode}
      \advance\@colN by 1\relax
    \fi
    \@ff@chckifthispg{\c@curpg}{\@colN}%
  \if@notthiscol
  \repeat
  #1=\@colN\relax
}
%    \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]{%
  \@notthiscolfalse
  \edef\ff@xpages{\csname @ff@xpages@\romannumeral#2\endcsname}%
  \@for\@ff@pp:=\ff@xpages\do
  {%
    \ifnum0\@ff@pp=#1\relax
      \@notthiscoltrue
      \@endfortrue
    \fi
  }%
  \if@notthiscol
  \else
    \@notthiscoltrue
    \edef\ff@pages{\csname @ff@pages@\romannumeral#2\endcsname}%
    \@@ff@chckifthispg{#1}%
  \fi
}
%    \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
        }%
        {%
%    \end{macrocode}
% check through list of page numbers
%    \begin{macrocode}
          \@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 (or the page given by the optional argument).
%\changes{1.14}{2012-11-10}{added optional argument}
%    \begin{macrocode}
\newcommand*{\@sf@chckifthispg}[2][\@ff@pages@countreg]{%
  \@notthiscoltrue
  \edef\ff@pages{\csname @sf@pages@\romannumeral#2\endcsname}%
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \@@ff@chckifthispg{#1}%
}
%    \end{macrocode}
%\end{macro}
%\begin{macro}{\@df@chckifthispg}
% Checks to see if \gls{dynamic} "#1" is defined on the
% current page (or the page given by the optional argument).
%\changes{1.14}{2012-11-10}{added optional argument}
%    \begin{macrocode}
\newcommand*{\@df@chckifthispg}[2][\@ff@pages@countreg]{%
  \@notthiscoltrue
  \edef\ff@pages{\csname @df@pages@\romannumeral#2\endcsname}%
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \@@ff@chckifthispg{#1}%
}
%    \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]{%
  \flf@message{Setting contents of box for flow frame \number#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]{%
  \flf@message{Doing flow frame \number#1\space
    (page \number\@ff@pages@countreg)}%
  \edef\ff@frametype{%
    \csname @ff@frametype@\romannumeral#1\endcsname}%
%    \end{macrocode}
% Frame colour
%    \begin{macrocode}
  \edef\ff@col{\csname @ff@col@\romannumeral#1\endcsname}%
%    \end{macrocode}
% Text colour
%    \begin{macrocode}
  \edef\ff@txtcol{\csname @ff@txtcol@\romannumeral#1\endcsname}%
%    \end{macrocode}
% Background colour
%    \begin{macrocode}
  \edef\ff@backcol{\csname @ff@backcol@\romannumeral#1\endcsname}%
%    \end{macrocode}
% Compute offset for this frame
%    \begin{macrocode}
  \@ff@setoffset{#1}%
%    \end{macrocode}
% Rotate frame if required
%    \begin{macrocode}
  \rotateframe{\csname @ff@angle@\romannumeral#1\endcsname}%
  {%
%    \end{macrocode}
% Check if frame has a border
%    \begin{macrocode}
    \ifthenelse{\boolean{columnframe\romannumeral#1}}%
    {%
%    \end{macrocode}
% Put the required border around the frame
%    \begin{macrocode}
       \@ff@fbox
         {\csname colwidth\romannumeral#1\endcsname}%
         {\csname colheight\romannumeral#1\endcsname}%
         {%
           \expandafter\box\csname column\romannumeral#1\endcsname
         }%
         {%
           \csname\ff@frametype\endcsname
         }%
    }%
    {%
%    \end{macrocode}
% Do the frame without a border
%    \begin{macrocode}
      \@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]{%
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \@ff@chckifthispg{\@ff@pages@countreg}{#1}%
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{added check for non-void box}
%    \begin{macrocode}
  \if@notthiscol
    \expandafter\ifvoid\csname column\romannumeral#1\endcsname
    \else
      \PackageWarning{flowfram}{Box \number#1\space is not void. 
       Dumping. This page: \number\@ff@pages@countreg.
       Page list: "\csname @ff@pages@\romannumeral#1\endcsname".
       Exclusion list: "\csname @ff@xpages@\romannumeral#1\endcsname". 
       (Maybe the page list was changed after this frame was
       selected or maybe you should use package option pages=absolute)}%
      \@notthiscolfalse
    \fi
  \fi
  \if@notthiscol
    \flf@message{Flow frame \number#1\space is not required on page
      \number\@ff@pages@countreg}%
  \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]{%
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with \cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \@ff@chckifthispg{\@ff@pages@countreg}{#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]{%
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \@ff@chckifthispg{\@ff@pages@countreg}{#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]{%
%    \end{macrocode}
%\changes{2014-06-04}{1.16}{added check for `hide' and `hidethis'
%attributes}
% Check the `hide' and `hidethis' attributes
%    \begin{macrocode}
  \ifthenelse{\boolean{@sf@hidethis@\romannumeral#1}}%
  {%
    \@notthiscoltrue
    \global\csletcs{if@sf@hidethis@\romannumeral#1}{iffalse}%
  }%
  {%
    \ifthenelse{\boolean{@sf@hide@\romannumeral#1}}%
    {%
      \@notthiscoltrue
    }%
    {%
%    \end{macrocode}
% Neither `hide' nor `hidethis' have been set so check the page
% list.
%    \begin{macrocode}
      \@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
%    \end{macrocode}
% Has the clear flag been set?
%    \begin{macrocode}
    \ifthenelse{\boolean{@sf@clear@\romannumeral\@colN}}%
    {%
%    \end{macrocode}
% Set the contents of the box to empty
%    \begin{macrocode}
      \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
%    \end{macrocode}
% no shape
%    \begin{macrocode}
    \expandafter\expandafter\expandafter
    \parbox\csname @df@dim@\romannumeral#1\endcsname
    {%
      \setlength\parindent\sdfparindent
      \csname\ff@style\endcsname{\ff@contents}%
    }%
  \or
%    \end{macrocode}
% \cs{parshape}
%    \begin{macrocode}
    \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
%    \end{macrocode}
% \cs{shapepar}
%    \begin{macrocode}
    \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]{%
%    \end{macrocode}
%\changes{2014-06-04}{1.16}{added check for `hide' and `hidethis'
%attributes}
% Check the `hide' and `hidethis' attributes
%    \begin{macrocode}
  \ifthenelse{\boolean{@df@hidethis@\romannumeral#1}}%
  {%
    \@notthiscoltrue
    \global\csletcs{if@df@hidethis@\romannumeral#1}{iffalse}%
  }%
  {%
    \ifthenelse{\boolean{@df@hide@\romannumeral#1}}%
    {%
      \@notthiscoltrue
    }%
    {%
%    \end{macrocode}
% Neither `hide' nor `hidethis' have been set so check the page
% list.
%    \begin{macrocode}
      \@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
%    \end{macrocode}
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
  \c@curpg=\@ff@pages@countreg
  \@g@tnextcol{\@nxtcol}%
  \if@ff@nwpg
%    \end{macrocode}
% Next flow frame starts on new page.
%    \begin{macrocode}
    \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
%    \end{macrocode}
% Shipout pages without flow frames.
%\changes{1.14}{2012-11-10}{replaced \cs{c@page} with
%\cs{@ff@pages@countreg}}
%    \begin{macrocode}
    \advance\c@curpg by -\@ff@pages@countreg\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
%    \end{macrocode}
% Still on same page, save contents of box255
%    \begin{macrocode}
    \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%
    }%
  }%
  {%
%    \end{macrocode}
% Store current chapter head definitions for starred and unstarred
% versions
%    \begin{macrocode}
    \let\@ff@OLDmakechapterhead\@makechapterhead
    \let\@ff@OLDmakeschapterhead\@makeschapterhead
%    \end{macrocode}
% Define user commands that can be redefined to modify the chapter
% head style (in the event that the user is using a class that
% doesn't provide an easy means to do this.)
%    \begin{macrocode}
    \renewcommand{\DFchapterstyle}[1]{\@ff@OLDmakechapterhead{##1}}%
    \renewcommand{\DFschapterstyle}[1]{\@ff@OLDmakeschapterhead{##1}}%
%    \end{macrocode}
% Redefine chapter heads so that they put their contents in the
% requested dynamic frame. First the unstarred version:
%    \begin{macrocode}
    \xdef\@makechapterhead##1{%
      \noexpand\@setdynamiccontents{\number#1}%
      {%
        \noexpand\DFchapterstyle{##1}%
      }%
    }%
%    \end{macrocode}
% Now the starred version:
%    \begin{macrocode}
    \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\relax
    \@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\relax
    \@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]{%
%    \end{macrocode}
% Check if this thumbtab exists
%    \begin{macrocode}
  \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]{%
%    \end{macrocode}
% Check if this thumbtab exists
%    \begin{macrocode}
  \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
%    \end{macrocode}
% Save original definition of "\tableofcontents"
%    \begin{macrocode}
\let\@ttb@old@tableofcontents\tableofcontents
%    \end{macrocode}
% Redefine "\tableofcontents"
%    \begin{macrocode}
\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-2025-08-23.sty>
%    \end{macrocode}
%\fi
%\Finale
\endinput
