%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 \starttyping
%D splitsen = ja | herhaal => als nofTH>1 then ja als herhaal
%D \stoptyping

%D To Do:
%D
%D \starttyping
%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 \stoptyping

% 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 \starttyping
%D \def\bTBLCELL{\begstrut}
%D \def\eTBLCELL{\endstrut}
%D \stoptyping

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

\def\bTBLCELL % why not \doinhibitblank
  {\inhibitblank\doconvertfont\tbltblstyle\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}}

\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\ifsqueezeTBLspan     \squeezeTBLspantrue % spans one column cell over multi column par cells
\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}
\def\noftblnextlines{0}
\def\noftblhdnxlines{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!row=>{\dosetupTABLExy[\c!y][#2][#3]},%
       \v!column=>{\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!header=>{\dosetupTABLExy[#1][#2][#3]},%
      \s!unknown=>{\dosetupTABLEzz[#1][#2][#3]}]%
   \else\ifsecondargument
     \processaction
       [#1]
       [  \v!row=>{\dosetupTABLExy[\c!y][\v!each][#2]},%
       \v!column=>{\dosetupTABLExy[\c!x][\v!each][#2]},%
               r=>{\dosetupTABLExy[\c!y][\v!each][#2]},%
               c=>{\dosetupTABLExy[\c!x][\v!each][#2]},%
               y=>{\dosetupTABLExy[\c!y][\v!each][#2]},%
               x=>{\dosetupTABLExy[\c!x][\v!each][#2]},%
        \v!start=>{\dosetupTABLExy[#1][\v!each][#2]},%
       \v!header=>{\dosetupTABLExy[#1][\v!each][#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\v!each\v!each}%
   \getvalue{\@@tblprefix\c!y\v!each}%
   \getvalue{\@@tblprefix\c!x\v!each}%
   \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!first}%
     \executeifdefined{\@@tblprefix\c!x#2\c!y\v!first}\donothing
   \fi
   \ifnum#2=\plusone
     \getvalue{\@@tblprefix\c!x\v!first}%
     \executeifdefined{\@@tblprefix\c!x\v!first\c!y#1}\donothing
   \fi
   \ifnum#1=\maximumrow\relax
     \getvalue{\@@tblprefix\c!y\v!last}%
     \executeifdefined{\@@tblprefix\c!x#2\c!y\v!last}\donothing
   \fi
   \ifnum#2=\maximumcol\relax
     \getvalue{\@@tblprefix\c!x\v!last}%
     \executeifdefined{\@@tblprefix\c!x\v!last\c!y#1}\donothing
   \fi
   \ifnum#1=\maximumrow\relax\ifnum#2=\maximumcol\relax
     \getvalue{\@@tblprefix\c!x\v!last\c!y\v!last}%
   \fi\fi
   \ifnum#1=\plusone \ifnum#2=\plusone
     \getvalue{\@@tblprefix\c!x\v!first\c!y\v!first}%
   \fi\fi
   \ifnum#1>\noftblhdnxlines\else
     \executeifdefined{\@@tblprefix\v!header\v!each}\donothing
     \executeifdefined{\@@tblprefix\v!header#2}\donothing
   \fi
   \executeifdefined{\@@tblprefix\c!y#1}\donothing
\getvalue{\@@tbl\@@tbl\c!extras}\letvalue{\@@tbl\@@tbl\c!extras}\relax % new, see x-fo
   \executeifdefined{\@@tblprefix\c!x#2}\donothing
\getvalue{\@@tbl\@@tbl\c!extras}\letvalue{\@@tbl\@@tbl\c!extras}\relax % new, see x-fo
   \executeifdefined{\@@tblprefix\c!x#2\c!y#1}\donothing
   \global\letcscsname\@@tblsplitafter\csname\@@tbl\@@tbl\c!after\endcsname
   \relax}

\globallet\@@tblsplitafter\relax

% split + page:
%
% \bTABLE[split=yes]
% \bTR \bTD left \eTD\bTD right \eTD\eTR
% \bTR[after=\page] \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}

\def\parseTR[#1][#2]% [#2] is dummy that kills spaces / no #3 argument
  {\def\currentcol{0}\increment\maximumrow
   \let\currentcolpos\currentcol
   \let\eTR\relax % handy in \expanded
   \setupTABLE[\v!row][\maximumrow][#1]}

% \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\parseTD[#1][#2]#3\eTD % [#2] is dummy that kills spaces
  {\getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,\c!n=\currentcol,#1]%
   % goto first cell % NEW, n=cellnumber
   \increment\currentcolpos
   \doifvaluesomething{\@@tbl\c!n}
     {\ifnum\getvalue{\@@tbl\c!n}=\currentcol\else
        \scratchcounter\getvalue{\@@tbl\c!n}%
        \advance\scratchcounter-\currentcol
        \advance\scratchcounter\plusone
        \expanded{\parseTD[][\c!nx=\the\scratchcounter]}\eTD
        \getparameters[\@@tbl][\c!ny=\tblnr,\c!nx=\tblnc,nc=1,nr=1,\c!n=\currentcol,#1]%
      \fi}%
   \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!color=\tbltblheadcolor,\c!style=\tbltblheadstyle,\c!aligncharacter=\v!no]#2\eTD}

%D new

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

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

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

\long\def\doTABLEhead[#1]#2\eTABLEhead{\appendtoks\doTABLEsection[#1]{#2}\to\TBLhead}
\long\def\doTABLEnext[#1]#2\eTABLEnext{\appendtoks\doTABLEsection[#1]{#2}\to\TBLnext}
\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!each}\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
   \ifhmode\kern\zeropoint\fi  % blocks \removeunwantedspaces: check this on icare handelingsschema
   \resetcharacteralign % new
   \getparameters
     [\@@tbl\@@tbl]
     [\c!align={\v!right,\v!broad,\v!high},#1]%
   \processaction
     [\tbltblsplit]
     [     \v!yes=>\enableTBLbreaktrue,
        \v!repeat=>\enableTBLbreaktrue\multipleTBLheadstrue]%
   \processaction
     [\tbltblheader]
     [\v!repeat=>\multipleTBLheadstrue]%
%    \ifnum\TBLlevel>\plusone
%      \vbox
%    \else\ifenableTBLbreak
%      % no \vbox
%    \else
%      \vbox
%    \fi\fi
%   \bgroup
   \localcolortrue
   \presetallTABLEparameters
   \ExpandFirstAfter\processallactionsinset
     [\tbltbloption]
     [\v!stretch=>\autoTBLspreadtrue]%
   \linewidth\tbltblrulethickness % 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}}

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

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

\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode
  {% tricky and dirty order -)
   \doifsometokselse\TBLhead
     {\the\TBLhead
      \edef\noftblheadlines{\number\maximumrow}%
      \doifsometokselse\TBLnext
        {\the\TBLnext
         \scratchcounter\maximumrow \advance\scratchcounter-\noftblheadlines
         \edef\noftblnextlines{\number\scratchcounter}}%
        {\let\noftblnextlines\!!zerocount}% was 1
      \edef\noftblhdnxlines{\number\maximumrow}}
     {\let\noftblheadlines\!!zerocount % was 1
      \let\noftblnextlines\!!zerocount
      \let\noftblhdnxlines\!!zerocount}%
   \the\TBLbody
   \the\TBLfoot
   \removeunwantedspaces % only if hmode
   % 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
   \startTBLprocessing
     \begTBL
       \dorecurse\maximumrow
         {\bTBL
            \let\row\recurselevel
            \dorecurse\maximumcol
              {\let\col\recurselevel
               \expanded{\doTBL{\row}{\col}}}%
          \eTBL}%
       \removeunwantedspaces % only if hmode
     \endTBL
   \stopTBLprocessing
   % wrong ! ! ! better to have an auto-offset-overlay
   % \ifnum\TBLlevel>1
   %   \vskip-\strutdp
   % \fi
   \egroup
   \popTBL}

\let\startTBLprocessing\relax
\let\stopTBLprocessing \relax

% \def\processTBL
%   {\begTBL
%    \dorecurse\maximumrow
%      {\bTBL
%       \let\row\recurselevel
%       \dorecurse\maximumcol
%         {\let\col\recurselevel
%          \expanded{\doTBL{\row}{\col}}}%
%       \eTBL}%
%    \removeunwantedspaces % only if hmode
%    \endTBL}

\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>\noftblhdnxlines\relax
          \ifnum\rowTBL<\maximumrow\relax
            \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}%
          \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!frame=\v!off,\c!background=,\c!align=\v!no]
        {\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!fit,\v!broad} % 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\TBLpass\plustwo
   \def\makeTBL##1##2% meer in cellD
     {\dimen2\zeropoint
      \globalpushmacro\colTBL
      \dorecurse{\gettblcol{##1}{##2}}
        {\advance\dimen2 \gettblwid\colTBL
         \increment\colTBL}%
      \edef\widthTBL{\the\dimen2}%
      \globalpopmacro\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\TBLpass\plusthree
   \def\makeTBL##1##2%
     {% height
      \globalpushmacro\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}%
      \globalpopmacro\rowTBL
      % width
      \globalpushmacro\colTBL
      \scratchdimen\zeropoint
      \dorecurse{\gettblcol{##1}{##2}}
        {\advance\scratchdimen \gettblwid\colTBL
         \increment\colTBL}%
      \edef\widthTBL{\the\scratchdimen}%
      \globalpopmacro\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
      \@EA\notsplittblbox
    \else\ifenableTBLbreak
      \@EAEAEA\splittblbox
    \else
      \@EAEAEA\notsplittblbox
    \fi\fi{\the\tbltoks}}

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

\newbox\finaltblbox

\def\notsplittblbox#1%
  {\setbox\finaltblbox\vbox{#1}%
   \postprocessTABLEbox\finaltblbox
   \beforeTABLEbox
   \box\finaltblbox
   \afterTABLEbox}

\def\splittblbox#1%
  {\ifinsidefloat
     \notsplittblbox{#1}%
   \else
     \executeifdefined{splittblbox\tbltblsplitmethod}\splittblboxa{#1}%
   \fi}

\newbox\TABLEsplitbox

\def\splittblboxa#1% spacing between rows gets lost in split
  {\setbox\TABLEsplitbox\vbox{#1}%
   \setbox8\vbox{\doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}}%
   \ifmultipleTBLheads
     \setbox2\vbox{}%
     \setbox4\vbox{}%
     \dorecurse\noftblheadlines
       {\setbox0\vsplit\TABLEsplitbox to \lineheight
        \setbox2\vbox{\unvcopy2\unvcopy0}}%
     \dorecurse\noftblnextlines
       {\setbox0\vsplit\TABLEsplitbox to \lineheight
        \setbox4\vbox{\unvcopy4\unvcopy0}}%
     \ifcase\noftblheadlines\else
       \ifdim\pagegoal<\maxdimen
         \dimen0\ht2
         \advance\dimen0\ht8
         \advance\dimen0\pagetotal\relax
         \ifdim\dimen0>\pagegoal
           \bgroup\page\egroup % make sure that local vars are kept
         \fi
       \fi
       \unvcopy2
       \ifcase\noftblnextlines\else
         \setbox2\box4
       \fi
     \fi
   \fi
   \donefalse
   \!!doneafalse
   \doloop
     {\setbox0\vsplit\TABLEsplitbox to \lineheight
      \if!!donea
        \ifdim\pagegoal<\maxdimen
          \setbox0\vbox{\unvbox0}%
          \ifdim\ht0>\zeropoint
            \dimen0\ht0
            \advance\dimen0\ht8
            \advance\dimen0\pagetotal\relax
            \ifdim\dimen0>\pagegoal
              \bgroup\page\egroup % make sure that local vars are kept
              \ifmultipleTBLheads
                \ifcase\noftblheadlines\else\unvcopy2\fi
              \fi
            \fi
          \fi
        \fi
      \fi
      \!!doneatrue
      \ifdone
        \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}%
      \fi
      \unvbox0
      %\allowbreak
      \bgroup
        % todo: what if tblnextlines ?
        \scratchcounter\recurselevel
        \ifmultipleTBLheads
          \advance\scratchcounter\noftblheadlines
        \fi
        \setupTBLcell{\number\scratchcounter}1
        \ifx\@@tblsplitafter\relax
          \allowbreak
        \else
          \doifelsenothing\@@tblsplitafter
             \allowbreak
            {\scratchcounter\realpageno
             \@@tblsplitafter
             \ifmultipleTBLheads
               \ifnum\scratchcounter<\realpageno
                 \ifcase\noftblheadlines\else\unvcopy2\fi
               \fi
             \fi}%
        \fi
      \egroup
      \ifvoid\TABLEsplitbox \exitloop \else \donetrue \fi}}

\let\extratblsplitheight\zeropoint % additional space taken by before/afterTABLEsplitbox

% \def\splittblboxb#1%
%   {\testpage[2]% quite save since a row is > 1 lineheight and we don't want one-liners
%    \setbox\TABLEsplitbox\vbox{#1}%
%    \setbox8\vbox{\doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}}%
%    \ifmultipleTBLheads
%      \setbox2\vbox{}%
%      \setbox4\vbox{}%
%      \dorecurse\noftblheadlines
%        {\setbox0\vsplit\TABLEsplitbox to \lineheight
%         \setbox2\vbox{\unvcopy2\unvcopy0}}%
%      \dorecurse\noftblnextlines
%        {\setbox0\vsplit\TABLEsplitbox to \lineheight
%         \setbox4\vbox{\unvcopy4\unvcopy0}}%
%    \fi
%    \!!doneafalse
%    \doloop
%      {\ifdim\pagegoal<\maxdimen
%         \scratchdimen\pagegoal
%         \advance\scratchdimen-\pagetotal
%       \else
%         \scratchdimen\textheight
%       \fi
%       \ifmultipleTBLheads
%         \ifcase\noftblheadlines\else
%           \advance\scratchdimen-\ht2
%         \fi
%       \fi
%       \advance\scratchdimen-\ht8
%       \getnoflines\scratchdimen
%       \ifdim\noflines\lineheight>\scratchdimen
%         \advance\scratchdimen-\lineheight
%       \fi
%       \advance\scratchdimen-\extratblsplitheight
%       \setbox\finaltblbox\vbox
%         {\ifmultipleTBLheads
%            \ifcase\noftblheadlines\else
%              \unvcopy2
%              \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}%
%            \fi
%          \fi
%          \setbox0\vsplit\TABLEsplitbox to\scratchdimen
%          \unvbox0}%
%       \if!!donea\else\ifcase\noftblnextlines\else
%         \setbox2\box4
%       \fi\fi
%       \!!doneatrue
%       \postprocessTABLEsplitbox\finaltblbox
%       \ifvoid\TABLEsplitbox
%         \beforeTABLEsplitbox
%         \box\finaltblbox
%         \afterTABLEsplitbox
%         \@@tblsplitafter
%         \exitloop
%       \else
%        % hack
%         \scratchdimen\pagegoal
%         \ifdim\scratchdimen<\maxdimen
%           \advance\scratchdimen \lineheight
%           \global\pagegoal\scratchdimen
%         \fi
%         % brrr
%         \beforeTABLEsplitbox
%         \box\finaltblbox
%         \afterTABLEsplitbox
%         \@@tblsplitafter
%         \page
%       \fi}}

\def\splittblboxb#1%
  {\scratchdimen-\extratblsplitheight
   \advance\scratchdimen-\tbltblsplitoffset
   \expanded{\testpage[2][\the\scratchdimen]}% quite save since a row is > 1 lineheight and we don't want one-liners
   \setbox\TABLEsplitbox\vbox{#1}%
   \setbox8\vbox{\doifsomething\tbltblspaceinbetween{\blanko[\tbltblspaceinbetween]}}%
   \dimen8\ht8\advance\dimen8\dp8
   \ifmultipleTBLheads
     \setbox2\vbox{}%
     \setbox4\vbox{}%
     \dorecurse\noftblheadlines
       {\setbox0\vsplit\TABLEsplitbox to \lineheight
        \setbox2\vbox{\unvcopy2\unvcopy0}}%
     \dorecurse\noftblnextlines
       {\setbox0\vsplit\TABLEsplitbox to \lineheight
        \setbox4\vbox{\unvcopy4\unvcopy0}}%
   \fi
   \!!doneafalse
   \doloop
     {\ifdim\pagegoal<\maxdimen
        \scratchdimen\pagegoal
        \advance\scratchdimen-\pagetotal
      \else
        \scratchdimen\textheight
      \fi
      \advance\scratchdimen-\dimen8
      \advance\scratchdimen-\extratblsplitheight
      \advance\scratchdimen-\tbltblsplitoffset
      \setbox\finaltblbox\vbox
        {\ifmultipleTBLheads
           \ifcase\noftblheadlines\else
             \unvcopy2 \doifsomething\tbltblspaceinbetween{\blank[\tbltblspaceinbetween]}%
           \fi
         \fi}%
      \if!!donea\else\ifcase\noftblnextlines\else
        \setbox2\box4
      \fi\fi
      \!!doneatrue
      % alternatively we could use a kind of balancing like splitter
      % first to scratchdimen and then smaller etc; more code and copy -)
      \doloop
        {\setbox\scratchbox\vsplit\TABLEsplitbox to \onepoint
         \setbox\scratchbox\vbox{\unvbox\scratchbox}%
         \bgroup
         \advance\scratchdimen-\ht\scratchbox
         \advance\scratchdimen-\dp\scratchbox
         \advance\scratchdimen-\ht\finaltblbox
         \advance\scratchdimen-\dp\finaltblbox\relax
         \ifdim\scratchdimen>\zeropoint
           \egroup
           \setbox\finaltblbox\vbox
              {\unvbox\finaltblbox
               \unvbox\scratchbox}%
           \ifvoid\TABLEsplitbox \exitloop \fi
         \else
           \egroup
           \setbox\TABLEsplitbox\vbox
              {\unvbox\scratchbox
               \ifvoid\TABLEsplitbox\else\unvbox\TABLEsplitbox\allowbreak\fi}%
           \exitloop
         \fi}%
      %
      \postprocessTABLEsplitbox\finaltblbox
      \ifvoid\TABLEsplitbox
        \beforeTABLEsplitbox
        \box\finaltblbox
        \afterTABLEsplitbox
        \@@tblsplitafter
        \exitloop
      \else
        % hack
        \ifdim\pagegoal<\maxdimen
          \scratchdimen\pagegoal
          \advance\scratchdimen \lineheight
          \global\pagegoal\scratchdimen
        \fi
        % brrr
        \beforeTABLEsplitbox
        \box\finaltblbox
        \afterTABLEsplitbox
        \@@tblsplitafter
        \pagina
      \fi}}

% ! ! ! ! TODO: naast \postprocessTABLEsplitbox ook evt \postprocessTABLEbox voor niet split

\let\postprocessTABLEsplitbox\gobbleoneargument
\let\postprocessTABLEbox     \gobbleoneargument

\let\beforeTABLEsplitbox\relax
\let\afterTABLEsplitbox \relax
\let\beforeTABLEbox     \relax
\let\afterTABLEbox      \relax

\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>\tbltblmaxwidth\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\tbltblaligncharacter\v!yes
     \doTBLcharalign\gobbleoneargument}

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

% 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!background=,\c!frame=\v!off]% 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!frame=\v!off,\c!background=]
        {\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!width \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!width \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!width=\widthTBL,\c!background=,\c!frame=\v!off]% 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
     [\tbltblcolor] % as well as permits local colors to take precedence
     {\ifdim\heightTBL=\zeropoint\relax % case: nc=maxcolumns
        \localframed
          [\@@tbl\@@tbl]
          [\c!color=,\c!width=\widthTBL]
          {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
      \else
        \localframed
          [\@@tbl\@@tbl]
          [\c!color=,\c!width=\widthTBL,\c!height=\heightTBL]
          {\bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}%
      \fi}}

\setupTABLE
  [\c!frameoffset=.5\linewidth,
   \c!backgroundoffset=\v!frame,
   \c!framecolor=\s!black,
   \c!color=,
   \c!style=,
   \c!headstyle=\v!bold,
   \c!headcolor=,
   \c!strut=\v!no,
   \c!aligncharacter=\v!no,
   \c!alignmentcharacter={,},
   \c!option=, % \v!stretch
   \c!header=,
   \c!spaceinbetween=,
   \c!maxwidth=8em,
   \c!split=\v!no,
   \c!splitoffset=0pt,
   \c!splitmethod=a]

%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
  {\globalpushmacro\TBLlevel
   \ifcase\TBLpass
     % we're just after \bTABLE
   \else\ifnum\TBLlevel>\zerocount
     \doglobal\increment\TBLlevel\relax
   \fi\fi}

\def\popTBLparameters
  {\globalpopmacro\TBLlevel}

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

\def\popTBL
  {\ifnum\TBLlevel>\plusone
     \globalpopmacro\rowTBL
     \globalpopmacro\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!frameoffset=.5\linewidth,
          \c!backgroundoffset=\v!frame,
          \c!framecolor=\s!black,
          \c!color=,
          \c!style=,
          \c!headstyle=,
          \c!headcolor=,
          \c!strut=\v!no,
          \c!aligncharacter=\v!no,
          \c!alignmentcharacter={,},
          \c!maxwidth=8em]%
     \else
       \setupTABLE
         [\c!width=\v!fit,
          \c!height=\v!fit]%
     \fi
  \fi}

%D Spacing:
%
% \starttabulate
% \NC text \NC text \NC \NR
% \TB[small]
% \NC text \NC text \NC \NR
% \TB[4*big]
% \NC text \NC text \NC \NR
% \stoptabulate
%
% \starttable[|||]
% \VL text \VL text \VL \AR
% \TB[small]
% \VL text \VL text \VL \AR
% \TB[4*big]
% \VL text \VL text \VL \AR
% \stoptable

\def\complexTableTB[#1]{\TABLEnoalign{\blank[#1]}}
\def\simpleTableTB     {\TABLEnoalign{\blank}}

\def\TabulateTB
  {\complexorsimpleTable{TB}}

\def\doTableinterline% #1
  {\ifnum\currentTABLEcolumn>\maxTABLEcolumn
     \chuckTABLEautorow
   \else\ifnum\currentTABLEcolumn=\zerocount
     \TABLEnoalign
       {\globalletempty\checkTABLEautorow
        \globalletempty\chuckTABLEautorow}%
   \else
     \setTABLEerror\TABLEmissingcolumn
     \handleTABLEerror
   \fi\fi
   \complexorsimpleTable} % {#1}

\def\TableHL{\doTableinterline{HL}}
\def\TableTB{\doTableinterline{TB}}

\appendtoks\let\TB\TableTB   \to\everytable
\appendtoks\let\TB\TabulateTB\to\everytabulate

\protect \endinput
