%D \module
%D   [       file=page-set,
%D        version=2000.10.20,
%D          title=\CONTEXT\ OTR Macros,
%D       subtitle=Column Sets,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA / Hans Hagen \& Ton Otten}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

% getnoflines vs getrawnoflines

% some day: cleanup

\writestatus{loading}{Context OTR Macros / Column Sets}

% todo : last longer than previous
% todo : block span over last column if footnotes
% todo : diagnosis balancing run
% todo : separate footnote placement
% todo : go on on same page with colset
% todo : test page areas per page
% todo : leftmargin/rightmargin (better than afstand(1))

\unprotect

\newcount\tofcolumns % total
\newcount\lofcolumns % left
\newcount\rofcolumns % right

\newcount\columnfirstcell \columnfirstcell=1
\newcount\columnlastcell
\newcount\columnfreecells
\newcount\currenthcell
\newcount\currentvcell
\newcount\columnhcells
\newcount\columnvcells

\newif\ifenoughcolumncells
\newif\ifsomefreecolumncells
\newif\ifcolumnspread
\newif\iftracecolumnset    %   \tracecolumnsettrue

\def\columnmaxcells    {75} % runtime
\def\columnmaxfreecells {0} % runtime
\def\columngaplimit     {0} % {5}

\def\@otr@{otr}

