%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 

\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-\dp\strutbox
     \else
       \removebottomthings
     \fi
   \fi}

\newcounter\currenttbl

%\def\@@tbl{tbl}  \def\tblcell{m}  \def\tblnone{n}
\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{\getvalue{\@@tblprefix#1:#2:s}}
\def\gettblcol#1#2{\getvalue{\@@tblprefix#1:#2:c}}
\def\gettblrow#1#2{\getvalue{\@@tblprefix#1:#2:r}}

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

\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\gettblaut#1{\getvalue{\@@tblprefix#1:a}}

\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\settbltxt#1#2{\long\setvalue{\@@tblprefix:#1:#2:t}}
\def\gettbltxt#1#2{\getvalue     {\@@tblprefix:#1:#2:t}}

%\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\iftraceTABLE         \traceTABLEfalse

\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]},
      \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]},
      \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]%
  {\setvalue{\@@tblprefix#1}{}}

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

\def\v!oddeven#1{\ifodd#1\v!oneven\else\v!even\fi}

\let\setupTBLsection\relax

\def\setupTBLcell#1#2% cell over col over row 
  {\setupTBLsection % here ? 
   \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=1                \getvalue{\@@tblprefix\c!y\v!eerste }\fi
   \ifnum#2=1                \getvalue{\@@tblprefix\c!x\v!eerste }\fi
   \ifnum#1=\maximumrow\relax\getvalue{\@@tblprefix\c!y\v!laatste}\fi
   \ifnum#2=\maximumcol\relax\getvalue{\@@tblprefix\c!x\v!laatste}\fi
   \getvalue{\@@tblprefix\c!y#1}%
   \getvalue{\@@tblprefix\c!x#2}%
   \getvalue{\@@tblprefix\c!x#2\c!y#1}\relax}

%\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]%
%    \let\row\maximumrow
%    \let\col\currentcol
%    % goto first cell
%    \doloop{\increment\col \doifnottbltag\row\col\exitloop}%
%    % fill r*c cells and set span
%    \let\currentcol\col
%    \let\currentrow\row
%    \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}%
%    \decrement\row
%    % 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}}%
%    % check max column
%    \let\currentcol\col
%    \decrement\currentcol
%    \ifnum\currentcol>\maximumcol\let\maximumcol\currentcol\fi}

\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!letter=\v!vet,\c!karakteruitlijnen=\v!nee]#2\eTD}
  {\parseTD[#1,\c!kleur=\tbltblkopkleur,\c!letter=\tbltblkopletter,%
      \c!karakteruitlijnen=\v!nee]#2\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
   \vbox\bgroup
   \localcolortrue
   \getparameters
     [\@@tbl\@@tbl]
     [\c!uitlijnen={\v!rechts,\v!ruim,\v!hoog},#1]%
   \presetallTABLEparameters
   \ExpandFirstAfter\processallactionsinset
     [\tbltbloptie]
     [\v!rek=>\autoTBLspreadtrue]%
   \linewidth=\tbltbllijndikte % needs to be frozen
   \dontcomplain
   \def\currentcol{0}%
   \def\maximumrowspan{1}%
   \let\maximumcol\currentcol
   \let\maximumrow\currentcol
   \def\bTR{\dodoubleempty\parseTR}%
   \def\bTD{\dodoubleempty\parseTD}%
   \def\bTH{\dodoubleempty\parseTH}%
   \endgraf}

\def\eTABLE%
  {\the\TBLhead\the\TBLbody\the\TBLfoot\endgraf % tricky and dirty order -)
   % 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 by -\row 
            \advance\scratchcounter by 1 
            \ifnum\gettblrow\row\col>\scratchcounter
              \settblrow\row\col{\the\scratchcounter}%
            \fi}%
         \settblht\row\col\!!zeropoint
         \settblwd\row\col\!!zeropoint
         \doifnottblcol\row\col{\settblcol\row\col0}%
         \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-\dp\strutbox
% \fi
   \egroup
   \popTBL}

\def\spanTBL#1#2%
  {\scratchcounter=\gettblcol{#1}{#2}\relax
   \ifnum\scratchcounter>0
     \advance\scratchcounter -1
     \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}}

