%D \module
%D   [       file=core-ntb,
%D        version=2000.04.18,
%D          title=\CONTEXT\ Core Macros,
%D       subtitle=Natural Tables,
%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.

%D This is an unfinished, preliminary module. At least two
%D runs are needed to get the table fixed.

% optie=rek beschrijven

\writestatus{loading}{Context Core Macros / Natural Tables}

%D As always, this is the nth version. Much time went in
%D trying to speed up the many cell calculations, some
%D optimizations were rejected in order not to complicate this
%D module too much (and in order to prevail extensibility).

%D To Do:
%D
%D \starttypen
%D break over pagina
%D kop herhalen
%D reset settings
%D
%D \setupTABLE [c|column|x]            [nx|odd|even|first|last][a=b]
%D \setupTABLE [r|row   |y]            [nx|odd|even|first|last][a=b]
%D \setupTABLE [nx|odd|even|first|last][ny|odd|even|first|last][a=b]
%D \setupTABLE [nx|odd|even|first|last]                        [a=b]
%D \setupTABLE                                                 [a=b]
%D
%D \bTH \eTH
%D \stoptypen

% the section setup does not work yet, data needs to be stored,
% i.e.each row should know if it's a head/body/foot, and there
% should be \setupTABLE[head]... and alike

\unprotect

%D A simple way to force equal line spacing is to say:
%D
%D \starttypen
%D \def\bTBLCELL{\begstrut}
%D \def\eTBLCELL{\endstrut}
%D \stoptypen

%D However, the next alternative also takes care of preceding
%D and following white space.

\def\bTBLCELL
  {\inhibitblank\doconvertfont\tbltblletter\empty\everypar{\begstrut}}

\def\eTBLCELL
  {\ifhmode
     \endstrut
   \else
     \par
     \ifdim\prevdepth<\zeropoint % =-1000pt ?
       \vskip-\strutdp
     \else
       \removebottomthings
     \fi
   \fi}

\newcounter\currenttbl

\def\@@tbl{tbl}  \def\tblcell{1}  \def\tblnone{2}

\def\@@tblprefix{tbl:} \let\@@rawtblprefix\@@tblprefix

%D This should be done more efficient:

\def\settbltag#1#2#3{\setevalue{\@@tblprefix#1:#2:s}{#3}} % \number#3
\def\settblcol#1#2#3{\setevalue{\@@tblprefix#1:#2:c}{#3}}
\def\settblrow#1#2#3{\setevalue{\@@tblprefix#1:#2:r}{#3}}

\def\settblwd #1#2#3{\setxvalue{\@@tblprefix#1:#2:wd}{#3}} % global !
\def\settblht #1#2#3{\setxvalue{\@@tblprefix#1:#2:ht}{#3}} % global !

\def\gettbltag#1#2{\csname\@@tblprefix#1:#2:s\endcsname}
\def\gettblcol#1#2{\csname\@@tblprefix#1:#2:c\endcsname}
\def\gettblrow#1#2{\csname\@@tblprefix#1:#2:r\endcsname}

\def\gettblwd #1#2{\csname\@@tblprefix#1:#2:wd\endcsname}
\def\gettblht #1#2{\csname\@@tblprefix#1:#2:ht\endcsname}

\def\settblwid#1#2{\setxvalue{\@@tblprefix#1:w}{#2}} % global !
\def\settblhei#1#2{\setxvalue{\@@tblprefix#1:h}{#2}} % global !
\def\settblaut#1#2{\setxvalue{\@@tblprefix#1:a}{#2}} % global !

%\def\gettblwid#1{\ifundefined{\@@tblprefix#1:w}\!!zeropoint\else\getvalue{\@@tblprefix#1:w}\fi}
%\def\gettblhei#1{\ifundefined{\@@tblprefix#1:h}\!!zeropoint\else\getvalue{\@@tblprefix#1:h}\fi}

\def\gettblwid#1{\executeifdefined{\@@tblprefix#1:w}\zeropoint}
\def\gettblhei#1{\executeifdefined{\@@tblprefix#1:h}\zeropoint}
\def\gettblaut#1{\csname\@@tblprefix#1:a\endcsname}

\def\doiftbltag    #1#2{\doifdefined    {\@@tblprefix#1:#2:s}}
\def\doifnottbltag #1#2{\doifundefined  {\@@tblprefix#1:#2:s}}
\def\doifelsetbltag#1#2{\doifdefinedelse{\@@tblprefix#1:#2:s}}
\def\doiftblrow    #1#2{\doifdefined    {\@@tblprefix#1:#2:r}}
\def\doiftblcol    #1#2{\doifdefined    {\@@tblprefix#1:#2:c}}
\def\doifnottblcol #1#2{\doifundefined  {\@@tblprefix#1:#2:c}}

% \def\settblspn#1#2{\setvalue     {\@@tblprefix#1:s}{#2}}
% \def\doiftblspn #1{\doifelsevalue{\@@tblprefix#1:s}{1}}

\newif\ifsqueezeTBLspan % \squeezeTBLspantrue

\def\settblspn     #1{\setvalue     {\@@tblprefix#1:s}{1}}
\def\doifelsetblspn#1{\doifelsevalue{\@@tblprefix#1:s}{1}}

\def\settbltxt#1#2{\long\setvalue{\@@tblprefix:#1:#2:t}}
\def\gettbltxt#1#2{\csname\@@tblprefix:#1:#2:t\endcsname}

%\def\doiftbl      #1#2#3{\ifcase0\getvalue{\@@tblprefix#1:#2:s}\relax  \else#3\fi}
%\def\doifnottbl   #1#2#3{\ifcase0\getvalue{\@@tblprefix#1:#2:s}\relax       #3\fi}
%\def\doifelsetbl#1#2#3#4{\ifcase0\getvalue{\@@tblprefix#1:#2:s}\relax#4\else#3\fi}
%
%\let\doiftbltag    \doiftbl
%\let\doifnottbltag \doifnottbl
%\let\doifelsetbltag\doifelsetbl

\newtoks\tbltoks

\let\pushTBLparameters\relax
\let\popTBLparameters \relax

\newif\ifautoTBLspread      \autoTBLspreadfalse
\newif\ifautoTBLhsize       \autoTBLhsizetrue
\newif\ifautoTBLrowspan     \autoTBLrowspantrue
\newif\ifautoTBLemptycell   \autoTBLemptycelltrue
\newif\ifautoTBLcheckwidth  \autoTBLcheckwidthtrue
\newif\ifappendTBLsetups    \appendTBLsetupstrue
\newif\ifenableTBLbreak     \enableTBLbreakfalse
\newif\ifmultipleTBLheads   \multipleTBLheadsfalse

\newif\iftraceTABLE         \traceTABLEfalse

\def\noftblheadlines{0}

\presetlocalframed[\@@tbl\@@tbl]

\long\def\handleTBLcell#1#2[#3]{}

\long\def\bTC#1\eTC{\bTD#1\eTD}
\long\def\bTX#1\eTX{\bTD#1\eTD}
\long\def\bTY#1\eTY{\bTR#1\eTR}

\let\getTABLEparameters\getparameters

\unexpanded\def\setupTABLE
  {\dotripleempty\dosetupTABLE}

\def\dosetupTABLE[#1][#2][#3]%
  {\ifthirdargument
     \processaction
       [#1]
       [  \v!rij=>{\dosetupTABLExy[\c!y][#2][#3]},%
        \v!kolom=>{\dosetupTABLExy[\c!x][#2][#3]},%
               r=>{\dosetupTABLExy[\c!y][#2][#3]},%
               c=>{\dosetupTABLExy[\c!x][#2][#3]},%
               y=>{\dosetupTABLExy[\c!y][#2][#3]},%
               x=>{\dosetupTABLExy[\c!x][#2][#3]},%
        \v!start=>{\dosetupTABLExy[#1][#2][#3]},%
        \v!hoofd=>{\dosetupTABLExy[#1][#2][#3]},%
      \s!unknown=>{\dosetupTABLEzz[#1][#2][#3]}]%
   \else\ifsecondargument
     \processaction
       [#1]
       [  \v!rij=>{\dosetupTABLExy[\c!y][\v!elk][#2]},%
        \v!kolom=>{\dosetupTABLExy[\c!x][\v!elk][#2]},%
               r=>{\dosetupTABLExy[\c!y][\v!elk][#2]},%
               c=>{\dosetupTABLExy[\c!x][\v!elk][#2]},%
               y=>{\dosetupTABLExy[\c!y][\v!elk][#2]},%
               x=>{\dosetupTABLExy[\c!x][\v!elk][#2]},%
        \v!start=>{\dosetupTABLExy[#1][\v!elk][#2]},%
        \v!hoofd=>{\dosetupTABLExy[#1][\v!elk][#2]},%
      \s!unknown=>{\dosetupTABLEzz[\c!x][#1][#2]}]%
   \else
     \getparameters[\@@tbl\@@tbl][#1]%
   \fi\fi}

\def\dosetupTABLExy[#1][#2][#3]%
  {\def\dodosetupTABLE##1%
     {\setTABLEparameters[#1##1][#3]}%
   \processcommalist[#2]\dodosetupTABLE}

\def\dosetupTABLEzz[#1][#2][#3]%
  {\def\dodosetupTABLE##1%
     {\def\dododosetupTABLE####1%
        {\setTABLEparameters[\c!x##1\c!y####1][#3]}%
      \processcommalist[#2]\dododosetupTABLE}%
   \processcommalist[#1]\dodosetupTABLE}

\def\nopTABLEparameters[#1][#2]%
  {\letvalue{\@@tblprefix#1}\empty}

\def\setTABLEparameters[#1][#2]%
  {\pushTBLparameters
   \ifappendTBLsetups
     \doifdefinedelse{\@@tblprefix#1}
       {\def\getTABLEparameters[##1][##2]%
          {\setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][##2,#2]}}%
        \getvalue{\@@tblprefix#1}%
        \let\getTABLEparameters\getparameters}
       {\setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][#2]}}%
   \else
     \setvalue{\@@tblprefix#1}{\getTABLEparameters[\@@tbl\@@tbl][#2]}%
   \fi
   \popTBLparameters}

\let\setupTBLsection\relax

\def\setupTBLcell#1#2% cell over col over row
  {\setupTBLsection % already forgotten
   \getvalue{\@@tblprefix\c!y\v!elk}%
   \getvalue{\@@tblprefix\c!x\v!elk}%
   \getvalue{\@@tblprefix\c!y\v!oddeven{#1}}%
   \getvalue{\@@tblprefix\c!x\v!oddeven{#2}}%
   \getvalue{\@@tblprefix\c!x\v!oddeven{#2}\c!y\v!oddeven{#1}}%
   \ifnum#1=\plusone
     \getvalue{\@@tblprefix\c!y\v!eerste}%
     \executeifdefined{\@@tblprefix\c!x#2\c!y\v!eerste}\donothing
   \fi
   \ifnum#2=\plusone
     \getvalue{\@@tblprefix\c!x\v!eerste}%
     \executeifdefined{\@@tblprefix\c!x\v!eerste\c!y#1}\donothing
   \fi
   \ifnum#1=\maximumrow\relax
     \getvalue{\@@tblprefix\c!y\v!laatste}%
     \executeifdefined{\@@tblprefix\c!x#2\c!y\v!laatste}\donothing
   \fi
   \ifnum#2=\maximumcol\relax
     \getvalue{\@@tblprefix\c!x\v!laatste}%
     \executeifdefined{\@@tblprefix\c!x\v!laatste\c!y#1}\donothing
   \fi
   \ifnum#1=\maximumrow\relax\ifnum#2=\maximumcol\relax
     \getvalue{\@@tblprefix\c!x\v!laatste\c!y\v!laatste}%
   \fi\fi
   \ifnum#1=\plusone \ifnum#2=\plusone
     \getvalue{\@@tblprefix\c!x\v!eerste\c!y\v!eerste}%
   \fi\fi
   \ifnum#1>\noftblheadlines\else
     \executeifdefined{\@@tblprefix\v!hoofd\v!elk}\donothing
     \executeifdefined{\@@tblprefix\v!hoofd#2}\donothing
   \fi
   \executeifdefined{\@@tblprefix\c!y#1}\donothing
   \executeifdefined{\@@tblprefix\c!x#2}\donothing
   \executeifdefined{\@@tblprefix\c!x#2\c!y#1}\donothing
   \global\letcscsname\@@tblsplitafter\csname\@@tbl\@@tbl\c!na\endcsname
   \relax}

\globallet\@@tblsplitafter\relax

% split + page:
%
% \bTABLE[split=yes]
% \bTR \bTD left \eTD\bTD right \eTD\eTR
% \bTR[after=\pagina] \bTD left \eTD\bTD right \eTD\eTR
% \bTR \bTD left \eTD\bTD right \eTD\eTR
% \eTABLE

% \long\def\parseTR[#1][#2]#3\eTR% [#2] is dummy that kills spaces
%   {\def\currentcol{0}\increment\maximumrow#3}

\long\def\parseTR[#1][#2]#3\eTR% [#2] is dummy that kills spaces
  {\def\currentcol{0}\increment\maximumrow
   \setupTABLE[\v!rij][\maximumrow][#1]#3}

\long\def\parseTD[#1][#2]#3\eTD % [#2] is dummy that kills spaces
  {\getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,#1]%
   % goto first cell
   \doloop
     {\increment\currentcol
      \doifnottbltag\maximumrow\currentcol\exitloop}%
   % fill r*c cells and set span
   \let\row\maximumrow
   \let\col\currentcol
   \dorecurse\tblny
     {\let\col\currentcol
      \settblcol\row\col\tblnx
      \ifnum\tblnx>\maximumrowspan\relax
        \let\maximumrowspan\tblnx
      \fi
      \dorecurse\tblnx
        {\settbltag\row\col\tblnone
         \increment\col}%
      \increment\row}%
   % check max column
   \decrement\col
   \ifnum\col>\maximumcol\relax
     \let\maximumcol\col
   \fi
   % set values
   \settbltag\maximumrow\currentcol\tblcell
   \settblcol\maximumrow\currentcol\tblnx
   \settblrow\maximumrow\currentcol\tblny
   % save text
   \edef\celltag{{\maximumrow}{\currentcol}}%
   \@EA\settbltxt\@EA\maximumrow\@EA\currentcol\@EA
     {\@EA\handleTBLcell\celltag[#1]{#3}}}

\long\def\parseTH[#1]#2\eTH
  {\parseTD
     [#1,\c!kleur=\tbltblkopkleur,\c!letter=\tbltblkopletter,%
      \c!karakteruitlijnen=\v!nee]#2\eTD}

%D new

\long\def\parseTN[#1]#2\eTN
  {\parseTD[#1]\digits#2\relax\eTD}

\newtoks\TBLhead
\newtoks\TBLbody
\newtoks\TBLfoot

% to be done: head <raw> foot, dus state var

\long\def\bTABLEhead{\dosingleempty\doTABLEhead}
\long\def\bTABLEbody{\dosingleempty\doTABLEbody}
\long\def\bTABLEfoot{\dosingleempty\doTABLEfoot}

\long\def\doTABLEhead[#1]#2\eTABLEhead
  {\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead}

\long\def\doTABLEbody[#1]#2\eTABLEbody
  {\appendtoks\doTABLEsection[#1]{#2}\to\TBLbody}

\long\def\doTABLEfoot[#1]#2\eTABLEfoot
  {\appendtoks\doTABLEsection[#1]{#2}\to\TBLfoot}

\long\def\doTABLEsection[#1]#2%
  {\def\setupTBLsection{\getparameters[\@@tbl\@@tbl][#1]}%
   #2%
   \let\setupTBLsection\relax}

\let\pushTBL\relax
\let\popTBL \relax

\chardef\TBLpass=0

\def\presetallTABLEparameters% each odd|even level
  {\executeifdefined{\@@rawtblprefix\v!start\v!elk}\relax
   \executeifdefined{\@@rawtblprefix\v!start\v!oddeven\TBLlevel}\relax
   \executeifdefined{\@@rawtblprefix\v!start\number\TBLlevel}\relax}

\def\bTABLE
  {\dosingleempty\dobTABLE}

\def\dobTABLE[#1]%
  {\pushTBL
   % box not here
   \bgroup
\resetcharacteralign % new
   \getparameters
     [\@@tbl\@@tbl]
     [\c!uitlijnen={\v!rechts,\v!ruim,\v!hoog},#1]%
   \processaction
     [\tbltblsplitsen]
     [     \v!ja=>\enableTBLbreaktrue,
      \v!herhaal=>\enableTBLbreaktrue\multipleTBLheadstrue]%
   \ifnum\TBLlevel>\plusone
     \vbox
   \else\ifenableTBLbreak
     % no \vbox
   \else
     \vbox
   \fi\fi
   \bgroup
   \localcolortrue
   \presetallTABLEparameters
   \ExpandFirstAfter\processallactionsinset
     [\tbltbloptie]
     [\v!rek=>\autoTBLspreadtrue]%
   \linewidth\tbltbllijndikte % needs to be frozen
   \dontcomplain
   \let\currentcol\!!zerocount
   \let\maximumrowspan\!!plusone
   \let\maximumcol\currentcol
   \let\maximumrow\currentcol
   \def\bTR{\dodoubleempty\parseTR}%
   \def\bTD{\dodoubleempty\parseTD}%
   \def\bTH{\dodoubleempty\parseTH}%
   \def\bTN{\dodoubleempty\parseTN}%
   \endgraf}

% permits \expanded{\bTD ... \eTD}

\unexpanded\def\eTR{}
\unexpanded\def\eTD{}
\unexpanded\def\eTH{}
\unexpanded\def\eTN{}

\def\eTABLE
  {% tricky and dirty order -)
   \the\TBLhead
   \edef\noftblheadlines{\number\maximumrow}%
   \the\TBLbody
   \the\TBLfoot
   \endgraf
   % finish cells
   \dorecurse\maximumrow
     {\let\row\recurselevel
      \dorecurse\maximumcol
        {\let\col\recurselevel \let\xxcol\col \let\xxrow\row
         \doifnottbltag\row\col
           {\let\xrow\row
            \doloop
              {\let\xcol\col
               \doloop
                 {\doifelsetbltag\xrow\xcol
                    {\exitloop}
                    {\increment\xcol \relax
                     \ifnum\xcol>\maximumcol\relax \exitloop \fi}}%
               \doifelsetbltag\xrow\xcol
                 {\exitloop}
                 {\let\xxrow\xrow \let\xxcol\xcol \increment\xrow \relax
                  \ifnum\xrow>\maximumrow \exitloop \fi}}}%
      \ifnum\xxrow>\maximumrow\let\xxrow\maximumrow\fi
      \ifnum\xxcol>\maximumcol\let\xxcol\maximumcol\fi
      \decrement(\xxrow,\row)\increment\xxrow
      \decrement(\xxcol,\col)\increment\xxcol
      \doifnottbltag\row\col
        {\let\xrow\row
         \dorecurse\xxrow
           {\let\xcol\col \settblcol\xrow\xcol\xxcol
            \dorecurse\xxcol
              {\settbltag\xrow\xcol\tblnone \increment\xcol}%
            \increment\xrow}%
         \settbltag\row\col\tblcell
         \settblcol\row\col\xxcol
         \settblrow\row\col\xxrow
         \ifautoTBLemptycell
           \edef\celltag{{\row}{\col}}%
           \@EA\settbltxt\@EA\row\@EA\col\@EA
             {\@EA\handleTBLcell\celltag[]{\strut}}%
         \fi}}}%
   % to be sure
   \dorecurse\maximumrow
     {\let\row\recurselevel
      \dorecurse\maximumcol
        {\let\col\recurselevel
         \doiftblrow\row\col
           {\scratchcounter\maximumrow
            \advance\scratchcounter -\row
            \advance\scratchcounter \plusone
            \ifnum\gettblrow\row\col>\scratchcounter
              \settblrow\row\col{\the\scratchcounter}%
            \fi}%
         \settblht\row\col\!!zeropoint
         \settblwd\row\col\!!zeropoint
         \doifnottblcol\row\col{\settblcol\row\col\!!zerocount}%
         \doifnottbltag\row\col{\settbltag\row\col\tblnone}}}%
   % check and do
   \begTBL
   \dorecurse\maximumrow
     {\bTBL
      \let\row\recurselevel
      \dorecurse\maximumcol
        {\let\col\recurselevel
         \expanded{\doTBL{\row}{\col}}}%
      \eTBL}%
   \endTBL
   % wrong ! ! ! better to have an auto-offset-overlay
   % \ifnum\TBLlevel>1
   %   \vskip-\strutdp
   % \fi
   \egroup
   \egroup
   \popTBL}

\def\spanTBL#1#2%
  {\scratchcounter\gettblcol{#1}{#2}\relax
   \ifnum\scratchcounter>\zerocount
     \advance\scratchcounter \minusone
     \dorecurse\scratchcounter{\appendtoks\spantblcol\to\tbltoks}%
     \dorecurse\scratchcounter{\appendtoks\skiptblcol\to\tbltoks}%
                               \appendtoks\nexttblcol\to\tbltoks
   \fi}

\def\bTBL{\appendtoks\begintblrow\to\tbltoks}
\def\eTBL{\appendtoks\endtblrow  \to\tbltoks}

% We use aligments to handle the empty (skipped) columns, so
% that we don't have to (re|)|calculate these.

\def\skiptblcol
  {\doglobal\increment\colTBL}

\def\nexttblcol
  {\doglobal\increment\colTBL&}

\def\spantblcol
  {\span}

\def\begintblrow
  {\noalign
     {\doglobal\increment\rowTBL
      \doglobal\newcounter\colTBL}%
   \nexttblcol}

\def\endtblrow
  {\crcr
   \noalign
     {\nointerlineskip
      \allowbreak
      \bgroup % protect local vars
        \@@tblsplitafter
      \egroup
      \bgroup % protect local vars
        \increment\rowTBL\relax
        \ifnum\rowTBL>\noftblheadlines\relax
          \ifnum\rowTBL<\maximumrow\relax
            \doifsomething\tbltbltussenwit{\blank[\tbltbltussenwit]}%
          \fi
        \fi
      \egroup}}

%\def\begintbl
%  {\doglobal\newcounter\colTBL
%   \doglobal\newcounter\rowTBL
%   \doglobal\decrement\rowTBL
%   \tabskip\zeropoint
%   \halign\bgroup\ignorespaces##\unskip&&\ignorespaces##\unskip\cr}

\def\begintbl
  {\doglobal\newcounter\colTBL
   \doglobal\newcounter\rowTBL
   \doglobal\decrement\rowTBL
   \tabskip\zeropoint
   \halign\bgroup
   \registerparoptions %  new
   \ignorespaces##\unskip&&\ignorespaces##\unskip\cr}

\def\endtbl
  {\egroup}

\setvalue{\tblnone TBL}#1#2%
  {\spanTBL{#1}{#2}}

\setvalue{\tblcell TBL}#1#2%
  {\appendtoks
     \makeTBL{#1}{#2}%    % append nog isoleren
   \to\tbltoks
   \spanTBL{#1}{#2}}

\def\doTBL#1#2%
  {\getvalue{\gettbltag{#1}{#2}TBL}{#1}{#2}}

\def\begTBL
  {\doglobal\newcounter\rowTBL
   \doglobal\newcounter\colTBL
   \chardef\TBLpass\zerocount
   \tbltoks\emptytoks
   \appendtoks
     \begintbl
   \to\tbltoks}

\def\endTBL
  {\appendtoks
     \endtbl
   \to\tbltoks
   \setbox\scratchbox\hbox
     {\localframed
        [\@@tbl\@@tbl]
        [\c!kader=\v!uit,\c!achtergrond=,\c!uitlijnen=\v!nee]
        {\strut}}%
   \edef\minimalcellheight{\the\ht\scratchbox}%
   \dorecurse\maximumcol
     {\settblaut\recurselevel\!!zeropoint % \zeropoint etc
      % new
      \let\xcol\recurselevel
      \dorecurse\maximumrow
        {\settblwd \recurselevel\xcol\!!zeropoint
         \settblht \recurselevel\xcol\!!zeropoint}%
      % till here
      \settblwid\recurselevel\!!zeropoint}%
   \dorecurse\maximumrow
     {\settblhei\recurselevel\maxdimen}%
   \chardef\TBLpass\plusone
   \let\handleTBLcell\dohandleTBLcellA
   \def\makeTBL##1##2%
     {\gettbltxt{##1}{##2}}%
   \def\inTBLcell##1##2%
     {\ExpandBothAfter\doifinsetelse\localwidth{\v!passend,\v!ruim} % user set
        {}
        {\scratchdimen\gettblaut\colTBL\relax
         \ifdim\localwidth>\scratchdimen
           \settblaut\colTBL\localwidth
         \fi}}%
   \setbox0\vbox{\trialtypesettingtrue \the\tbltoks}%
   \ifautoTBLspread
     % experimental, stretch non fixed cells to \hsize
     \checktblwidthsone   % trial run
     \checktblwidthstwo   % real run
     \stretchtblwidths
     \let\handleTBLcell\dohandleTBLcellB
     \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}%
   \else\ifdim\wd0>\hsize
     \ifautoTBLhsize
       \checktblwidthsone % trial run
       \checktblwidthstwo % real run
       \let\handleTBLcell\dohandleTBLcellB
       \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}%
     \fi
   \else\ifautoTBLrowspan\ifnum\maximumrowspan>1 % max ?
     % added jan 2002 because nx=* did no longer work
     \checktblwidthsone % trial run
     \checktblwidthstwo % real run
     %
     \let\handleTBLcell\dohandleTBLcellC
     \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}%
   \fi\fi\fi\fi
   \let\handleTBLcell\dohandleTBLcellD
   \chardef\TBLpass2
   \def\makeTBL##1##2% meer in cellD
     {\dimen2\zeropoint
      \pushmacro\colTBL
      \dorecurse{\gettblcol{##1}{##2}}
        {\advance\dimen2 \gettblwid\colTBL
         \increment\colTBL}%
      \edef\widthTBL{\the\dimen2}%
      \popmacro\colTBL
      \setbox\scratchbox\hbox{\gettbltxt{##1}{##2}}%
      \settblht{##1}{##2}{\the\ht\scratchbox}%
      \settblwd{##1}{##2}{\the\wd\scratchbox}%
      \ifdim\ht\scratchbox>\gettblhei{##1}\relax
        \settblhei{##1}{\the\ht\scratchbox}%
      \fi}%
   \setbox\scratchbox\vbox{\trialtypesettingtrue \the\tbltoks}%
   \checktblheightsone
   \checktblheightstwo
   \let\handleTBLcell\dohandleTBLcellE
   \chardef\TBLpass3
   \def\makeTBL##1##2%
     {% height
      \pushmacro\rowTBL
      \scratchdimen\zeropoint
      \def\rowTBL{##1}%
      \ifnum\gettblcol{##1}{##2}=\maximumcol\relax
        % case: nc=maxcolumns
      \else
        \dorecurse{\gettblrow{##1}{##2}}
          {\advance\scratchdimen \gettblhei\rowTBL
           \increment\rowTBL}%
        \ifdim\scratchdimen<\gettblht{##1}{##2}\relax
          \scratchdimen\gettblht{##1}{##2}\relax
        \fi
      \fi
      \edef\heightTBL{\the\scratchdimen}%
      \popmacro\rowTBL
      % width
      \pushmacro\colTBL
      \scratchdimen\zeropoint
      \dorecurse{\gettblcol{##1}{##2}}
        {\advance\scratchdimen \gettblwid\colTBL
         \increment\colTBL}%
      \edef\widthTBL{\the\scratchdimen}%
      \popmacro\colTBL
      % cell
      \setbox\scratchbox\hbox{\gettbltxt{##1}{##2}}%
      \ifnum\gettblcol{##1}{##2}=\maximumcol\relax
        % case: nc=maxcolumns
      \else
        \scratchdimen\gettblhei{##1}%
        \setbox\scratchbox\hbox
          {\lower\ht\scratchbox\hbox{\raise\scratchdimen\box\scratchbox}}%
        \ht\scratchbox\scratchdimen
      \fi
      \dp\scratchbox\zeropoint
      \box\scratchbox}%
    \iftraceTABLE\showtbltoks\fi
    \ifnum\TBLlevel>\plusone
      \vbox{\the\tbltoks}%
    \else\ifenableTBLbreak
      \ifmultipleTBLheads
        \setbox\scratchbox\vbox{\the\tbltoks}%
        \splittblbox\scratchbox
      \else
        \the\tbltoks
      \fi
    \else
      \vbox{\the\tbltoks}%
    \fi\fi}

\def\stretchtblwidths
  {\!!dimend\zeropoint
   \dorecurse\maximumcol
     {\advance\!!dimend\gettblwid\recurselevel}%
   % distribute width (stretch)
   \ifdim\!!dimend<\hsize
     \advance\!!dimend-\hsize
     \!!dimend-\!!dimend
     \divide\!!dimend\maximumcol
     \dorecurse\maximumcol
       {\scratchdimen\gettblwid\recurselevel
        \advance\scratchdimen\!!dimend
        \settblwid\recurselevel{\the\scratchdimen}}%
   \fi}

% \def\splittblbox#1% #1 <> 0/2
%   {\unvbox#1}

\def\splittblbox#1% #1 <> 0/2
  {\ifinsidefloat
     \unvbox#1%
   \else
     % spacing between rows gets lost in split
     \setbox4\vbox
       {\doifsomething\tbltbltussenwit{\blank[\tbltbltussenwit]}}%
     \setbox2\vbox
       {}%
     \dorecurse\noftblheadlines
       {\setbox0\vsplit#1 to \lineheight
        \setbox2\vbox{\unvcopy2\unvcopy0}}%
     \ifcase\noftblheadlines\else\unvcopy2\fi
     \donefalse
     \doloop
       {\setbox0\vsplit#1 to \lineheight
        \ifdim\pagegoal<\maxdimen
          \setbox0\vbox{\unvbox0}%
          \dimen0\ht0
          \advance\dimen0\ht4
          \advance\dimen0\pagetotal
          \ifdim\dimen0>\pagegoal
            \bgroup \pagina \egroup % make sure that local vars are kept
            \ifcase\noftblheadlines\else\unvcopy2\fi
          \fi
        \fi
        \ifdone
          \doifsomething\tbltbltussenwit{\blank[\tbltbltussenwit]}%
        \fi
        \unvbox0
        \allowbreak
        \ifvoid#1 \exitloop \else \donetrue \fi}%
   \fi}

\def\checktblwidthsone{\dochecktblwidths0} % 0 = trial run
\def\checktblwidthstwo{\dochecktblwidths1} % 1 = real run

\def\dochecktblwidths#1%
  {\iftraceTABLE\showtblwids{B#1}\fi
   \!!dimena\hsize
   \!!counta\zerocount
   \dorecurse\maximumcol
     {\scratchdimen\gettblaut\recurselevel\relax
      \ifdim\scratchdimen>\zeropoint\relax
        \advance\!!dimena -\scratchdimen
      \else
        \scratchdimen\gettblwid\recurselevel\relax
        \ifdim\scratchdimen>\tbltblmaxbreedte\relax
          \ifcase#1\else\settblwid\recurselevel\!!zeropoint\fi
          \advance\!!counta \plusone
        \else
          \ifdim\scratchdimen>\zeropoint\relax
            \advance\!!dimena -\scratchdimen
          \else
            % eigenlijk moet dit alleen als de kolom wordt overspannen door een
            % vorige, maw extra dubbele loop en status var
            \advance\!!counta \plusone
          \fi
        \fi
      \fi}%
   \ifcase\!!counta \else \divide\!!dimena \!!counta \fi
   \dorecurse\maximumcol
     {\scratchdimen\gettblwid\recurselevel\relax
      \ifcase#1\relax
        \ifdim\scratchdimen<\!!dimena  % take natural width
          \settblaut\recurselevel{\the\scratchdimen}%
        \fi
      \else
        \ifdim\scratchdimen=\zeropoint % auto set width
          \settblwid\recurselevel{\the\!!dimena}%
        \fi
      \fi}%
   \iftraceTABLE\showtblwids{E#1}\fi}

\def\checktblheightsone
  {\dorecurse\maximumrow
     {\let\xrowTBL\recurselevel
      \dorecurse\maximumcol
        {\let\xcolTBL\recurselevel
         \!!countb=0\gettblrow\xrowTBL\xcolTBL\relax
         % check row span
         \ifnum\!!countb>1
           % current height in row
           \dimen0=\gettblht\xrowTBL\xcolTBL
           % find nearest height in row
           \dimen2=\zeropoint
           \dorecurse\maximumcol
             {\ifnum\recurselevel=\xcolTBL\else
                \!!countc=0\gettblrow\xrowTBL\recurselevel\relax
                \ifnum\!!countc=\plusone
                  \dimen4=\gettblht\xrowTBL\recurselevel\relax
                  \ifdim\dimen2<\dimen4
                    \dimen2=\dimen4
                  \fi
                \fi
              \fi}%
           \let\xxrowTBL\xrowTBL
           % calculate cummulative height
           \dimen4=\dimen2
           \dorecurse\!!countb
             {\ifnum\xxrowTBL=\xrowTBL\else
                \advance\dimen4 \gettblhei\xxrowTBL
              \fi
              \increment\xxrowTBL}%
           % distribute overshoot equally
           \ifdim\dimen4<\dimen0
             \advance\dimen0 -\dimen4
             \divide\dimen0 \!!countb
             \let\xxrowTBL\xrowTBL
             \settblhei\xrowTBL{\the\dimen2}%
             \dorecurse\!!countb
               {\dorecurse\maximumcol
                  {\ifnum\recurselevel=\xcolTBL\else
                     \scratchdimen\gettblht\xxrowTBL\recurselevel
                     \advance\scratchdimen \dimen0
                     \settblht\xxrowTBL\recurselevel{\the\scratchdimen}%
                     \ifdim\gettblhei\xxrowTBL<\scratchdimen
                       \settblhei\xxrowTBL{\the\scratchdimen}%
                     \fi
                   \fi}%
                \increment\xxrowTBL}%
           \else\ifdim\dimen4>\dimen0
             \settblhei\xrowTBL{\the\dimen2}%
           \fi\fi
         \fi}}}

\def\checktblheightstwo
  {}

\def\showtblwids#1%
  {\vbox
     {\forgetall\tttf[#1]\dorecurse\maximumcol
        {\scratchdimen\gettblwid\recurselevel
         [\recurselevel:\the\scratchdimen]}}}

\def\showtbltoks
  {\vbox
     {\forgetall\tttf
      \let\begintbl   \relax  \let\endtbl    \relax
      \let\begintblrow\par    \let\endtblrow \par
      \def\nexttblcol {[next]}\def\spantblcol{[span]}
      \def\makeTBL##1##2{[##1,##2]}
      \the\tbltoks}}

\def\TBLcharalign
  {\doifelse\tbltblkarakteruitlijnen\v!ja
     \doTBLcharalign\gobbleoneargument}

\long\def\doTBLcharalign#1#2% column data
  {\edef\alignmentclass{#1}%
   \edef\alignmentcharacter{\tbltbluitlijnkarakter}%
   \ifcase\TBLpass\or
     \setfirstpasscharacteralign\checkalignment{#2}% {\strut#2\unskip}%
   \fi % force hsize, so always a second
   \setsecondpasscharacteralign \checkalignment{#2}% {\strut#2\unskip}%
   \ignorespaces}

% \long\def\dohandleTBLcellA#1#2[#3]#4%
%   {\setbox\scratchbox\hbox
%      {\setupTBLcell{#1}{#2}%
%       \localframed
%         [\@@tbl\@@tbl]
%         [#3,\c!achtergrond=,\c!kader=\v!uit]% 25% faster
%         {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL\inTBLcell{#1}{#2}}}%
%    \scratchdimen\gettblwid\colTBL\relax
%    \ifdim\wd\scratchbox>\scratchdimen
%      \settblwid\colTBL{\the\wd\scratchbox}% auto set
%    \fi
%    \let\rowTBLx\rowTBL\increment\rowTBLx
%    \scratchdimen\gettblhei\rowTBLx\relax
%    \ifdim\ht\scratchbox<\scratchdimen
%      \settblhei\rowTBLx{\the\ht\scratchbox}% auto set
%    \fi
%    \settblht{#1}{#2}{\the\ht\scratchbox}%
%    \settblwd{#1}{#2}{\the\wd\scratchbox}%
%    \ifautoTBLcheckwidth
%      \ifdim\wd\scratchbox<.75\hsize
%        \ifdim\ht\scratchbox>2\openlineheight % honor width since this can be a
%          \scratchdimen\gettblaut\colTBL\relax % figure or so
%          \ifdim\scratchdimen=\zeropoint
%            % side effect: when width is set to 0pt,
%            % we can force a span that fits the sum of spans widths
%            \settblaut\colTBL{\the\scratchdimen}%
%          \else\ifdim\wd\scratchbox>\scratchdimen
% % unless span
%            \settblaut\colTBL{\the\wd\scratchbox}%
%            % to be translated
%            \writestatus\m!TABLE{no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}%
%          \fi\fi
%        \fi
%      \fi
%    \fi
%    \setbox2\null
%    \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox
%    \box2}

% new, needed for icare first col of 'doeltabel', experimental

\long\def\dohandleTBLcellA#1#2[#3]#4%
  {\setbox\scratchbox\hbox
     {\setupTBLcell{#1}{#2}%
      \localframed
        [\@@tbl\@@tbl]
        [#3,\c!achtergrond=,\c!kader=\v!uit]% 25% faster
        {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL\inTBLcell{#1}{#2}}}%
   \scratchdimen\gettblwid\colTBL\relax
   \ifdim\wd\scratchbox>\scratchdimen
     \ifsqueezeTBLspan
       \ifnum0\number\gettblcol{#1}{#2}>1\relax \settblspn\colTBL \fi
     \fi
     \doifelsetblspn\colTBL
       \donothing{\settblwid\colTBL{\the\wd\scratchbox}}% auto set
   \fi
   \let\rowTBLx\rowTBL\increment\rowTBLx
   \scratchdimen\gettblhei\rowTBLx\relax
   \ifdim\ht\scratchbox<\scratchdimen
     \settblhei\rowTBLx{\the\ht\scratchbox}% auto set
   \fi
   \settblht{#1}{#2}{\the\ht\scratchbox}%
   \settblwd{#1}{#2}{\the\wd\scratchbox}%
   \ifautoTBLcheckwidth
     \ifdim\wd\scratchbox<.75\hsize
       \ifdim\ht\scratchbox>2\openlineheight % honor width since this can be a
         \scratchdimen\gettblaut\colTBL\relax % figure or so
         \ifdim\scratchdimen=\zeropoint
           % side effect: when width is set to 0pt,
           % we can force a span that fits the sum of spans widths
           \settblaut\colTBL{\the\scratchdimen}%
         \else\ifdim\wd\scratchbox>\scratchdimen
           % unless span
           \settblaut\colTBL{\the\wd\scratchbox}%
           % to be translated
           \writestatus\m!TABLE{no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}%
         \fi\fi
       \fi
     \fi
   \fi
   \setbox2\null
   \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox
   \box2}

\long\def\dohandleTBLcellBC#1#2#3[#4]#5%
  {\setbox\scratchbox\hbox
     {\setupTBLcell{#2}{#3}%
      \localframed
        [\@@tbl\@@tbl]
        [#4,#1,\c!kader=\v!uit,\c!achtergrond=]
        {\bTBLCELL#5\eTBLCELL}}%
   \setbox2\null
   \wd2\wd\scratchbox \ht2\ht\scratchbox \dp2\dp\scratchbox
   \ifautoTBLrowspan
     \let\rowTBLx\rowTBL\increment\rowTBLx
     \scratchdimen\gettblhei\rowTBLx\relax
     \ifnum\gettblrow\rowTBLx\colTBL>1 \ifdim\ht\scratchbox>\scratchdimen
       \scratchdimen-\scratchdimen \advance\scratchdimen -\ht\scratchbox
       \ht2\scratchdimen
     \fi \fi
   \fi
   \box2 }

\long\def\dohandleTBLcellB#1#2[#3]#4%
   {\scratchdimen\gettblaut\colTBL\relax
    \ifdim\scratchdimen>\zeropoint\relax
      \let\tblwidthkey\c!breedte \edef\tblwidth{\the\scratchdimen}%
    \else
      \scratchdimen\gettblwid\colTBL\relax
      \ifdim\scratchdimen>\zeropoint\relax
        \ifnum\gettblcol{#1}{#2}=\maximumcol\relax
          \scratchdimen\hsize
        \fi
        \let\tblwidthkey\c!breedte \edef\tblwidth{\the\scratchdimen}%
      \else
        \let\tblwidthkey\s!unknown \let \tblwidth \!!zeropoint
      \fi
    \fi
    \dohandleTBLcellBC{\tblwidthkey=\tblwidth}{#1}{#2}[#3]{\TBLcharalign{#2}{#4}}}

\long\def\dohandleTBLcellC
  {\dohandleTBLcellBC{}}

\long\def\dohandleTBLcellD#1#2[#3]#4%
  {\setupTBLcell{#1}{#2}%
   \bgroup
   \localframed
     [\@@tbl\@@tbl]
     [#3,\c!breedte=\widthTBL,
      \c!achtergrond=,\c!kader=\v!uit]% 25% faster
     {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
   \egroup}

\long\def\dohandleTBLcellE#1#2[#3]#4%
  {\setupTBLcell{#1}{#2}%
   \getparameters[\@@tbl\@@tbl][#3]% to get the color right, the way we
   \color % handle color here prevents interference due to whatsit nodes
     [\tbltblkleur] % as well as permits local colors to take precedence
     {\ifdim\heightTBL=\zeropoint\relax % case: nc=maxcolumns
        \localframed
          [\@@tbl\@@tbl]
          [\c!kleur=,\c!breedte=\widthTBL]
          {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
      \else
        \localframed
          [\@@tbl\@@tbl]
          [\c!kleur=,\c!breedte=\widthTBL,\c!hoogte=\heightTBL]
          {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
      \fi}}

\setupTABLE
  [\c!kaderoffset=.5\linewidth,
   \c!achtergrondoffset=\v!kader,
   \c!kaderkleur=black,
   \c!kleur=,
   \c!letter=,
   \c!kopletter=\v!vet,
   \c!kopkleur=,
   \c!strut=\v!nee,
   \c!karakteruitlijnen=\v!nee,
   \c!uitlijnkarakter={,},
   \c!optie=, % \v!rek
   \c!splitsen=\v!nee,
   \c!tussenwit=,
   \c!maxbreedte=8em]

%D We have already prepared the previous macros for nesting,
%D so we only have to pop in the right ones:

%D Redefined:

\newcounter\TBLlevel

\def\@@tblprefix{\@@tbl:\ifnum\TBLlevel>1 \TBLlevel:\fi}

\long\def\settbltxt#1#2#3%
  {\setxvalue{\@@tblprefix#1:#2:l}{\TBLlevel}%
   \long\setvalue{\@@tblprefix#1:#2:t}%
     {\doifdefined{\@@tblprefix#1:#2:l}
        {\edef\TBLlevel{\getvalue{\@@tblprefix#1:#2:l}}}%
      #3}}

\def\gettbltxt#1#2%
  {\getvalue{\@@tblprefix#1:#2:t}}

%D New:

\def\pushTBLparameters
  {\pushmacro\TBLlevel
   \ifcase\TBLpass
     % we're just after \bTABLE
   \else\ifnum\TBLlevel>\zerocount
     \doglobal\increment\TBLlevel\relax
   \fi\fi}

\def\popTBLparameters
  {\popmacro\TBLlevel}

\def\pushTBL
  {\ifnum\TBLlevel=\zerocount
     \doglobal\increment\currenttbl\relax
   \fi
   \doglobal\increment\TBLlevel\relax
   \ifnum\TBLlevel>\plusone
     \resetallTABLEparameters
     \pushmacro\colTBL
     \pushmacro\rowTBL
   \else
     \global\intabletrue
   \fi}

\def\popTBL
  {\ifnum\TBLlevel>\plusone
     \popmacro\rowTBL
     \popmacro\colTBL
   \else
     \global\intablefalse
   \fi
   \doglobal\decrement\TBLlevel\relax}

\newconditional\resetTABLEmode \settrue\resetTABLEmode

\def\resetallTABLEparameters% moet genest wel werken
  {\ifnum\TBLlevel>\plusone % in ieder geval
     \ifconditional\resetTABLEmode
       \presetlocalframed   % breedte hoogte diepte offset
         [\@@tbl\@@tbl]%    % achtergrond, achtergrondraster, achtergrondkleur
       % not ok yet
       \setupTABLE
         [\c!kaderoffset=.5\linewidth,
          \c!achtergrondoffset=\v!kader,
          \c!kaderkleur=black,
          \c!kleur=,
          \c!letter=,
          \c!kopletter=,
          \c!kopkleur=,
          \c!strut=\v!nee,
          \c!karakteruitlijnen=\v!nee,
          \c!uitlijnkarakter={,},
          \c!maxbreedte=8em]%
     \else
       \setupTABLE
         [\c!breedte=\v!passend,
          \c!hoogte=\v!passend]%
     \fi
  \fi}

\protect \endinput