\def\OTRSETgridcell#1#2%
  {\csname\@otr@:\number#1:\number#2\endcsname}

\def\OTRSETgetgridcell#1#2%
  {\box\csname\@otr@:\number#1:\number#2\endcsname}

\def\OTRSETsetgridcell#1#2%
  {\global\setbox\csname\@otr@:\number#1:\number#2\endcsname}

% \def\OTRSETgetgridcell{\box          \OTRSETgridcell}
% \def\OTRSETsetgridcell{\global\setbox\OTRSETgridcell}

\long\def\OTRSETdoifcellelse#1#2#3#4%
  {\relax\ifvoid\csname\@otr@:\number#1:\number#2\endcsname#4\else#3\fi}

\beginETEX \ifcsname

\def\columnerasegridboxes % maybe dedicated loops
  {\bgroup
   \increment\columnmaxcells\relax
   \ifodd\realpageno
   \else % we are on the other page
     \columnspreadfalse
   \fi
   \ifcolumnspread
     \dorecurse\nofcolumns
       {\let\!!stringa\recurselevel
        \scratchcounter\recurselevel \advance\scratchcounter\lofcolumns
        \edef\!!stringb{\the\scratchcounter}%
        \dostepwiserecurse \zerocount \columnmaxcells \plusone
          {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
             \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box
             \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
               \csname\@otr@:\!!stringb:\recurselevel\endcsname
              %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \else
               \voidb@x
              %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\voidb@x
               \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \fi
           \else
             \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
             \ifcsname\@otr@:\!!stringb:\recurselevel\endcsname
               \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \else
               \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \fi
           \fi}}%
   \else
     \dorecurse \tofcolumns
       {\let\!!stringa\recurselevel
        \dostepwiserecurse \zerocount \columnmaxcells \plusone
          {\ifcsname\@otr@:\!!stringa:\recurselevel\endcsname
             \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\voidb@x
           \else
             \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
           \fi}}%
   \fi
   \dorecurse\tofcolumns
     {\global\setbox\csname\@otr@:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}%
   \global\columnfirstcell\zerocount
   \global\columnlastcell\columnfirstcell
   \global\columnfreecells\columnfirstcell
   \egroup}

\endETEX

\beginTEX

\def\columnerasegridboxes
  {\bgroup
   \increment\columnmaxcells\relax
   \ifodd\realpageno \else % we are on the other page
     \columnspreadfalse
   \fi
   \ifcolumnspread
     \dorecurse\nofcolumns
       {\let\!!stringa\recurselevel
        \scratchcounter\recurselevel \advance\scratchcounter\lofcolumns
        \edef\!!stringb{\the\scratchcounter}%
        \dostepwiserecurse \zerocount \columnmaxcells \plusone
          {\expandafter\ifx\csname\@otr@:\!!stringa:\recurselevel\endcsname\relax
             \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
             \expandafter\ifx\csname\@otr@:\!!stringb:\recurselevel\endcsname\relax
               \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \else
               \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \fi
           \else
             \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box
             \expandafter\ifx\csname\@otr@:\!!stringb:\recurselevel\endcsname\relax
               \voidb@x
              %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\voidb@x
               \expandafter\newbox\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \else
               \csname\@otr@:\!!stringb:\recurselevel\endcsname
              %\global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\csname\@otr@:\!!stringb:\recurselevel\endcsname
             \fi
           \fi}}%
   \else
     \dorecurse\tofcolumns
       {\let\!!stringa\recurselevel
        \dostepwiserecurse \zerocount \columnmaxcells \plusone
          {\expandafter\ifx\csname\@otr@:\!!stringa:\recurselevel\endcsname\relax
             \expandafter\newbox\csname\@otr@:\!!stringa:\recurselevel\endcsname
           \else
             \global\setbox\csname\@otr@:\!!stringa:\recurselevel\endcsname\box\voidb@x
           \fi}}%
   \fi
   \dorecurse\tofcolumns
     {\global\setbox\csname\@otr@:\recurselevel:\columnmaxcells\endcsname\copy\placeholderboxa}%
   \global\columnfirstcell\zerocount
   \global\columnlastcell\columnfirstcell
   \global\columnfreecells\columnfirstcell
   \egroup}

\endTEX

\def\doOTRSETsetgridcells#1#2#3#4#5#6% placeholder col row wid hei {data}
  {\!!countd#2\advance\!!countd#4\advance\!!countd\minusone
   \!!counte#3\advance\!!counte#5\advance\!!counte\minusone
   \dostepwiserecurse{#2}\!!countd\plusone
     {\!!countf\recurselevel
      \dostepwiserecurse{#3}\!!counte\plusone
        {\OTRSETsetgridcell\!!countf\recurselevel#1}}%
   \dostepwiserecurse{#3}\!!counte\plusone
     {\global\wd\OTRSETgridcell{#2}\recurselevel\hsize}%
   \OTRSETsetgridcell{#2}\!!counte#6}

\def\OTRSETsetgridcells
  {\doOTRSETsetgridcells{\copy\placeholderboxb}}

\def\OTRSETerasegridcells#1#2#3#4%
  {\doOTRSETsetgridcells{\box\voidb@x}{#1}{#2}{#3}{#4}{\box\voidb@x}}

% \def\OTRSETsetfreecells#1#2% col start
%   {\global\columnfirstcell\ifnum#2=0 1\else#2\fi\relax
%    \ifnum\columnfirstcell>\columnmaxcells
%      \global\columnfreecells\zerocount
%      \global\columnfirstcell\plusone
%      \global\columnlastcell \zerocount
%      \global\somefreecolumncellsfalse
%     %\message{no cells a}%
%    \else
%      \doloop
%        {\ifnum\columnfirstcell>\columnmaxcells\relax
%           \exitloop
%         \else
%           \OTRSETdoifcellelse{#1}\columnfirstcell
%             {\global\advance\columnfirstcell\plusone}
%             {\exitloop}%
%         \fi}%
%      \global\columnlastcell\columnfirstcell
%      \doloop
%        {\ifnum\columnlastcell>\columnmaxcells\relax
%           \exitloop
%         \else
%           \OTRSETdoifcellelse{#1}\columnlastcell
%             {\global\advance\columnlastcell \minusone \exitloop}
%             {\global\advance\columnlastcell \plusone }%
%         \fi}%
%      \ifnum\columnfirstcell>\columnmaxcells
%        \global\columnfreecells\zerocount
%        \global\columnfirstcell\plusone
%        \global\columnlastcell \zerocount
%        \global\somefreecolumncellsfalse
%       %\message{no cells b}%
%      \else
%        \ifnum\columnlastcell>\columnmaxcells
%          \global\columnlastcell\columnmaxcells
%        \fi
%        \global\columnfreecells\columnlastcell
%        \global\advance\columnfreecells -\columnfirstcell
%        \global\advance\columnfreecells \plusone
%        \global\somefreecolumncellstrue
%       %\message{\number\columnfirstcell-\number\columnlastcell=\number\columnfreecells}%
%      \fi
%    \fi}

% \def\OTRSETgetmaxfreecells#1#2% col start
%   {\scratchcounter\zerocount
%    \let\columnmaxfreecells\!!zerocount
%    \let\columnfrmfreecells\!!zerocount
%    \dostepwiserecurse{#2}\columnmaxcells\plusone
%      {\OTRSETdoifcellelse{#1}\recurselevel
%         {\ifnum\columnmaxfreecells<\scratchcounter
%            \edef\columnmaxfreecells{\the\scratchcounter}%
%            \let\columnfrmfreecells\recurselevel
%          \fi
%          \scratchcounter\zerocount}
%         {\advance\scratchcounter\plusone}}}

\def\setupcolumnsetlines
  {\doquadrupleargument\dosetupcolumnsetlines}

\def\dosetupcolumnsetlines[#1][#2][#3][#4]%
  {\setevalue{\??mc#1:#2:\number#3}{\number#4}}

\beginTEX

\def\currentcolumnmaxcells
  {\ifundefined{\??mc\OTRSETidentifier:\columnsetpage:\number\mofcolumns}%
     \columnmaxcells
   \else\ifnum\csname\??mc\OTRSETidentifier:\columnsetpage:\number\mofcolumns\endcsname=0
     \columnmaxcells
   \else
     \csname\??mc\OTRSETidentifier:\columnsetpage:\number\mofcolumns\endcsname
   \fi\fi}

\endTEX

% in etex we also support negative numbers

\def\currentcolumnmaxcellstag
  {\??mc\OTRSETidentifier:\columnsetpage:\number\mofcolumns}

\beginETEX \numexpr

\def\currentcolumnmaxcells
  {\ifcsname\currentcolumnmaxcellstag\endcsname
     \ifnum\csname\currentcolumnmaxcellstag\endcsname=0
       \columnmaxcells
     \else
       \number\numexpr(\ifnum\csname\currentcolumnmaxcellstag\endcsname<0
         \columnmaxcells+\fi\csname\currentcolumnmaxcellstag\endcsname)%
     \fi
   \else
     \columnmaxcells
   \fi}

\endETEX

\def\doresetcolumnsetlines#1%
  {\ifundefined{\??mc\OTRSETidentifier:\columnsetpage:\number#1}\else
     \letgvalue{\??mc\OTRSETidentifier:\columnsetpage:\number#1}\!!zerocount
   \fi}

\def\OTRSETsetfreecells#1#2% col start
  {\global\columnfirstcell\ifnum#2=0 1\else#2\fi\relax
   \pushmacro \columnmaxcells
   \edef\columnmaxcells{\currentcolumnmaxcells}%
   \ifnum\columnfirstcell>\columnmaxcells
     \global\columnfreecells\zerocount
     \global\columnfirstcell\plusone
     \global\columnlastcell \zerocount
     \global\somefreecolumncellsfalse
    %\message{no cells a}%
   \else
     \doloop
       {\ifnum\columnfirstcell>\columnmaxcells\relax
          \exitloop
        \else
          \OTRSETdoifcellelse{#1}\columnfirstcell
            {\global\advance\columnfirstcell\plusone}
            {\exitloop}%
        \fi}%
     \global\columnlastcell\columnfirstcell
     \doloop
       {\ifnum\columnlastcell>\columnmaxcells\relax
          \exitloop
        \else
          \OTRSETdoifcellelse{#1}\columnlastcell
            {\global\advance\columnlastcell \minusone \exitloop}
            {\global\advance\columnlastcell \plusone }%
        \fi}%
     \ifnum\columnfirstcell>\columnmaxcells
       \global\columnfreecells\zerocount
       \global\columnfirstcell\plusone
       \global\columnlastcell \zerocount
       \global\somefreecolumncellsfalse
      %\message{no cells b}%
     \else
       \ifnum\columnlastcell>\columnmaxcells
         \global\columnlastcell\columnmaxcells
       \fi
       \global\columnfreecells\columnlastcell
       \global\advance\columnfreecells -\columnfirstcell
       \global\advance\columnfreecells \plusone
       \global\somefreecolumncellstrue
      %\message{\number\columnfirstcell-\number\columnlastcell=\number\columnfreecells}%
     \fi
   \fi
   \popmacro \columnmaxcells}

\def\OTRSETgetmaxfreecells#1#2% col start
  {\scratchcounter\zerocount
   \let\columnmaxfreecells\!!zerocount
   \let\columnfrmfreecells\!!zerocount
   \pushmacro \columnmaxcells
   \edef\columnmaxcells{\currentcolumnmaxcells}%
   \dostepwiserecurse{#2}\columnmaxcells\plusone
     {\OTRSETdoifcellelse{#1}\recurselevel
        {\ifnum\columnmaxfreecells<\scratchcounter
           \edef\columnmaxfreecells{\the\scratchcounter}%
           \let\columnfrmfreecells\recurselevel
         \fi
         \scratchcounter\zerocount}
        {\advance\scratchcounter\plusone}}%
   \popmacro\columnmaxcells}

\long\def\OTRSETrecurseRL#1%
  {\dostepwiserecurse\nofcolumns\plusone\minusone
     {#1\hskip\OTRSETgetparameter\c!afstand\recurselevel}}

\def\OTRSETmakegridbox
  {\ifcase\columndirection
     \OTRSETdomakegridbox\plusone\nofcolumns\plusone
   \else
     \OTRSETdomakegridbox\nofcolumns\plusone\minusone
   \fi}

\def\OTRSETdomakegridbox#1#2#3%
  {\hbox\bgroup
   \dontcomplain
   \forgetall % can go once in \flush
   \!!heighta \teksthoogte
   % test first !
   \hbox to \zetbreedte
     {\dostepwiserecurse{#1}{#2}{#3}
        {\mofcolumns\recurselevel
         \localcolumnwidth\OTRSETlocalwidth\mofcolumns
         \setbox\scratchbox\hbox\localframed
           [\??mc\OTRSETidentifier\number\mofcolumns]%
           [\c!breedte=\localcolumnwidth,\c!hoogte=\!!heighta,
            \c!regels=]%
           {}%
         \wd\scratchbox\localcolumnwidth
         \ht\scratchbox\!!heighta
         \ifcase\columndirection
           \hskip\OTRSETgetparameter\c!afstand\recurselevel
           \box\scratchbox
         \else
           \box\scratchbox
           \hskip\OTRSETgetparameter\c!afstand\recurselevel
         \fi}}%
   \hskip-\zetbreedte
   % main text
   \hbox to \zetbreedte
     {\dostepwiserecurse{#1}{#2}{#3}
        {\mofcolumns\recurselevel
         \localcolumnwidth\OTRSETlocalwidth\mofcolumns
         \offinterlineskip
         \setbox\scratchbox\vbox to \!!heighta % \teksthoogte
           {\topskipcorrection
            \dorecurse\columnmaxcells
              {\setbox\scratchbox\hbox{\OTRSETgetgridcell\mofcolumns\recurselevel}%
               \ht\scratchbox\strutht
               \dp\scratchbox\strutdp
               \ifcase\columndirection
                 \box\scratchbox
               \else
                 \hbox to \localcolumnwidth
                   {\hskip\localcolumnwidth\llap{\box\scratchbox}}%
               \fi
               \par}}%
         \wd\scratchbox\localcolumnwidth % \tekstbreedte
         \ifcase\columndirection
           \hskip\OTRSETgetparameter\c!afstand\recurselevel\box\scratchbox
         \else
           \box\scratchbox\hskip\OTRSETgetparameter\c!afstand\recurselevel
         \fi}}%
   \egroup}

\def\OTRSETreducegridbox
  {\ifnum\localcolumnmaxcells>\zerocount
     \let\columnmaxcells\localcolumnmaxcells
   \fi}

\def\OTRSETflushfinalfootnotes
  {\ifcase\lastcolumnlastcell \else
     \setbox\scratchbox\hbox
       {\placebottomnotes}%
     \ifdim\ht\scratchbox>\zeropoint
       \setbox\scratchbox\hbox
         {\hbox to \zeropoint{\OTRSETgetgridcell\nofcolumns\lastcolumnlastcell}%
          \box\scratchbox}%
       \ht\scratchbox\strutht
       \dp\scratchbox\strutdp
       \OTRSETsetgridcell\nofcolumns\lastcolumnlastcell\box\scratchbox
     \fi
     \global\lastcolumnlastcell\zerocount
   \fi}

\def\OTRSETdoflush
  {\ifcollectingcontent
     \global\mofcolumns\plusone
   \else
     \OTRSETdofinalflush
     \OTRSETdofinaloutput
\ifnum\columnsetpage>0
  \dorecurse\nofcolumns{\doresetcolumnsetlines\recurselevel}%
\fi
\doglobal\increment\columnsetpage
     \OTRSETinitializecolumns
    %\OTRSETdoflushfloats
     \OTRSETstartnextpage
     \initializecolumntextareas
   \fi}

%\def\OTRSETdofinalflush % see \OTRSETdoflush
%  {\OTRSETflushfinalfootnotes
%   \placecolumntextareas
%   \OTRSETcentergridcells
%   \setbox\scratchbox=\OTRSETmakegridbox
%   \global\mofcolumns=\nofcolumns % otherwise problems in finaloutput
%   \finaloutput\box\scratchbox}

\newbox\OTRfinalpagebox

\def\OTRSETdofinalflush % see \OTRSETdoflush
  {\OTRSETflushfinalfootnotes
   \placecolumntextareas
   \OTRSETcentergridcells
   \bgroup % we want to keep the reduction local
     \OTRSETreducegridbox
     \global\setbox\OTRfinalpagebox\OTRSETmakegridbox
   \egroup % otherwise we get the wrong number of free cells
  %\gdef\localcolumnmaxcells{0}% here ?
   \global\mofcolumns\nofcolumns} % otherwise problems in finaloutput

\def\OTRSETdofinaloutput
  {\ifdim\ht\OTRfinalpagebox=\teksthoogte
   % \bgroup \let\OTRSETsetvsize\relax % prevents useless search for gap
       \finaloutput\box\OTRfinalpagebox
   % \egroup
   \fi}

\definesystemvariable {mc}
\definesystemvariable {mt}
\definesystemconstant {colset}

\definetwopasslist\s!colset

\newdimen  \OTRSETtextswidth
\newdimen  \OTRSETtextsheight
\let       \OTRSETidentifier=\empty

\newtoks   \OTRSEToutput

\def\OTRSETgetparameter#1#2{\getvalue{\??mc\OTRSETidentifier\number#2#1}}
\def\OTRSETsetparameter#1#2{\setvalue{\??mc\OTRSETidentifier\number#2#1}}

\def\OTRSETsetvsize % snap per sectie (gap here?)
  {\ifcollectingcontent \else % can be assigndimen
     \OTRSETcheckinsert % added
     \OTRSETsetfreecells\mofcolumns\columnfirstcell
     \ifsomefreecolumncells
       \global\vsize\columnfreecells\lineheight
       \ifinotr % else problems with floats, see extreme
         \global\pagegoal\vsize % niet nodig, tenzij binnen otr
       \fi
       \synchronizeoutput % fails on example
      % \allowbreak % hm
     \fi
     \synchronizenotes
   \fi}

\def\OTRSETsethsize % of course this does not migrate outside the otr
  {\localcolumnwidth\OTRSETlocalwidth\mofcolumns
   \tekstbreedte\localcolumnwidth
   \hsize\localcolumnwidth}

%\def\OTRSETsynchronizehsize
%  {\doifnotvalue{\??mc\OTRSETidentifier\the\mofcolumns\c!breedte}\v!passend
%     \OTRSETsethsize}

\def\OTRSETsynchronizehsize
  {\ifcase0\getvalue{\??mc\??mc\c!breedte}\else % some width set
     \bgroup
     \scratchdimen\OTRSETlocalwidth\mofcolumns
     \ifdim\scratchdimen=\tekstbreedte
       \egroup
     \else
       % only if change in width and \column/\break
       \egroup \OTRSETsethsize
     \fi
   \fi}

\def\OTRSETcheckfreelines
  {\OTRSETsetvsize}

\def\doOTRSETcolumnseparator
  {\hbox to \zeropoint{\hss\red\vl\hss}}

\let\OTRSETcolumnseparator\relax

\def\showbreaks
  {\let\OTRSETcolumnseparator\doOTRSETcolumnseparator}

% \installcolumnbreakhandler {SET} \v!ja
%   {% hmmm:
%    \ifhmode
%      \bgroup
%      \removeunwantedspaces
%      \parfillskip\zeropoint
%      \OTRSETcolumnseparator
%      \par
%      \egroup
%    \fi
%    % brrr:
%    \ejectinsert
%    \ejectpage
%    \OTRSETsynchronizehsize} % no \OTRSETsethsize, can be mid smaller (like tabulate)
%
% \installcolumnbreakhandler {SET} \v!forceer
%   {\OTRSETgotocolumn[\v!forceer]}
% \installcolumnbreakhandler {SET} \v!eerste
%   {\OTRSETgotocolumn[\v!eerste]}
% \installcolumnbreakhandler {SET} \v!laatste
%   {\OTRSETgotocolumn[\v!laatste]}
%
% \installcolumnbreakhandler {SET} \v!pagina
%   {\simplepagebreak % \flushnotes \executepagebreakhandler\v!ja
%    \ifnum\mofcolumns>\plusone
%      \OTRSETgotocolumn[\v!laatste,\v!forceer]%
%    \fi}

\def\OTRSETcolumnhbreak
  {\ifhmode
     \bgroup
     \removeunwantedspaces
     \parfillskip\zeropoint
     \OTRSETcolumnseparator
     \par
     \egroup
   \fi}

\installcolumnbreakhandler {SET} \v!lokaal
  {\OTRSETcolumnhbreak
   \ejectinsert
   \ejectpage % brrr
   % no \OTRSETsethsize, can be mid smaller (like tabulate)
   % also, this one should be executed at the outer level
   % (setting hsize inside otr does not work)
   \OTRSETsynchronizehsize}

% We need to make sure that we really leave the column; mid
% column we may end up in an empty gap, and we don't want to
% stay there (basically such a gap is a small empty page
% then).

\installcolumnbreakhandler {SET} \v!ja
  {\OTRSETcolumnhbreak
   \edef\savedmofcolumns{\the\mofcolumns}%
   \edef\savedrealpageno{\the\realpageno}%
   \ejectinsert
   \ejectpage % brrr
   \doloop
     {\ifnum\savedmofcolumns=\mofcolumns
        \ifnum\savedrealpageno=\realpageno
          \OTRSETdummycolumn
        \else
          \exitloop
        \fi
      \else
        \exitloop
      \fi}%
   \OTRSETsynchronizehsize}

\installcolumnbreakhandler {SET} \s!unknown
  {\expanded{\OTRSETgotocolumn[\@@columnspecification]}}

\installcolumnbreakhandler {SET} \v!pagina
  {\vfill\eject % \doejectpage\eject
   \OTRSETgotonextpage}

\newtoks\OTRSETeverystartofcolumn

\newbox\OTRSETsavedfootnotes

% \installoutput\OTRSETflushtextsofar % spacing goes wrong

%\def\OTRSETflushtextsofar
%  {\ifvoid\normalpagebox \else
%     \setbox\scratchbox\vbox{\unvbox\normalpagebox}%
%     \OTRSETsavenotes
%     \OTRSEThandleflushedtext0
%   \fi}

% The complication is in the fact that when the HERE float
% is placed, the otr is not invoked when there is not yet
% enough content; this can lead to a change in order (turning
% on the tracer with option 0 is very instructive, watch the
% small numbers in the margin)
%
% 0 = no flushing, so no interference but user should handle
%     border cases of placement
% 1 = the normal otr, rather untested
% 2 = a solution that works ok, is experimental and above
%     all messy

\chardef\OTRSETflushtextmode=0

\def\OTRSETflushtextsofar
  {\ifcase\OTRSETflushtextmode
     % don't mess around
   \or
     % the normal one
     \ifvoid\normalpagebox\else
       \OTRSETnaturalflush
       \OTRSETcheckfreelines
     \fi
   \or
     % way to complicated, but kind of ok
     \doOTRSETflushtextsofar
   \fi}

\newskip\lastskipinotr

\installoutput\doOTRSETflushtextsofar % experimental
  {\ifvoid\normalpagebox\else
     \scratchdimen\dp\normalpagebox
     \setbox\scratchbox\vbox
       {\forgetall
        \unvbox\normalpagebox
        \global\lastskipinotr\lastskip\relax
        \ifdim\lastskipinotr>\zeropoint\relax
          \removelastskip
        \else
          \kern-\scratchdimen % handle depth
        \fi}%
     \ifdim\lastskipinotr>\zeropoint
       \scratchskip\ht\scratchbox
       \setbox\scratchbox\hbox
         {\lower\strutdepth\box\scratchbox}%
       \dp\scratchbox\scratchdimen
       \ht\scratchbox\scratchskip
     \fi
     \OTRSETsavenotes
     \OTRSEThandleflushedtext0%
     \ifdim\lastskipinotr>\zeropoint
       %\vskip \lastskipinotr % hm, gets lost anyway
     \else
       % we should not discard skips after here; tricky
     \fi
     \OTRSETsetvsize
   \fi}

\def\OTRSETplacebottomnotes
  {\iflastcolumnfootnotes
     \ifnum\nofcolumns=\mofcolumns
       \ifintermediatefootnotes \placebottomnotes \fi
     \fi
   \else
     \placebottomnotes
   \fi}

\def\OTRSETflushsavednotes
  {\iflastcolumnfootnotes
     \ifnum\nofcolumns=\mofcolumns
       \flushsavednotes
     \fi
   \else
     \flushsavednotes
   \fi}

\def\OTRSETsavenotes
  {\iflastcolumnfootnotes
     \ifnum\nofcolumns=\mofcolumns \else
       \savenotes
     \fi
   \fi}

\appendtoks \OTRSETflushsavednotes \to \OTRSETeverystartofcolumn

% \def\OTRSETnaturalflush
%   {\bgroup
%    \forgetall % new, needed !
%    \setbox0\vbox to \columnfreecells\lineheight
%      {\vskip-\topskip
%       \vskip\lineheight
%       \prevdepth\strutdp
%       \unvbox\normalpagebox
%       \vfill}%
%    \setbox2\hbox
%      {\OTRSETplacebottomnotes}%
%    \setbox\scratchbox\hbox
%      {\wd0\zeropoint\box0\box2}%
%    \dp\scratchbox\strutdp
%    \OTRSEThandleflushedtext1
%    \egroup}

\def\OTRSETnaturalflush
  {\bgroup
   \forgetall % new, needed !
   \setbox0\vbox to \columnfreecells\lineheight
     {\vskip-\topskip
      \vskip\lineheight
      \prevdepth\strutdp
      \unvbox\normalpagebox
      \vfill}%
   \setbox2\hbox
     {\OTRSETplacebottomnotes}%
   \setbox\scratchbox\hbox
     {\wd0\zeropoint\box0\box2}%
   \dp\scratchbox\strutdp
   \OTRSEThandleflushedtext1
   \egroup}

\newcount\lastcolumnlastcell

\def\OTRSEThandleflushedtext#1%
  {\getnoflines{\ht\scratchbox}%
  %\wd\scratchbox\tekstbreedte % geen \hsize kan < zijn in bv split tabulate
   \wd\scratchbox\OTRSETlocalwidth\mofcolumns
   \doOTRSETsetgridcells
     {\copy\placeholderboxf}
     \mofcolumns\columnfirstcell\plusone\noflines
     {\registeredtextarea1\columnfirstcell\scratchbox}% == \hbox
   \global\columnlastcell\columnfirstcell
   \global\advance\columnlastcell \noflines
   \global\lastcolumnlastcell\columnlastcell
   \global\advance\lastcolumnlastcell \minusone
   % find next (acceptable) gap, todo: deadcycle
   \ifcase#1\else
     \OTRSETfillgapsbetweencells\mofcolumns\columnlastcell
   \fi
   \OTRSETfindnextgap
   % \message{\the\mofcolumns,\the\columnfirstcell,\the\columnfreecells}%
   % \wait
   % we cannot adapt the hsize since it may have changed (like
   % inside a tabulate) so we only change it when there is a
   % reason to do so
   \OTRSETsynchronizehsize
   \OTRSETsetvsize}

\def\OTRSETfindnextgap
  {\OTRSETsetfreecells\mofcolumns\columnlastcell
   \ifsomefreecolumncells
     % okay
   \else
     \global\advance\mofcolumns \plusone
     \ifnum\mofcolumns>\nofcolumns
       \OTRSETdoflush
       \global\columnlastcell\plusone
       \global\columnfirstcell\zerocount
       \OTRSETdoflushfloats
     \else
       \the\OTRSETeverystartofcolumn
       \global\columnlastcell\plusone
       \global\columnfirstcell\zerocount
     \fi
   \fi}

\let\OTRSETcheckfreelines\donothing

\def\OTRSETfillgapsbetweencells#1#2% col
  {\ifnum\columngaplimit>\zerocount
     \donefalse
     \dostepwiserecurse{#2}\columnmaxcells\plusone
       {\OTRSETdoifcellelse{#1}\recurselevel
          {\ifdone
             \!!countb\recurselevel \advance\!!countb -\!!counta\relax
             \ifnum\!!countb>\plusone
               \advance\!!countb \minusone
               \ifnum\!!countb<\columngaplimit\relax
                 \!!countb\recurselevel \advance\!!countb \minusone
                 \dostepwiserecurse\!!counta\!!countb\plusone
                   {\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}%
                %\message{[gap]}%
               \fi
             \fi
           \fi
           \donefalse}
          {\ifdone \else
             \donetrue
             \!!counta\recurselevel
           \fi}}%
   \fi}

\appendtoks
  \OTRSETfillgapsbetweencells\mofcolumns\plusone
\to \OTRSETeverystartofcolumn

%\def\OTRSETfreezeminimumgap#1%
%  {\OTRSETgetmaxfreecells{#1}{1}%
%   \ifnum\columnmaxfreecells>0
%     \!!countb=\columnfrmfreecells
%     \!!counta=\!!counta \advance\!!counta -\columnmaxfreecells
%     \dorecurse{\columnmaxcells}
%       {\ifnum\recurselevel<\!!counta\relax
%          \donetrue
%        \else\ifnum\recurselevel>\!!countb
%          \donetrue
%        \else
%          \donefalse
%        \fi\fi
%        \ifdone
%          \OTRSETdoifcellelse{#1}{\recurselevel}
%            {}{\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}%
%        \fi}%
%   \fi}
%
%\def\OTRSETfillgaps#1#2#3% col from to
%  {\dostepwiserecurse{#2}{#3}{1}
%     {\OTRSETdoifcellelse{#1}{\recurselevel}
%        {}{\OTRSETsetgridcell{#1}\recurselevel\copy\placeholderboxc}}}
%
%\def\OTRSETfillbotgaps#1#2% col first
%  {\OTRSETfillgaps{#1}{#2}{\columnmaxcells}}
%
%\def\OTRSETfilltopgaps#1#2% col last
%  {\OTRSETfillgaps{#1}{1}{#2}}

\newif\ifspancolumnslots \spancolumnslotstrue
\newif\ifcheckcolumnspan \checkcolumnspantrue

\def\OTRSETcheckwidthgap#1#2% box size
  {\ifcheckcolumnspan
     \bgroup
     \scratchdimen#2%
     \advance\scratchdimen-\wd#1\relax
     \ifdim-10\s!sp>\scratchdimen
       \egroup
     \else\ifdim10\s!sp<\scratchdimen
       \egroup
     \else
       \egroup
       \wd#1=#2%
     \fi\fi
   \fi}

\def\OTRSETcheckcolumnslot#1%
  {\enoughcolumncellstrue
   \ifspancolumnslots\else
     \OTRSETcheckwidthgap#1\hsize
     \ifdim\wd#1>\hsize
       \enoughcolumncellsfalse
     \fi
   \fi
   \ifenoughcolumncells
     \getnoflines\pagetotal
     \scratchcounter\noflines
     \getnoflines{\ht#1}%
     \columnvcells\noflines
     \columnhcells\plusone
     \advance\scratchcounter \columnvcells \relax
     \ifnum\scratchcounter>\columnfreecells
       \enoughcolumncellsfalse
     \fi
   \fi}

\def\OTRSETstoreincolumnslotPAGE#1%
  {\ifenoughcolumncells
     % to do
     \OTRSETsavebox{#1}%
   \else
     \OTRSETsavebox{#1}%
   \fi}

\def\OTRSETstoreincolumnslotTOPS#1%
  {\OTRSETprepareforcolumnslot1{#1}%
   \OTRSETcheckcolumnslot{#1}%
   \ifenoughcolumncells
     \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
   \fi
   \ifenoughcolumncells
     \OTRSETsetgridcells\mofcolumns\columnfirstcell\columnhcells\columnvcells
       {\hbox{\copy#1}}%
     \OTRSETsetvsize
   \else
     \OTRSETsavebox{#1}%
   \fi}

\def\OTRSETstoreincolumnslotBOTS#1%
  {\OTRSETprepareforcolumnslot3{#1}%
   \edef\savedcolumnlastcell{\the\columnlastcell}%
   \OTRSETcheckcolumnslot{#1}%
   \ifenoughcolumncells
     \advance\columnlastcell -\columnvcells \advance\columnlastcell \plusone
%     \OTRSETcheckcolumnspace\mofcolumns\columnfirstcell{#1}%
     \OTRSETcheckcolumnspace\mofcolumns\columnlastcell{#1}%
   \fi
   \ifenoughcolumncells
     \OTRSETsetgridcells\mofcolumns\columnlastcell\columnhcells\columnvcells
       {\copy#1}
     \OTRSETfillgapsbetweencells\mofcolumns\savedcolumnlastcell % -)
     \OTRSETsetvsize
   \else
     \columnlastcell\savedcolumnlastcell
     \OTRSETsavebox{#1}%
   \fi}

\newdimen\totalcolumnspace

\def\columnspacetopoffset{0}
\def\columnspacebotoffset{0}

\def\OTRSETcheckcolumnspace#1#2#3% col row box
  {\columnhcells\plusone
   \totalcolumnspace\zeropoint
   \scratchcounter#1%
   \enoughcolumncellstrue
   \doloop
     {\advance\totalcolumnspace \OTRSETlocalwidth\scratchcounter\relax % needed
\OTRSETcheckwidthgap#3\totalcolumnspace
      \ifnum\wd#3>\totalcolumnspace\relax
        \ifnum\scratchcounter=\nofcolumns
          \enoughcolumncellsfalse
          \exitloop
        \else
          \advance\columnhcells \plusone
          \advance\scratchcounter \plusone
          \advance\totalcolumnspace \OTRSETgetparameter\c!afstand\scratchcounter
        \fi
      \else
        \exitloop
      \fi}%
   \ifenoughcolumncells
     \getnoflines{\ht#3}%
     \columnvcells\noflines
     \OTRSETcheckcolumncells{#1}{#2}\columnhcells\columnvcells
   \fi}

\def\OTRSETcheckcolumncells#1#2#3#4% col row wid hei
  {\!!countd#1\advance\!!countd#3\advance\!!countd\minusone
   \!!counte#2\advance\!!counte#4\advance\!!counte\minusone
   \ifnum\!!counte>\columnmaxcells\relax
     \enoughcolumncellsfalse
   \else
     \enoughcolumncellstrue
%\let\columnspacetopoffset\zerocount
%\scratchcounter#2\advance\scratchcounter\minusone
%\ifnum\scratchcounter>0
%  \dostepwiserecurse{#1}\!!countd\plusone
%    {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
%       \let\columnspacetopoffset\plusone
%     \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
%       \let\columnspacetopoffset\plusone
%     \fi\fi}%
%  \advance\!!counte \columnspacetopoffset \relax
%  \advance\columnvcells \columnspacetopoffset \relax
%\fi
%\let\columnspacebotoffset\zerocount
%\scratchcounter\!!counte
%\advance\scratchcounter \columnvcells \relax
%\ifnum\scratchcounter>\columnmaxcells\else
%  \dostepwiserecurse{#1}\!!countd\plusone
%    {\ifdim\wd\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
%       \let\columnspacebotoffset\plusone
%     \else\ifdim\dp\OTRSETgridcell\recurselevel\scratchcounter>\zeropoint
%       \let\columnspacebotoffset\plusone
%     \fi\fi}%
%  \advance\!!counte \columnspacebotoffset \relax
%  \advance\columnvcells \columnspacebotoffset \relax
%\fi
     \dostepwiserecurse{#1}\!!countd\plusone % cols
       {\ifenoughcolumncells
          \!!countf\recurselevel\relax
          \dostepwiserecurse{#2}\!!counte\plusone % rows
            {\ifenoughcolumncells
               \OTRSETdoifcellelse\!!countf\recurselevel
                 {\enoughcolumncellsfalse}{}%
             \fi}%
        \fi}%
   \fi}

\def\OTRSETsetpreferedcolumnslot#1#2%
  {\doifsomething{#1}{\edef\preferedcolumn{#1}}%
   \doifsomething{#2}{\edef\preferedrow   {#2}}}

\OTRSETsetpreferedcolumnslot{\nofcolumns}{1} % default ?

\let\pofcolumns\mofcolumns
\let\qofcolumns\mofcolumns

\newif\ifquitincurrentcolumn

\def\OTRSETstoreincolumnslotLRTB#1%
  {\OTRSETprepareforcolumnslot1{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \mofcolumns\nofcolumns+\currenthcell
     \plusone\columnmaxcells+\currentvcell{#1}}

\def\OTRSETstoreincolumnslotLRBT#1%
  {\OTRSETprepareforcolumnslot3{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \mofcolumns\nofcolumns+\currenthcell
     \columnmaxcells\plusone-\currentvcell{#1}}

\def\OTRSETstoreincolumnslotRLTB#1%
  {\OTRSETprepareforcolumnslot1{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \nofcolumns\qofcolumns-\currenthcell
     \plusone\columnmaxcells+\currentvcell{#1}}

\def\OTRSETstoreincolumnslotRLBT#1%
  {\OTRSETprepareforcolumnslot3{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \nofcolumns\qofcolumns-\currenthcell
     \columnmaxcells\plusone-\currentvcell{#1}}

\def\OTRSETstoreincolumnslotTBLR#1%
  {\OTRSETprepareforcolumnslot1{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \plusone\columnmaxcells+\currentvcell
     \mofcolumns\nofcolumns+\currenthcell{#1}}

\def\OTRSETstoreincolumnslotTBRL#1%
  {\OTRSETprepareforcolumnslot1{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \plusone\columnmaxcells+\currentvcell
     \nofcolumns\qofcolumns-\currenthcell{#1}}

\def\OTRSETstoreincolumnslotBTLR#1%
  {\OTRSETprepareforcolumnslot3{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \columnmaxcells\plusone-\currentvcell
     \mofcolumns\nofcolumns+\currenthcell{#1}}

\def\OTRSETstoreincolumnslotBTRL#1%
  {\OTRSETprepareforcolumnslot3{#1}%
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \columnmaxcells\plusone-\currentvcell
     \nofcolumns\qofcolumns-\currenthcell{#1}}

\def\OTRSETstoreincolumnslotFXTB#1% fixed column
  {\OTRSETprepareforcolumnslot2{#1}% % 1/2 dependent of place, todo
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \pofcolumns\pofcolumns+\currenthcell
     \preferedrow\columnmaxcells+\currentvcell{#1}}

\def\OTRSETstoreincolumnslotFXBT#1% fixed column
  {\OTRSETprepareforcolumnslot2{#1}% % 3/2 dependent on place, todo
\OTRSETflushtextsofar
   \OTRSETstoreincolumnslotindeed
     \pofcolumns\pofcolumns+\currenthcell
     \columnmaxcells\preferedrow-\currentvcell{#1}}

% \def\OTRSETstoreincolumnslotHERE#1% fixed column
%   {\OTRSETprepareforcolumnslot2{#1}%
%    \OTRSETflushtextsofar
%    \getnoflines\pagetotal \advance\noflines\columnfirstcell
%    \OTRSETstoreincolumnslotindeed
%      \mofcolumns\mofcolumns+\currenthcell
%      \noflines\columnmaxcells+\currentvcell{#1}%
%    \OTRSETsetvsize}

\chardef\OTRSETforcefixedfloats=0

\def\OTRSETstoreincolumnslotHERE#1% fixed column
  {\ifcase\OTRSETforcefixedfloats
     \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
   \else
     \OTRSETstoreincolumnslotFIXD{#1}%
   \fi}

% this one looses too wide graphics
%
% \def\OTRSETstoreincolumnslotFIXD#1% fixed column
%   {\OTRSETprepareforcolumnslot2{#1}%
%    % no flush text sofar here, beware: no width test
%    \snaptogrid\vbox{\box#1}}
%
% still imperfect

\def\OTRSETstoreincolumnslotFIXD#1% fixed column
  {\OTRSETflushtextsofar
   \ifdim\wd#1>\tekstbreedte
     \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
   \else
     % crappy test / needed for o-pbu-f / will be replaced
     \getnoflines{\ht#1}%
     \scratchdimen\dimexpr(\noflines\lineheight+\lineheight)\relax
     \advance\scratchdimen\pagetotal\relax
     \ifdim\scratchdimen<\pagegoal
       \OTRSETprepareforcolumnslot3{#1}%
       \snaptogrid\vbox{\box#1}%
       \blanko
     \else
       \OTRSETstoreincolumnslotSOMEWHERE2{#1}%
     \fi
   \fi}

\def\OTRSETstoreincolumnslotSOMEWHERE#1#2%
  {\OTRSETprepareforcolumnslot{#1}{#2}%
   \OTRSETflushtextsofar
   \getnoflines\pagetotal \advance\noflines\columnfirstcell
   \OTRSETstoreincolumnslotindeed
     \mofcolumns\mofcolumns+\currenthcell
     \noflines\columnmaxcells+\currentvcell{#2}%
   \OTRSETsetvsize}

\def\OTRSETstoreincolumnslotindeed#1#2#3#4#5#6#7#8#9%
  {\ifnum\preferedcolumn<\mofcolumns
     \let\pofcolumns\mofcolumns
   \else
     \let\pofcolumns\preferedcolumn
   \fi
   \ifquitincurrentcolumn
     \ifnum\mofcolumns=\nofcolumns
       \def\qofcolumns{\mofcolumns}%
     \else
       \scratchcounter\mofcolumns
       \advance\scratchcounter \plusone
       \edef\qofcolumns{\the\scratchcounter}%
     \fi
   \else
     \let\qofcolumns\mofcolumns
   \fi
   \enoughcolumncellsfalse
   \donefalse
   \dostepwiserecurse{#1}{#2}{#31}
     {\ifdone
        \exitloop
      \else
        #4=\recurselevel
        \dostepwiserecurse{#5}{#6}{#71}
          {\ifdone
             \exitloop
           \else
             #8=\recurselevel
             \OTRSETcheckcolumnspace\currenthcell\currentvcell{#9}%
             \ifenoughcolumncells \donetrue \fi
           \fi}%
      \fi}%
   \ifdone
     \enoughcolumncellstrue
   \else
     \enoughcolumncellsfalse
   \fi
   \ifenoughcolumncells
%    \ifnum\columnspacetopoffset>0\message{[+++]}\fi
%    \ifnum\columnspacebotoffset>0\message{[---]}\fi
%    \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
%      {\vbox
%         {\ifcase\columnspacetopoffset\else\ruledvskip\columnspacetopoffset\lineheight\fi
%          \copy#9
%          \ifcase\columnspacebotoffset\else\ruledvskip\columnspacebotoffset\lineheight\fi}}%
     \OTRSETsetgridcells\currenthcell\currentvcell\columnhcells\columnvcells
       {\copy#9}%
     \ifnum\currenthcell=\mofcolumns\relax
       \ifdim\ht\OTRSETsavedfootnotes>\zeropoint
         \OTRSETsetfreecells\mofcolumns\columnfirstcell
         \ifsomefreecolumncells
           \getnoflines{\ht\OTRSETsavedfootnotes}\relax
           \ifnum\columnfreecells<\noflines
             \global\somefreecolumncellsfalse
           \else
            %\message{[flt]}% float
           \fi
         \fi
         \ifsomefreecolumncells
           % ok, enough room for notes
          %\message{[flt]}% float
         \else % ?
           \OTRSETsavebox{#9}%
           \OTRSETerasegridcells\currenthcell\currentvcell\columnhcells\columnvcells
          %\message{[clr]}% save box
         \fi
       \else
        %\message{[flt]}% float
       \fi
     \else
      %\message{[flt]}% float
     \fi
     \OTRSETsetvsize
    %\message{[fnt]}% float
   \else
    %\message{[rej]}% save box
     \OTRSETsavebox{#9}%
   \fi}

\chardef\columnslotspacing \plusone

\def\OTRSETstoreincolumnslot#1% #2 % {method} {box} % alleen last
  {% no messing around here
   % \dp#2=\zeropoint
   % \ifcase\columnslotspacing\else
   %   \setbox#2=\vbox spread \columnslotspacing\lineheight
   %     {\vss\box#2\vss}%
   % \fi
   % and don't change this any more
%   \doifdefinedelse{\strippedcsname\OTRSETstoreincolumnslot#1}
%     {\getvalue{\strippedcsname\OTRSETstoreincolumnslot#1}{#2}}
%     {\OTRSETstoreincolumnslotUNKNOWN{#2}}}
   \executeifdefined{\strippedcsname\OTRSETstoreincolumnslot#1}
     \OTRSETstoreincolumnslotUNKNOWN} % {#2}}

\def\OTRSETstoreincolumnslotUNKNOWN#1%
  {\OTRSETprepareforcolumnslot2{#1}\copy#1} % {} ?

\def\OTRSETprepareforcolumnslot#1#2% 1=hoog 2=midden 3=laag
  {\dp#2\zeropoint
   \ifcase\columnslotspacing\else
     \scratchdimen\columnslotspacing\lineheight
     \ifnum#1=2 \scratchdimen2\scratchdimen \fi
     \setbox#2\vbox spread \scratchdimen
       {\ifnum#1>1\vss\fi\box#2\relax\ifnum#1<3\vss\fi}%
   \fi}

\def\OTRSETdocheckiffloatfits % eigenlijk moet else float anders
  {\global\ifnofloatpermitted\roomforfloatfalse\else\roomforfloattrue\fi}

\def\OTRSETunpreparebox#1%
  {\ifhbox#1% spans and so
     \global\setbox\floatbox\vbox{\box#1}%
   \else
     \setbox\scratchbox\vbox
       {\unvbox#1\unskip\unskip\unskip
        \global\setbox\floatbox\lastbox}%
   \fi}

\def\OTRSETsavebox#1% clean up the skips
  {\OTRSETunpreparebox{#1}%
   \dosavefloat}

\def\OTRSETresavebox#1% clean up the skips
  {\OTRSETunpreparebox{#1}%
   \doresavefloat}

\def\OTRSETflushfloatbox % nog verder doorvoeren en meer info in marge
  {\iftestfloatbox\ruledhbox\fi{\box\floatbox}}

\def\OTRSETdoflushfloats
  {\bgroup
   \def\OTRSETsavebox##1{\!!doneafalse}%
   \doloop
     {\ifsomefloatwaiting
        \dogetfloat
        \ifdim\wd\floatbox>\zeropoint
          \!!doneatrue
          \dp\floatbox\zeropoint
          \OTRSETstoreincolumnslot{TBLR}\floatbox
          \if!!donea
           %\message{[flu]}%
          \else
            \OTRSETresavebox\floatbox
            \exitloop
          \fi
        \else
         %\message{[err]}% happens but why?
        \fi
      \else
        \exitloop
      \fi}
   \egroup}

\newif\ifcentergridcells \centergridcellstrue

\newif\ifcentergridcellonly     \centergridcellonlyfalse
\newif\ifautocentergridcellonly \autocentergridcellonlytrue

\def\OTRSETcentergridcells
  {\ifcentergridcells
     \dorecurse\nofcolumns
       {\currenthcell\recurselevel
        \ifautocentergridcellonly
          % we prevent centering when the next column is empty
          % to be checked ! ! ! !
          \advance\currenthcell \plusone
          \centergridcellonlytrue
          \ifnum\currenthcell>\nofcolumns
            % ok already
          \else
            % only span if there is a next column with content
            \dorecurse\columnmaxcells
              {\ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
                 \centergridcellonlyfalse
               \else\ifdim\dp\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
                 \centergridcellonlyfalse
               \fi\fi}%
          \fi
        \fi
        \currenthcell\recurselevel
        \dorecurse\columnmaxcells
          {\currentvcell\recurselevel\relax
           \ifdim\ht\OTRSETgridcell\currenthcell\currentvcell>\zeropoint
           \ifdim\dp\OTRSETgridcell\currenthcell\currentvcell=\zeropoint
             \bgroup
             \setbox\scratchbox\OTRSETgetgridcell\currenthcell\currentvcell
             \getnoflines{\ht\scratchbox}%
             \!!counta\currentvcell
             \advance\!!counta -\noflines
             \advance\!!counta \plusone
             % first col always ok
             \!!countb\currenthcell
             \!!countc\currenthcell
             \advance\!!countc \plusone
             \!!donebtrue
             \ifcentergridcellonly
               \!!countc\maxdimen
             \fi
             \dostepwiserecurse\!!countc\nofcolumns\plusone
               {\if!!doneb
                  \let\xrecurselevel\recurselevel
                  \dostepwiserecurse\!!counta\currentvcell\plusone
                    {\ifdim\ht\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
                       \!!donebfalse
                     \else\ifdim\wd\OTRSETgridcell\xrecurselevel\recurselevel>\zeropoint
                       \!!donebfalse
                     \fi\fi}%
                  \if!!doneb
                    \!!countb\xrecurselevel
                  \fi
                \fi}%
             \totalcolumnspace\OTRSETlocalwidth\currenthcell
             \dostepwiserecurse\!!countc\!!countb\plusone
               {\advance\totalcolumnspace \OTRSETlocalwidth\recurselevel
                \advance\totalcolumnspace \OTRSETgetparameter\c!afstand\recurselevel}%
             \ifdim\totalcolumnspace>\wd\scratchbox
               \setbox\scratchbox\hbox to \totalcolumnspace{\hss\box\scratchbox\hss}%
             \fi
             \OTRSETsetgridcell\currenthcell\currentvcell\box\scratchbox
           \egroup
           \fi
           \fi}}%
   \fi}

\def\OTRSETinitializecolumns% once per page
  {\columnspreadtrue % todo
   \ifcolumnspread
     \global\rofcolumns\getvalue{\??mc\OTRSETidentifier\c!nrechts}%
     \global\lofcolumns\getvalue{\??mc\OTRSETidentifier\c!nlinks}%
     \global\tofcolumns\rofcolumns \relax
     \ifodd\realpageno\relax
       \global\nofcolumns\rofcolumns
     \else
       \global\advance\tofcolumns\lofcolumns
       \global\nofcolumns\lofcolumns
     \fi
   \else
     \global\nofcolumns\getvalue{\??mc\OTRSETidentifier\c!n}%
     \global\rofcolumns\nofcolumns
     \global\lofcolumns\nofcolumns
     \global\tofcolumns\nofcolumns
   \fi
   \OTRSETassignwidths
   \global\mofcolumns\plusone
   \columnerasegridboxes}

% vanaf hier:

\def\definecolumnset
  {\dodoubleargument\dodefinecolumnset}

\def\dodefinecolumnset[#1][#2]%
  {\getparameters[\??mc#1]
     [\c!richting=\v!rechts,
      \c!balanceren=\v!nee,
      \c!afstand=1.5\bodyfontsize, % controleren
      \c!n=2,
      \c!nlinks=\getvalue{\??mc#1\c!n},
      \c!nrechts=\getvalue{\??mc#1\c!n},
      \c!breedte=\v!passend,
      \c!regels=0,
      #2]%
   \dorecurse{\getvalue{\??mc#1\c!nlinks}} % todo
     {\dododefinecolumnset[#1][\recurselevel]}%
   \dorecurse{\getvalue{\??mc#1\c!nrechts}} % todo
     {\dododefinecolumnset[#1][\recurselevel]}%
   % redo framed settings
   \setupcolumnset[#1][1][\c!afstand=\!!zeropoint]}

\def\dododefinecolumnset[#1][#2]%
  {\presetlocalframed
     [\??mc#1#2]%
   \setupcolumnset
     [#1][#2]
     [\c!offset=\v!overlay,
      \c!kader=\v!uit,
      \c!uitlijnen=,
      \c!regels=0,% really needed since c!regels is now part of framed
      \c!breedte=\getvalue{\??mc#1\c!breedte},
      \c!afstand=\getvalue{\??mc#1\c!afstand}]}

\def\setupcolumnset
  {\dotripleargument\dosetupcolumnset}

\def\dosetupcolumnset[#1][#2][#3]%
  {\ifthirdargument
     \def\docommando##1%
       {\doifelse{##1}\v!elk
          {\dorecurse{\getvalue{\??mc#1\c!n}}{\docommando\recurselevel}}
          {\getparameters[\??mc#1##1][#3]}}%
     \processcommalist[#2]\docommando
   \else
     \getparameters[\??mc#1][#2]%
   \fi}

\definecolumnset[\s!default][\c!n=2] % fallback

\def\OTRSETgotonextpage
  {\vfill\eject
   \relax\ifnum\mofcolumns>\plusone
     \OTRSETgotocolumn[\v!laatste]%
     \ifnum\mofcolumns>\plusone
       \OTRSETgotocolumn[\v!forceer]%
     \fi
   \fi}

\let\OTRSETgotonextpageX\OTRSETgotonextpage % will become obsolete

\def\OTRSETgotocolumn
  {\dosingleempty\doOTRSETgotocolumn}

% \def\doOTRSETgotocolumn[#1]% first|last|yes|<number>
%   {\doifnumberelse{#1}
%      {\OTRSETdummycolumn
%       \doloop
%         {\ifnum\mofcolumns<#1\relax
%            \OTRSETdummycolumn
%          \else
%            \exitloop
%          \fi}}
%      {\processallactionsinset
%         [#1]
%         [     \v!ja=>\OTRSETdummycolumn,
%          \v!forceer=>\OTRSETdummycolumn,
%           \v!eerste=>{\doOTRSETgotocolumn[1]},
%          \v!laatste=>\expanded{\doOTRSETgotocolumn[\the\nofcolumns]},
%          \s!default=>\OTRSETdummycolumn]}}

% \def\doOTRSETgotocolumn[#1]% first|last|yes|<number>
%   {\doifnumberelse{#1}
%      {\ifnum\mofcolumns<#1\relax
%         \vfill\eject % \doejectpage\eject
%         \doloop
%           {\ifnum\mofcolumns<#1\relax
%              \OTRSETdummycolumn \else \exitloop
%            \fi}%
%       \fi}
%      {\processallactionsinset
%         [#1]
%         [     \v!ja=>\OTRSETdummycolumn,
%          \v!forceer=>\OTRSETdummycolumn,
%           \v!eerste=>{\doOTRSETgotocolumn[1]},
%          \v!laatste=>\expanded{\doOTRSETgotocolumn[\the\nofcolumns]},
%          \s!default=>\OTRSETdummycolumn]}}

\def\doOTRSETgotoCOLROW#1% <number>|<number>*<number>
  {\bgroup % really needed
   \splitstring#1\at*\to\column\and\row
   \bgroup
     \ifx\column\empty\else\expanded{\doOTRSETgotoCOLUMN{\column}}\fi
   \egroup
   \bgroup
     \ifx\row   \empty\else\expanded{\doOTRSETgotoROW   {\row   }}\fi
   \egroup
   \egroup}

\def\doOTRSETgotoCOLUMN#1%
  {\ifnum\mofcolumns=#1\else
     \vfill\eject % \doejectpage\eject
     \doloop
       {\ifnum\mofcolumns=#1\relax
          \exitloop \else \OTRSETdummycolumn
        \fi}%
   \fi}

\def\doOTRSETgotoROW#1%
  {\ifnum#1>1
     \scratchcounter\zerocount
     \currenthcell\mofcolumns
     \currentvcell#1\advance\currentvcell \minusone
     \dorecurse\currentvcell
       {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
          {\advance\scratchcounter\plusone}}
     \getnoflines\pagetotal
     \advance\scratchcounter-\noflines
     \ifnum\scratchcounter>\zerocount
       \dorecurse\scratchcounter{\line{\strut}}%
     \fi
   \fi
   \OTRSETsetvsize}

\def\doOTRSETgotocolumn[#1]% yes|force|first|last|<number>|<number>*<number>
  {\processallactionsinset
     [#1]
     [     \v!ja=>\OTRSETdummycolumn,
          \v!nee=>,% not supported
      \v!forceer=>\OTRSETdummycolumn,
       \v!eerste=>\expanded{\doOTRSETgotoCOLUMN{1}},
      \v!laatste=>\expanded{\doOTRSETgotoCOLUMN{\the\nofcolumns}},
      \s!default=>\OTRSETdummycolumn,
      \s!unknown=>\expanded{\doOTRSETgotoCOLROW{\commalistelement}}]}

% to be documented and tested, not yet that robust

% \def\OTRSETgotocell#1#2%
%   {\endgraf
%    \gdef\gotocellcounter{0}%
%    \doloop
%      {\ifnum\mofcolumns<#1\relax
%         \doglobal\increment\gotocellcounter\relax
%         \ifnum\gotocellcounter>#1\relax
%           \line{\strut}\crlf
%           \line{\strut}\crlf
%           \column
%           \writestatus{columnset}{quitting goto cell}%
%           \exitloop
%         \else
%           \column
%         \fi
%       \else
%         \exitloop
%       \fi}%
%    \ifnum\mofcolumns=#1\relax
%      \ifnum#2>1
%        \scratchcounter\zerocount
%        \currenthcell\mofcolumns
%        \currentvcell#2\advance\currentvcell \minusone
%        \dorecurse\currentvcell
%          {\OTRSETdoifcellelse\mofcolumns\recurselevel\donothing
%             {\advance\scratchcounter\plusone}}
%        \getnoflines\pagetotal
%        \advance\scratchcounter-\noflines
%        \ifnum\scratchcounter>\zerocount
%          \dorecurse\scratchcounter{\line{\strut}}%
%        \fi
%      \fi
%    \fi
%    \OTRSETsetvsize}

\def\OTRSETgotocell#1#2% obsolete: now \column[#1*#2]
  {\endgraf
   \doOTRSETgotoCOLUMN{#1}%
   \doOTRSETgotoROW   {#2}}

\def\OTRSETdummycolumn
  {\verticalstrut
   \vskip-\struttotal
   \vfill
   \eject}

\newcounter\columnsetlevel
\let\currentcolumnset\empty
\chardef\OTRSETfinish\zerocount

\def\startcolumnset
  {\dodoubleempty\dostartcolumnset}

\def\dostartcolumnset[#1][#2]%
  {\increment\columnsetlevel\relax
   \globallet\localcolumnmaxcells\!!zerocount
   \global\chardef\OTRSETfinish\zerocount
   \ifnum\columnsetlevel=\plusone
     \bgroup
     \globallet\columnsetpage\!!plusone
     \def\currentcolumnset{#2}%
     \binnenkolommentrue % will be different flag
     \activateotr{SET}{ONE}% andere naam, activate or so
     \doifelsenothing{#1}
       {\globallet\OTRSETlist\s!default}
       {\xdef\OTRSETlist{#1}}%
     \OTRSETstartnextpage
     \OTRSETassignwidths
     \OTRSETsethsize
   \else
     \bgroup
   \fi}

\def\stopcolumnset
  {\relax
   \ifnum\columnsetlevel=\plusone
     \endgraf % needed, else wrong vsize in one par case
     \global\chardef\OTRSETfinish\plusone
     % no, extra page \pagebreak % (test on pascal toc)
     \dostopcolumnset
     \egroup
     \global\footnotelimittrue
     \setvsize
     \sethsize
     \ifvoid\OTRfinalpagebox\else
       % probably balanced
       \ifdim\ht\OTRfinalpagebox<\teksthoogte
         \snaptogrid[\v!pagina]\hbox{\box\OTRfinalpagebox}%
       \else
         \box\OTRfinalpagebox
       \fi
     \fi
     \global\chardef\OTRSETfinish\zerocount
     \ifsomefloatwaiting \setvsize \pagebreak \setvsize \fi
   \else
     \egroup
   \fi
   \decrement\columnsetlevel\relax}

\def\dostopcolumnset
  {%\OTRSETdofinalflushfloats % yes/no
   \ifbalancecolumns
     \OTRSETdobalance
   \else
     \OTRSETnobalance
   \fi}

\def\OTRSETdobalance
  {\OTRSETnobalance}

\def\localcolumnmaxcells{0}

% currently line represents real line, i.e. on the grid, and
% not something noflines (also, watch out for switching from
% 2-3 columns on one page with both sets balanced: the
% second set does not see the first set

\chardef\OTRSETbottombalance\zerocount

% \def\OTRSETinitbalancing
%   {\ifbalancecolumns
%      \let\savedcolumnmaxcells\columnmaxcells
%      \ifnum\realpageno=\balancingpageno\relax
%        \ifnum\mofcolumns=\plusone
%          \dorecurse\nofcolumns
%            {\!!counta\recurselevel\relax
%             \!!countb\getvalue{\??mc\OTRSETidentifier\number\!!counta\c!regels}\relax
%             \ifcase\!!countb
%               \!!countb\getvalue{\??mc\OTRSETidentifier\c!regels}\relax
%             \fi
%             \ifcase\!!countb
%               \!!countb \savedcolumnmaxcells\relax
%             \fi
%             % can be an option: absolute versus relative
%             \ifcase\OTRSETbottombalance
%               \advance\!!countb\precolumnlines
%               \ifnum\!!countb>\localcolumnmaxcells\relax
%                 \xdef\localcolumnmaxcells{\the\!!countb}%
%               \fi
%               \advance\!!countb \plusone
%               \dostepwiserecurse\!!countb\columnmaxcells\plusone
%                 {\ifvoid\OTRSETgridcell\!!counta\recurselevel
%                    \OTRSETsetgridcell\!!counta\recurselevel\copy\placeholderboxe
%                  \fi}%
%             \else
%               \globallet\localcolumnmaxcells\columnmaxcells
%               \advance\!!countb-\columnmaxcells
%               \!!countb-\!!countb
%               \advance\!!countb \minusone
%               \ifnum\!!countb>\zerocount
%                 \dostepwiserecurse\plusone\!!countb\plusone
%                   {\ifvoid\OTRSETgridcell\!!counta\recurselevel
%                      \OTRSETsetgridcell\!!counta\recurselevel\copy\placeholderboxe
%                    \fi}%
%               \fi
%             \fi}%
%          \OTRSETsetvsize % ! ! !
%        \fi
%      \fi
%    \fi}
%
%  \def\OTRSETpresetbalancing
%    {\doifvaluesomething{\??mc\OTRSETidentifier\c!regels}%
%       {\getcommacommandsize[\csname\??mc\OTRSETidentifier\c!regels\endcsname]%
%        \ifnum\commalistsize>\plusone
%          \scratchcounter\zerocount
%          \def\docommando##1%
%            {\advance\scratchcounter\plusone
%             \setvalue{\??mc\OTRSETidentifier\the\scratchcounter\c!regels}{##1}}%
%          \processcommacommand
%            [\csname\??mc\OTRSETidentifier\c!regels\endcsname]\docommando
%          \setvalue{\??mc\OTRSETidentifier\c!regels}{0}%
%        \fi}}

% don't loose empty 1page/1column with area (example **)
%
% \definecolumntextarea[title][x=1,y=4,nx=2,ny=7,state=start]
% \setupcolumntextareatext[title][\vtop to 5cm{a\\b\\b\\d}]
%
% \starttext
% \startcolumnset \dorecurse{1}{\input tufte \par} \stopcolumnset
% \stoptext

% better:

\def\definecolumnsetarea   {\definecolumntextarea}
\def\setupcolumnsetarea    {\setupcolumntextarea}
\def\setupcolumnsetareatext{\setupcolumntextareatext}

% so this will be changed

\def\OTRSETnobalance
  {\iflastcolumnfootnotes % testen ! optie
     % inhibit flush of floats !
     % todo: nothing if no footnotes, else empty page
     \dostepwiserecurse\mofcolumns\nofcolumns\plusone
       {\vskip-\struttotal\verticalstrut\vfill\eject}%
   \else
     \ifdim\pagetotal>\zeropoint % no, see example **
       \ifnum\mofcolumns=\nofcolumns
         \OTRSETflushfinalfootnotes
       \else
         % probably todo
       \fi
       \vfill
       \eject
       % brr, may result in empty page after nicely fit text
       % or if left, then lost of first column only text
       \ifnum\mofcolumns>1
         \OTRSETdofinalflush
         \OTRSETdofinaloutput
       \fi
     \fi
   \fi}

\def\OTRSETstartnextpage
  {\doifsomething\OTRSETlist
     {\getfromcommacommand[\OTRSETlist][1]%
      \global\let\OTRSETidentifier\commalistelement
      \doifundefined{\??mc\OTRSETidentifier\c!n}
        {\globallet\OTRSETidentifier\s!default}%
      \let\newcommalistelement\empty
      \doglobal\replaceincommalist\OTRSETlist1%
      \OTRSETrestart}}

\def\OTRSETrestart % weed
  {\OTRSETinitializefeatures
   \OTRSETflushpreposttext
   \OTRSETinitializecolumns
   \OTRSETcheckinsert
   \OTRSETcheckgrid
   \OTRSETsetvsize
   \OTRSETsethsize % or local ?
   \OTRSETsetplaceholders
   \OTRSEThandlepreposttext
   \initializecolumntextareas % name !
   \OTRSETsetvsize}

\OTRSEToutput
  {\OTRSETnaturalflush
  %\OTRSETstartnextpage
   \OTRSETdoflushfloats % zou eigenlijk in \flushsavedfloats moeten (gaat fout)
   \OTRSETcheckfreelines
   \OTRSETchecksidefloat}

\def\OTRSETinitializefeatures
  {% number of lines
   % new: raw
   \getrawnoflines\teksthoogte\xdef\columnmaxcells{\the\noflines}%
   % direction
   \doifelsevalue{\??mc\OTRSETidentifier\c!richting}\v!rechts
     {\chardef\columndirection\zerocount}
     {\chardef\columndirection\plusone}%
   % balancing
   \balancecolumnsfalse
   \chardef\OTRSETbottombalance\zerocount
   \processaction
     [\getvalue{\??mc\OTRSETidentifier\c!balanceren}]
     [    \v!ja=>\balancecolumnstrue,
       \v!onder=>\chardef\OTRSETbottombalance\plusone
                 \balancecolumnstrue,
       \v!boven=>%chardef\OTRSETbottombalance\zerocount
                 \balancecolumnstrue]}

% keep 'm for a while
%
% \installoutput\OTRSETflushpreposttext
%  {\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}%
%   \ifcarryoverfootnotes \else
%     \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
%   \fi}
%
% to be tested on 'boekinhoud' in 'pascal/demo-bbi'
%
% junk ! ! ! ! !
%
%\installoutput\OTRSETflushpreposttext
%  {\global\setbox\precolumnbox\vbox
%     {\unvbox\normalpagebox
%      \strut\vskip-2\lineheight\strut}% we want a proper depth
%   \ifcarryoverfootnotes \else
%     \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
%   \fi}
%
% \starttext
%   \definecolumnset[two][n=2]
%   \startcolumnset[two] \dorecurse{4}{\input tufte } \stopcolumnset
%   \input tufte
%   \startcolumnset[two] \input tufte \stopcolumnset
% \stoptext
%
% \installoutput\OTRSETflushpreposttext
%   {\global\setbox\precolumnbox\vbox{\unvbox\normalpagebox}%
%    \global\dp\precolumnbox\strutdepth
%    \ifcarryoverfootnotes \else
%      \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
%    \fi}

% test:
%
% \definecolumnset[two]  [n=2,balance=yes]
% \definecolumnset[three][n=3,balance=yes]
% \setupcolumnset [two]  [1] [lines=10]
% \setupcolumnset [two]  [2] [lines=10]
%
% \startcolumnset[two]   \dorecurse{14}{\input tufte \par} \stopcolumnset
% \startcolumnset[three] \dorecurse{12}{\input tufte \par} \stopcolumnset
%
% with:
%
% \installoutput\OTRSETflushpreposttext
%   {%\ifvoid\normalpagebox
%    %  \global\setbox\precolumnbox\vbox{}%
%    %\else
%      \global\setbox\precolumnbox\vbox
%        {\unvcopy\normalpagebox}%
%      \global\setbox\precolumnbox\vbox to \ht\precolumnbox
%        {\box\normalpagebox}%
%    %\fi
%    \global\dp\precolumnbox\strutdepth
%    \ifcarryoverfootnotes \else
%      \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
%    \fi}

% testcase : pascal demo-bbi, paragraaf/aanduiding koppen

\ifx\lastskipinotr\undefined \newskip\lastskipinotr \fi

\installoutput\OTRSETflushpreposttext
  {\global\setbox\precolumnbox\vbox
     {\unvbox\normalpagebox
      \global\lastskipinotr\lastskip}%
   \ifdim\lastskipinotr>\zeropoint
     \global\setbox\precolumnbox\hbox
       {\lower\strutdepth\box\precolumnbox}%
   \fi
   \global\dp\precolumnbox\strutdepth
   \ifcarryoverfootnotes \else
     \global\setbox\postcolumnbox\vbox{\placebottomnotes}%
   \fi}

\let\precolumnlines \!!zerocount
\let\postcolumnlines\!!zerocount

\def\OTRSEThandlepreposttext
  {\ifdim\ht\precolumnbox>\zeropoint % new
     \getnoflines{\ht\precolumnbox}%
     \edef\precolumnlines{\the\noflines}%
     \doOTRSETsetgridcells
       {\copy\placeholderboxe}
       \plusone\plusone\nofcolumns\noflines
       {\box\precolumnbox}%
   \else
     \let\precolumnlines\!!zerocount
   \fi
   \ifdim\ht\postcolumnbox>\zeropoint % new, otherwise empty bottom line
     \getnoflines{\ht\postcolumnbox}%
     \edef\postcolumnlines{\the\noflines}%
     \advance\columnfreecells -\noflines
     \advance\columnfreecells \plusone
     \doOTRSETsetgridcells
       {\copy\placeholderboxe}
       \plusone\columnfreecells\nofcolumns\noflines
       {\box\postcolumnbox}%
   \else
     \let\postcolumnlines\!!zerocount
   \fi}

\def\OTRSETchecksidefloat
  {} % {\sidefloatoutput}

\def\OTRSETfinalsidefloatoutput
  {}

\def\OTRSETcheckgrid
  {\topskip1\topskip
   \ifforcecolumngrid
     \widowpenalty\zerocount
     \clubpenalty\zerocount
     \brokenpenalty\zerocount
   \fi}

\def\OTRSETcheckinsert%
  {\iflastcolumnfootnotes
     \ifnum\nofcolumns=\mofcolumns
       \OTRSETforceinserts
     \else
       \OTRSETinhibitinserts
     \fi
   \else
     \OTRSETforceinserts
   \fi}

\def\OTRSETforceinserts
  {\enablenotes}

\def\OTRSETinhibitinserts
  {\disablenotes}

% interface to footnotes

%\def\OTRSETassignwidth#1\to#2%
%  {\doifelsevalue{\??mc#1\c!breedte}{\v!passend}
%     {#2=\zetbreedte
%      \scratchcounter=\getvalue{\??mc#1\c!nlinks}\relax
%\ifnum\getvalue{\??mc#1\c!nrechts}>\scratchcounter
%      \scratchcounter=\getvalue{\??mc#1\c!nrechts}%
%\fi
%      \dorecurse{\scratchcounter}
%        {\advance#2 -\getvalue{\??mc#1\recurselevel\c!afstand}}%
%      \divide#2 \scratchcounter}
%     {#2=\getvalue{\??mc#1\c!breedte}}}

%\def\OTRSETassignwidth#1\to#2% assumes mofcolumns
%  {\doifelsevalue{\??mc#1\number\mofcolumns\c!breedte}{\v!passend}
%     {#2=\zetbreedte
%      \scratchcounter=0
%      \dorecurse{\getvalue{\??mc#1\c!n}}
%        {\doifelsevalue{\??mc#1\number\recurselevel\c!breedte}{\v!passend}
%           {\advance\scratchcounter by 1 }
%           {\advance#2 by -\getvalue{\??mc#1\recurselevel\c!breedte}}%
%         \advance#2 by -\getvalue{\??mc#1\recurselevel\c!afstand}}%
%      \divide#2 by \scratchcounter}
%     {#2=\getvalue{\??mc#1\number\mofcolumns\c!breedte}}}
%
% replaced by
%
%\def\OTRSETassignwidth#1\to#2% assumes mofcolumns
%  {#2=\OTRSETlocalwidth\mofcolumns}

\def\OTRSETassignwidths
  {%\scratchdimen\zetbreedte
   \freezetextwidth \scratchdimen\tekstbreedte
   %
   \scratchcounter\zerocount
   \dorecurse\nofcolumns
     {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!breedte}\v!passend
        {\advance\scratchcounter \plusone }
        {\advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!breedte}}%
      \advance\scratchdimen -\getvalue{\??mc\OTRSETidentifier\recurselevel\c!afstand}}%
   \ifcase\scratchcounter\else
     \divide\scratchdimen \scratchcounter
   \fi
   \setgvalue{\??mc\??mc\c!breedte}{0}%
   \dorecurse\nofcolumns
     {\doifelsevalue{\??mc\OTRSETidentifier\recurselevel\c!breedte}\v!passend
        {\dimen0=\scratchdimen}
        {\setgvalue{\??mc\??mc\c!breedte}{1}%
         \dimen0=\getvalue{\??mc\OTRSETidentifier\recurselevel\c!breedte}}%
      \setxvalue{\??mc\recurselevel\??mc\c!breedte}{\the\dimen0}}}

\def\OTRSETlocalwidth#1%
  {\getvalue{\??mc\number#1\??mc\c!breedte}}

\newbox\placeholderboxa
\newbox\placeholderboxb
\newbox\placeholderboxc
\newbox\placeholderboxd
\newbox\placeholderboxe
\newbox\placeholderboxf

\def\columnplaceholder#1#2%
  {\hbox
     {\localcolortrue
      \setbox\scratchbox\hbox to \hsize
        {\iftracecolumnset \incolortrue \localcolortrue
           #2\hskip-.5ex\vrule\!!width1ex\!!height.5ex\!!depth.5ex\hss
         \fi
         \hss}%
      \ifcase#1\relax
        \ht\scratchbox\zeropoint
        \dp\scratchbox\zeropoint
        \wd\scratchbox\zeropoint
      \else
        \wd\scratchbox\hsize
        \ht\scratchbox\strutht
        \dp\scratchbox\strutdp
      \fi
      \box\scratchbox}}

\def\OTRSETsetplaceholders
  {\global\setbox\placeholderboxa\columnplaceholder0\cyan
   \global\setbox\placeholderboxb\columnplaceholder0\green
   \global\setbox\placeholderboxc\columnplaceholder0\blue
   \global\setbox\placeholderboxd\columnplaceholder0\red
   \global\setbox\placeholderboxe\columnplaceholder0\magenta
   \global\setbox\placeholderboxf\columnplaceholder1\darkgray}

\def\doOTRSETshowstatus
  {\llap{\incolortrue \localcolortrue \tt\tfxx\blue
     (\the\vsize->\number\columnfirstcell\#\number\columnfreecells)%
     \hskip\leftskip}}

\def\OTRSETshowstatus
  {\iftracecolumnset \doOTRSETshowstatus \fi}

\appendtoks \OTRSETshowstatus \to \everypar

% page contents

\def\OTRSETdopagecontents#1#2% takes two args: \box<n> \unvbox<n>
  {\vbox to \teksthoogte{\forgetall#1#2\pushcolor}}

\def\OTRSETsomepagefloat  {\def\floatmethod{PAGE}\OTRSETsomeslotfloat} % check
\def\OTRSETsomeherefloat  {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
\def\OTRSETsomeelsefloat  {\def\floatmethod{HERE}\OTRSETsomeslotfloat} % check
\def\OTRSETsomefixdfloat  {\def\floatmethod{FIXD}\OTRSETsomeslotfloat} % check
\def\OTRSETsometopfloat   {\def\floatmethod{TOPS}\OTRSETsomeslotfloat} % check
\def\OTRSETsomebottomfloat{\def\floatmethod{BOTS}\OTRSETsomeslotfloat} % check

% \def\OTRSETsomeslotfloat {\let\floatmethod\v!hier\OTRONEsomeelsefloat}

\def\OTRSETflushfloatbox% nog verder doorvoeren en meer info in marge
  {\iftestfloatbox\ruledhbox\fi{\box\floatbox}}

\def\OTRSETsomeslotfloat[#1]%
  {\setbox\floatbox\vbox{\flushfloatbox}%
   \dp\floatbox\strutdp
   \@EA\uppercasestring\floatmethod\to\floatmethod
   \OTRSETstoreincolumnslot\floatmethod\floatbox
   \doinsertfloatinfo}

% kind of new, looks much like OTRONE, but not entirely

\def\OTRSETdosettopinserts
  {\bgroup
   \ifsomefloatwaiting
     \noffloatinserts\zerocount
     \let\totaltopinserted\!!zeropoint
     \OTRSETdodosettopinserts
     \ifnum\@@bknonder=\zerocount
       \ifnum\@@bknregels>\zerocount
         \ifdim\totaltopinserted>\zeropoint\relax
           \dimen0\lineheight
           \dimen0=\@@bknregels\dimen0
           \advance\dimen0 \totaltopinserted\relax
           \ifdim\dimen0>\teksthoogte % \vsize  %%%%%%%%% \teksthoogte
             \showmessage\m!floatblocks8{\@@bknregels}%
             \vfilll\eject
           \fi
         \fi
       \fi
     \fi
   \fi
   \egroup}

\def\OTRSETdodosettopinserts
  {\ifnum\noffloatinserts<\noftopfloats
     \dogetfloat
     \ifdim\topinserted=\zeropoint\relax
       \topofinserttrue
     \else
       \topofinsertfalse
     \fi
     \setbox\scratchbox\vbox % kan beter !
       {\forgetall
        \iftopofinsert
          \ifdim\OTRSETtopoffset=\zeropoint
            \verplaatsopgrid[\v!boven]
          \fi
        \else
          \betweenfloatblanko % inserts can't look back
        \fi
        \flushfloatbox
        \blanko[\@@bknawit]}%
     \global\advance\topinserted \ht\scratchbox\relax
     \ifdim\topinserted>\vsize % was \teksthoogte\relax
       \OTRSETresavebox\floatbox
       \noffloatinserts\noftopfloats\relax
       \global\advance\topinserted -\ht\scratchbox
       \let\OTRSETdodosettopinserts\relax % to be tested
     \else
       \xdef\totaltopinserted{\the\topinserted}%
       \insert\topins{\forgetall\box\scratchbox}% interlineskip ?
       \ifsomefloatwaiting
         \advance\noffloatinserts \plusone
       \else
         \noffloatinserts\noftopfloats\relax
       \fi
       \dofloatflushedinfo
     \fi
   \else
     \ifsomefloatwaiting
       \showmessage\m!floatblocks6{\the\noftopfloats}%
     \fi
     \let\OTRSETdodosettopinserts\relax
   \fi
   \OTRSETdodosettopinserts}

\def\OTRSETdosetbotinserts
  {\bgroup
   \ifsomefloatwaiting
     \noffloatinserts\zerocount
     \OTRSETdodosetbotinserts
   \fi
   \egroup}

\def\OTRSETdodosetbotinserts
  {\ifnum\noffloatinserts<\nofbotfloats\relax
     \dogetfloat
     \global\advance\botinserted \ht\floatbox\relax
     \global\advance\botinserted \dp\floatbox\relax
     \global\advance\botinserted \floattopskip\relax
     \ifdim\botinserted<\pagegoal\relax
       \insert\botins
         {\forgetall
          \blanko[\@@bkvoorwit]%
          \flushfloatbox}%
       \ifsomefloatwaiting
         \advance\noffloatinserts \plusone
       \else
         \noffloatinserts\nofbotfloats
       \fi
       \dofloatflushedinfo
     \else
       \OTRSETresavebox\floatbox
       \noffloatinserts\nofbotfloats\relax
     \fi
     \global\nofloatpermittedtrue % vgl topfloats s!
   \else
     \ifsomefloatwaiting
       \showmessage\m!floatblocks7{\the\nofbotfloats}%
     \fi
     \let\OTRSETdodosetbotinserts\relax
   \fi
   \OTRSETdodosetbotinserts}

\let\OTRSETdosetbothinserts\relax

\def\OTRSETdotopinsertions
  {\ifvoid\topins\else
     \ifvoid\columntopbox\mofcolumns
       \columnsettopbox\mofcolumns\box\topins
     \else
       \columnsettopbox\mofcolumns\vbox % temp, must be better
         {\forgetall
          \offinterlineskip
          \box\columntopbox\mofcolumns
          \box\topins}
     \fi
   \fi
   \global\topinserted\zeropoint\relax} % goes away

\def\OTRSETdobotinsertions
  {\ifvoid\botins \else
     \columnsetbotbox\mofcolumns\box\botins
%   \else
%     \columnsetbotbox\mofcolumns\vbox % temp, must be better
%       {\forgetall
%        \offinterlineskip
%        \box\botins
%        \box\columnbotbox\mofcolumns}
   \fi
   \global\botinserted\zeropoint\relax} % goes away

% set ipv text

% left right 1 2 3 +1 +2 +3

\let\columnleftareas \empty
\let\columnrightareas\empty

% links rechts => odd, even, n, named

\def\definecolumntextarea
  {\dotripleempty\dodefinecolumntextarea}

\def\dodefinecolumntextarea[#1][#2][#3]% y=0 is mogelijke en handig !
  {\ifthirdargument
     \doifinsetelse{#2}{\v!beide,\v!vast}
       {\definecolumntextarea[#1][\v!links ][\c!type=#2,#3]%
        \definecolumntextarea[#1][\v!rechts][\c!type=#2,#3]}
       {\doifelse{#2}\v!volgende
          {\doifoddpageelse
             {\definecolumntextarea[#1][\v!rechts][\c!type=#2,#3]}
             {\definecolumntextarea[#1][\v!links ][\c!type=#2,#3]}}
          {\presetlocalframed
             [\??mt#1#2]%
           \processaction[#2] % \doglobal voorkomt stack build up
             [ \v!links=>\doglobal\addtocommalist{#1}\columnleftareas,
              \v!rechts=>\doglobal\addtocommalist{#1}\columnrightareas]%
           \getparameters[\??mt#1#2]
             [\c!x=1,\c!y=1,\c!nx=1,\c!ny=1,\c!clipoffset=2\lineheight,
              \c!offset=\v!overlay,\c!strut=\v!nee,\c!kader=\v!uit,
              \c!type=#2,\c!pagina=1,\c!status=\v!stop,#3]}}%
   \else
     \definecolumntextarea[#1][\v!volgende][#2]%
   \fi}

\def\setupcolumntextarea
  {\dotripleempty\dosetupcolumntextarea}

\def\dosetupcolumntextarea[#1][#2][#3]%
  {\ifthirdargument
     \doifelse{#2}\v!beide
       {\setupcolumntextarea[#1][\v!links ][#3]%
        \setupcolumntextarea[#1][\v!rechts][#3]}
       {\doifelse{#2}\v!volgende
          {\doifoddpageelse
             {\setupcolumntextarea[#1][\v!rechts][#3]}
             {\setupcolumntextarea[#1][\v!links][#3]}}
          {\getparameters[\??mt#1#2][#3]}}%
   \else
     \setupcolumntextarea[#1][\v!volgende][#2]%
   \fi}

\def\docheckcolumnsetareapage#1#2%
  {\ifnum\getvalue{\??mt#1\c!pagina}>\plusone
     \doifelsevalue{\??mt#1\c!type}\v!vast
       {\ifnum\columnsetpage=\getvalue{\??mt#1\c!pagina}\relax
          \donetrue\else\donefalse
        \fi}
       {\ifnum\columnsetpage<\getvalue{\??mt#1\c!pagina}\relax
          \donefalse\else\donetrue
        \fi}%
   \else
     \donetrue
   \fi}

\def\initializecolumntextareas
  {\ifodd\realpageno
     \doinitializecolumntextareas\columnrightareas\v!rechts
   \else
     \doinitializecolumntextareas\columnleftareas\v!links
   \fi}

%\def\doinitializecolumntextareas#1#2%
%  {\def\docommando##1%
%     {\doifelsevalue{\??mt##1#2\c!status}\v!start
%        {\dodoinitializecolumntextareas{##1}{#2}}
%        {\doifvalue{\??mt##1#2\c!status}\v!herhaal
%           {\dodoinitializecolumntextareas{##1}{#2}}}}%
%   \processcommacommand[#1]\docommando}

\def\doinitializecolumntextareas#1#2%
  {\def\docommando##1%
     {\docheckcolumnsetareapage{##1#2}\plusone
      \ifdone
        \donefalse
        \processaction
          [\getvalue{\??mt##1#2\c!status}]
          [  \v!start=>\donetrue,
           \v!herhaal=>\donetrue,
           \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
        \ifdone\dodoinitializecolumntextareas{##1}{#2}\fi
      \fi}%
   \processcommacommand[#1]\docommando}

\def\dodoinitializecolumntextareas#1#2%
  {\doOTRSETsetgridcells
     {\copy\placeholderboxd}
     {\getvalue{\??mt#1#2\c!x }}{\getvalue{\??mt#1#2\c!y }}
     {\getvalue{\??mt#1#2\c!nx}}{\getvalue{\??mt#1#2\c!ny}}
     {\copy\placeholderboxd}}

\def\placecolumntextareas
  {\ifodd\realpageno
     \doplacecolumntextareas\columnrightareas\v!rechts
   \else
     \doplacecolumntextareas\columnleftareas\v!links
   \fi}

%\def\doplacecolumntextareas#1#2% global ?
%  {\bgroup
%   \forgetall
%   \def\docommando##1%
%     {\doifelsevalue{\??mt##1#2\c!status}\v!start
%        {\doglobal\removefromcommalist{##1}#1%
%         \dodoplacecolumntextareas{##1}{#2}}
%        {\doifvalue{\??mt##1#2\c!status}\v!herhaal
%           {\dodoplacecolumntextareas{##1}{#2}}}}%
%   \processcommacommand[#1]\docommando
%   \egroup}

\def\doplacecolumntextareas#1#2% global ?
  {\bgroup
   \forgetall
   \def\docommando##1%
     {\docheckcolumnsetareapage{##1#2}\zerocount
      \ifdone
        \donefalse
        \processaction
          [\getvalue{\??mt##1#2\c!status}]
          [  \v!start=>\donetrue\doglobal\removefromcommalist{##1}#1,
           \v!herhaal=>\donetrue,
           \s!unknown=>\doperformtest\commalistelement\donetrue\donefalse]%
        \ifdone
          \dodoplacecolumntextareas{##1}{#2}
        \else
          \doglobal\removefromcommalist{##1}#1%
        \fi
      \fi}%
   \processcommacommand[#1]\docommando
   \egroup}

\def\columntextlastbackspace{\rugwit}

% beware, we have clipping offsets of 2\lineheight by default

\def\columntextareaparameter#1%
  {\csname\??mt\currentcolumntestarea#1\endcsname}

\def\dodoplacecolumntextareas#1#2%
  {\def\currentcolumntestarea{#1#2}%
   \!!counta\columntextareaparameter\c!x
   \!!countb\columntextareaparameter\c!nx
   \docalculatecolumnsetspan
   \!!heighta\columntextareaparameter\c!ny\lineheight
   % wrong
   % \ifnum\columntextareaparameter\c!y=\zerocount
   %   \advance\!!heighta -\lineheight
   %   \advance\!!heighta \topskip
   % \fi
   % \advance\!!heighta -\lineheight % option
   \ifnum\columntextareaparameter\c!y=\plusone
     \advance\!!heighta -\lineheight
     \advance\!!heighta \topskip
   \fi
   %
   \setbox\scratchbox\vbox
     {\donetrue\localframed
        [\??mt\currentcolumntestarea]
        [\c!plaats=,% new (*)
         \c!breedte=\!!widtha,\c!hoogte=\!!heighta,\c!regels=]
        {\columntextareaparameter\empty}}%
   \!!counta\columntextareaparameter\c!x
   \!!countb\columntextareaparameter\c!y
   \advance\!!countb \columntextareaparameter\c!ny
   \advance\!!countb \minusone
   % new (*)
   \doif{\columntextareaparameter\c!plaats}\v!diepte
     {\setbox\scratchbox\hbox{\lower\strutdepth\box\scratchbox}%
      \dp\scratchbox\zeropoint
      \ht\scratchbox\!!heighta}%
   %
   \setbox0\hbox
     {\ifcase\!!countc
        \copy\scratchbox % \box
      \else
        \clip
          [%\c!bovenoffset=\columntextareaparameter\c!clipoffset,%
           %\c!onderoffset=\columntextareaparameter\c!clipoffset,%
           %\c!linkeroffset=\columntextareaparameter\c!clipoffset,%
           \c!offset=\columntextareaparameter\c!clipoffset,%
           \c!rechteroffset=\zeropoint,%
           \c!breedte=\!!widthb,%
           \c!hoogte=\!!heighta]%
          {\copy\scratchbox}%
      \fi}%
   \OTRSETsetgridcell\!!counta\!!countb\box0
   \ifcase\!!countc\else
     \advance\!!counta \columntextareaparameter\c!nx
     \advance\!!counta -\!!countc
     \advance\!!widtha -\!!widthb
     \setbox0\hbox
       {\hskip-\namedlayoutparameter\v!oneven\c!rugwit
        \clip
          [%\c!bovenoffset=\columntextareaparameter\c!clipoffset,%
           %\c!onderoffset=\columntextareaparameter\c!clipoffset,%
           %\c!rechteroffset=\columntextareaparameter\c!clipoffset,%
           \c!offset=\columntextareaparameter\c!clipoffset,%
           \c!linkeroffset=\zeropoint,%
           \c!breedte=\!!widtha,%
           \c!hoogte=\!!heighta,%
           \c!hoffset=\!!widthb]%
          {\copy\scratchbox}}%
     \OTRSETsetgridcell\!!counta\!!countb\box0%
   \fi}

\def\setupcolumntextareatext
  {\dotripleempty\dosetupcolumntextareatext}

\long\def\dosetupcolumntextareatext[#1][#2][#3]%
  {\ifthirdargument
     \doifelse{#2}\v!beide
       {\setvalue{\??mt#1\v!links }{#3}%
        \setvalue{\??mt#1\v!rechts}{#3}}
       {\doifelse{#2}\v!volgende
          {\doifoddpageelse
             {\setvalue{\??mt#1\v!rechts}{#3}}%
             {\setvalue{\??mt#1\v!links }{#3}}}%
          {\setvalue{\??mt#1#2}{#3}}}%
   \else
     \setupcolumntextareatext[#1][\v!volgende][{#2}]%
   \fi}

\def\docalculatecolumnsetspan
  {% \!!counta <= x
   % \!!countb <= nx
   % \!!widtha => total width
   % \!!widthb => left width
   % \!!countc => left cols
   \!!widtha\!!countb\tekstbreedte % we assume equal widths
   \advance\!!countb \!!counta
   \advance\!!countb \minusone
   \ifnum\!!countb>\nofcolumns
     \!!countc\!!countb
     \advance\!!countc -\nofcolumns
     \!!countb\nofcolumns
   \else
     \!!countc\zerocount
   \fi
   \advance\!!counta \plusone
   \dostepwiserecurse\!!counta\!!countb\plusone
     {\advance\!!widtha\OTRSETgetparameter\c!afstand\recurselevel}%
   \!!widthb\!!widtha
   \advance\!!widthb -\!!countc\tekstbreedte
   \ifodd\realpageno \else % tricky, assumes that we keep there
     \ifcase\!!countc\else
       % nog niet ok voor enkel/dubbelzijdig
       \advance\!!widtha \namedlayoutparameter\v!even  \c!rugwit
       \advance\!!widtha \namedlayoutparameter\v!oneven\c!rugwit
       \advance\!!widthb \namedlayoutparameter\v!even  \c!rugwit
       \dorecurse\!!countc
         {\advance\!!widtha\OTRSETgetparameter\c!afstand\recurselevel}%
     \fi
   \fi}

\def\columnsetspanhsize{\tekstbreedte}

\def\setcolumnsetspanhsize#1#2% x nx / uses counta/b
  {\!!counta#1\!!countb#2\docalculatecolumnsetspan
   \edef\columnsetspanhsize{\the\!!widtha}}

\def\definecolumnsetspan
  {\dodoubleempty\dodefinecolumnsetspan}

\def\dodefinecolumnsetspan[#1][#2]%
  {%\ifsecondargument
     \defineframedtext
       [cs:#1]
       [\c!kader=\v!uit,
        \c!voor=,
        \c!na=,
        \c!offset=\v!overlay,
        \c!plaats=\v!links,
        \c!regelcorrectie=\v!uit,
        \c!dieptecorrectie=\v!uit,
        \c!n=2,
        \c!nregels=0,
        \c!springvolgendein=\v!ja,
        \c!default=HERE,
        \c!variant=\v!a,
        #2]%
   %\else
   %  \definecolumnspan[][#1]%
  }%\fi}

\definecolumnsetspan[\s!default]

\def\setupcolumnsetspan
  {\dodoubleempty\dosetupcolumnsetspan}

\def\dosetupcolumnsetspan[#1][#2]%
  {\ifsecondargument
     \setupframedtexts[cs:#1][#2]%
   \else
     \setupcolumnsetspan[\s!default][#1]%
   \fi}

\def\startcolumnsetspan
  {\dotripleempty\dostartcolumnsetspan}

%%%%%%%%%%%%%%%% TODO

\def\dostartcolumnsetspan[#1][#2][#3]% [#3] gobbles space
  {\endgraf % else rubish output if forgotten
   \vskip \zeropoint % make sure otr is done, otherwise last line problems
   \bgroup
\forgetall
   \setupframedtexts[cs:#1]
     [\c!breedte=\columnsetspanhsize,
      \c!regelcorrectie=\v!uit,
      \c!dieptecorrectie=\v!uit,
      #2]%
   % determine widths
   \!!countc\framedtextparameter{cs:#1}\c!n
    % \!!countd\numexpr(\nofcolumns-\mofcolumns+\plusone)%
   \!!countd\nofcolumns
   % n <= n of columns
   \ifnum\!!countc>\!!countd \!!countc\!!countd \fi
   \advance\!!countd -\mofcolumns
   \advance\!!countd \plusone
   % n <= n of available columns (alternative a)
   \doif{\framedtextparameter{cs:#1}\c!variant}\v!a
     {\ifnum\!!countc>\!!countd \!!countc\!!countd \fi}%
   % here it all starts
   \setcolumnsetspanhsize\mofcolumns\!!countc % a/b used
   \hsize\columnsetspanhsize
   \setbox\scratchbox\vbox\bgroup
     \dostartframedtext[cs:#1][\v!geen]% geen nils placement
     \vskip-\struttotal\par\verticalstrut\par
     \framedtextparameter{cs:#1}\c!voor
     \def\stopcolumnsetspan{\dostopcolumnsetspan{#1}}}

% \chardef\columnslotlocation2

\def\dostopcolumnsetspan#1%
  {\par
   \verticalstrut
   \kern-2\struttotal
   \verticalstrut
   \doifsomething{\framedtextparameter{cs:#1}\c!na}
     {\framedtextparameter{cs:#1}\c!na
      \kern\zeropoint}% otherwise blanks disappear, better be a switch
   \dostopframedtext
   \egroup
   % frozen keeps grid snapping okay
   \setbox\scratchbox\frozenhbox to \hsize
     {\dontcomplain
      \alignedline{\framedtextparameter{cs:#1}\c!plaats}\v!midden
        {\lower\strutdepth\box\scratchbox}}%
   \dp\scratchbox\zeropoint % else wrong snap insidefloat
%
% to be tested first:
%
% \setbox\scratchbox\frozenhbox to \hsize
%   {\dontcomplain
%    \chardef\alignstrutmode\zerocount
%    \alignedline{\framedtextparameter{cs:#1}\c!plaats}\v!midden
%      {\box\scratchbox}}%
%
   \ifinsidefloat
     \box\scratchbox
   \else
     % we only set \columnsetspacing when asked for, else bottom problems
     % don't change this any more (test naw)
     \chardef\columnslotspacing\framedtextparameter{cs:#1}\c!nregels\relax
     % todo: nboven/onder & \chardef\columnslotlocation2
     %\OTRSETstoreincolumnslotHERE\scratchbox
     \edef\floatmethod{\framedtextparameter{cs:#1}\c!default}%
     \@EA\uppercasestring\floatmethod\to\floatmethod
     % todo : \v!hier -> here enzovoorts
     \OTRSETstoreincolumnslot\floatmethod\scratchbox
     % watch out: no \dochecknextindentation{tag}
     \checknextindentation[\framedtextparameter{cs:#1}\c!springvolgendein]
   \fi
   \egroup
   \endgraf}

% \startcolumnset[two]
%   \input tufte
%   \startcolumnsetspan[two][width=20cm,location=middle] \input tufte \stopcolumnsetspan
%   \startcolumnsetspan[two][default=btlr] \input tufte \stopcolumnsetspan
%   \input tufte \par
%   \input tufte \par
%   \startcolumnsetspan[two] \emptylines[5] \stopcolumnsetspan
%   \startcolumnsetspan[two] \input tufte   \stopcolumnsetspan
% \stopcolumnset

\protect \endinput