\def\begintbl%
  {\doglobal\newcounter\colTBL
   \doglobal\newcounter\rowTBL
   \doglobal\decrement\rowTBL
   \tabskip\zeropoint
   \halign\bgroup\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=0
   \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
      % 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=1
   \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{\the\tbltoks}%
\ifautoTBLspread
  % experimental, stretch non fixed cells to \hsize 
  \checktblwidthsone % trial run 
  \checktblwidthstwo % real run 
  \let\handleTBLcell\dohandleTBLcellB
  \setbox\scratchbox=\vbox{\the\tbltoks}%
\else
   \ifdim\wd0>\hsize
     \ifautoTBLhsize
       \checktblwidthsone % trial run 
       \checktblwidthstwo % real run 
       \let\handleTBLcell\dohandleTBLcellB
       \setbox\scratchbox=\vbox{\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{\the\tbltoks}%
   \fi\fi\fi
\fi
   \let\handleTBLcell\dohandleTBLcellD
   \chardef\TBLpass=2
   \def\makeTBL##1##2% meer in cellD 
     {\dimen2=\zeropoint
      \pushmacro\colTBL
      \dorecurse{\gettblcol{##1}{##2}}
        {\advance\dimen2 by \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{\the\tbltoks}%
   \checktblheightsone
   \checktblheightstwo
   \let\handleTBLcell\dohandleTBLcellE
   \chardef\TBLpass=3
   \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 by \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 by \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
    \vbox{\the\tbltoks}}

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

\def\dochecktblwidths#1% 
  {\iftraceTABLE\showtblwids{B#1}\fi
   \!!dimena=\hsize 
   \!!counta=0
   \dorecurse{\maximumcol}
     {\scratchdimen=\gettblaut\recurselevel\relax
      \ifdim\scratchdimen>\zeropoint\relax
        \advance\!!dimena by -\scratchdimen
      \else
        \scratchdimen=\gettblwid\recurselevel\relax
        \ifdim\scratchdimen>\tbltblmaxbreedte\relax
          \ifcase#1\else\settblwid\recurselevel\!!zeropoint\fi
          \advance\!!counta by 1 
        \else
          \ifdim\scratchdimen>\zeropoint\relax
            \advance\!!dimena by -\scratchdimen
          \else
            % eigenlijk moet dit alleen als de kolom wordt overspannen door een 
            % vorige, maw extra dubbele loop en status var
            \advance\!!counta by 1 
          \fi
        \fi
      \fi}%
   \ifcase\!!counta \else \divide\!!dimena by \!!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\relax % auto set width 
          \settblwid\recurselevel{\the\!!dimena}% 
        \fi
      \fi}%
   \iftraceTABLE\showtblwids{E#1}\fi}

% \def\checktblwidthsXXX% 
%   {\!!dimena=\hsize 
%    \!!counta=0
%    \dorecurse{\maximumcol}
%      {\scratchdimen=\gettblaut\recurselevel\relax
%       \ifdim\scratchdimen>\zeropoint\relax
%         \advance\!!dimena by -\scratchdimen
%       \else
%         \advance\!!counta by 1 
%       \fi}%
%    \ifcase\!!counta \else \divide\!!dimena by \!!counta \fi
%    \dorecurse{\maximumcol}
%      {\scratchdimen=\gettblaut\recurselevel\relax
%       \ifdim\scratchdimen=\zeropoint\relax 
%         \settblaut\recurselevel{\the\!!dimena}% 
%       \fi
% \settblwid\recurselevel{\the\!!dimena}% 
% }}

\def\checktblheightsone% 
  {\dorecurse{\maximumrow}
     {\let\xrowTBL\recurselevel
      \dorecurse{\maximumcol}
        {\let\xcolTBL\recurselevel
         \count0=0\gettblrow\xrowTBL\xcolTBL\relax 
         % check row span 
         \ifnum\count0>1
           % current height in row 
           \dimen0=\gettblht\xrowTBL\xcolTBL 
           % find nearest height in row 
           \dimen2=\!!zeropoint              
           \dorecurse{\maximumcol}
             {\ifnum\recurselevel=\xcolTBL\else
                \count2=0\gettblrow\xrowTBL\recurselevel\relax 
                \ifnum\count2=1
                  \dimen4=\gettblht\xrowTBL\recurselevel\relax
                  \ifdim\dimen2<\dimen4
                    \dimen2=\dimen4
                  \fi
                \fi
              \fi}%
           \let\xxrowTBL\xrowTBL
           % calculate cummulative height 
           \dimen4=\dimen2 
           \dorecurse{\count0}
             {\ifnum\xxrowTBL=\xrowTBL\else
                \advance\dimen4 by \gettblhei\xxrowTBL 
              \fi
              \increment\xxrowTBL}%
           % distribute overshoot equally
           \ifdim\dimen4<\dimen0 
             \advance\dimen0 by -\dimen4
             \divide\dimen0 by \count0 
             \let\xxrowTBL\xrowTBL
             \settblhei\xrowTBL{\the\dimen2}%
             \dorecurse{\count0}
               {\dorecurse{\maximumcol}
                  {\ifnum\recurselevel=\xcolTBL\else
                     \scratchdimen=\gettblht\xxrowTBL\recurselevel
                     \advance\scratchdimen by \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}{[\recurselevel:\gettblwid\recurselevel]}}}

\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}
     {\let\next\doTBLcharalign}
     {\let\next\gobbleoneargument}%
   \next}

\long\def\doTBLcharalign#1#2% column data
  {\edef\alignmentclass{#1}%
   \edef\alignmentcharacter{\tbltbluitlijnkarakter}%
   \ifcase\TBLpass\or
     \setfirstpasscharacteralign\checkalignment{\strut#2\unskip}%
   \fi % force hsize, so always a second 
   \setsecondpasscharacteralign\checkalignment{\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}%
%    \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\wd\scratchbox>\scratchdimen
%          \settblaut\colTBL{\the\wd\scratchbox}%
%         %\message{[forcing width of \colTBL\space(\the\wd\scratchbox/\the\hsize)]}%
%        \fi
%      \fi
%    \fi
%    \setbox2=\null
%    \wd2=\wd\scratchbox \ht2=\ht\scratchbox \dp2=\dp\scratchbox
%    \box2}

\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
        {\trialtypesettingtrue
         \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\wd\scratchbox>\scratchdimen
           \settblaut\colTBL{\the\wd\scratchbox}%
           % to be translated 
           \writestatus{TABLE}{no auto width in (\number#1,\number#2)\space\the\wd\scratchbox/\the\hsize}%
         \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=] 
        {\trialtypesettingtrue
         \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 by -\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}%
   \localframed
     [\@@tbl\@@tbl]
     [#3,\c!breedte=\widthTBL,
      \c!achtergrond=,\c!kader=\v!uit]% 25% faster
     {\trialtypesettingtrue
      \bTBLCELL\TBLcharalign{#2}{#4}\eTBLCELL}}

\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!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>0 
     \doglobal\increment\TBLlevel\relax
   \fi\fi}

\def\popTBLparameters%
  {\popmacro\TBLlevel}

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

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

\newconditional\resetTABLEmode \settrue\resetTABLEmode

\def\resetallTABLEparameters% moet genest wel werken
  {\ifnum\TBLlevel>1        % 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 
