%D \module
%D   [       file=core-tbl,
%D        version=1998.11.03,
%D          title=\CONTEXT\ Table Macros,
%D       subtitle=Text Flow Tabulation,
%D         author=Hans Hagen,
%D           date=\currentdate,
%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
%C
%C This module is part of the \CONTEXT\ macro||package and is
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.

\writestatus{loading}{ConTeXt Table Macros / Tabulation}

% \processbetween gebruiken in head/tail macros

\unprotect

% WATCH OUT: don't change this model else trialtypesetting
% compatibility problems

% watch out, cells expand pretty late on a per row basis

% |p2|p3| 2:3
% spanning

% Be careful with changing the hsize calculation in p mode;
% the following code works quite well:
%
% \setupfield [line][location=low,height=1.2\lineheight,width=\hsize]
% \definefield [test] [line] [line] []
%
% \starttabulate[|l|p|]
% \NC test \NC \field [test] \NC \NR
% \stoptabulate

% In-text tabbing environment
%
% \starttabulate[| separated template] % eg [|l|p|] or [|l|p|p|]
%   \NC ... \NC ... \NC\NR
% \stoptabulate
%
% with: two pass auto width calculation when no p-width
% specified, even with multiple p's, see examples.

%  TaBlE compatible specifications:
%
%  l  align column/paragraph left
%  r  align column/paragraph right
%  c  align column/paragraph center
%  p  p(dimen) of automatisch als alleen p
%  w  column width
%  f  font#1
%  B  bold
%  I  italic
%  S  slanted
%  T  type
%  R  roman
%  m  math
%  M  display math
%  h  hook (inner level or par lines)
%  b  before (may be command#1)
%  a  after
%  i  i<n> skip left of column
%  j  i<n> skip right of column
%  k  i<n> skip around column

%  s  setups

%  g  g{char} align at char
%  .  align at .
%  ,  align at ,

%  Still to be done

%  N      math numbers (best hook into existing digits mechanism)
%  n      numbers (best hook into existing digits mechanism)
%  Q      math numbers (best hook into existing digits mechanism)
%  q      numbers (best hook into existing digits mechanism)
%  ~      \hskip.5em
%  |      check

%  nesting

%  10     evt auto stack; dan wel andere signal dan void nodig

%  present but not yet 100% ok
%
%  \FL    top hrule
%  \ML    mid hrule (with auto split)
%  \LL    bottom hrule
%  \HL

%  \VL    as soon as needed
%  color  as soon as needed

%  \EQ \RQ \HQ  equal  (raw, hook)
%  \NC \RC \HC  normal (raw, hook)
%
%  \NR

%  \HR : rule with lineheight

%  \autotabulaterule : with lineheight, not first/last
%  \autotabulateline : spaced, not first/last
%  \tabulaterule     : with lineheight
%  \tabulateline     : spaced

% tricky: align scans ahead, over # and expands ones before
% while doing

% new:
%
% \starttabulate[|cg{.}|cg{,}|cg{,}|]
% \NC period     \NC comma      \NC comma   \NC\NR
% \NG 100.000,00 \NG 100.000,00 \NG 100,00  \NC\NR
% \NG 10.000,00  \NG 10.000,00  \NG 1000,00 \NC\NR
% \NG 100,00     \NG 100,00     \NG 10,00   \NC\NR
% \NG 10         \NG 10         \NG 0,00    \NC\NR
% \stoptabulate
%
% \starttabulate[|c.|c,|c,|]
% \NC period     \NC comma      \NC comma   \NC\NR
% \NG 100.000,00 \NG 100.000,00 \NG 100,00  \NC\NR
% \NG 10.000,00  \NG 10.000,00  \NG 1000,00 \NC\NR
% \NG 100,00     \NG 100,00     \NG 10,00   \NC\NR
% \NG 10         \NG 10         \NG 0,00    \NC\NR
% \stoptabulate

% nice demo (for BG)
%
% \starttabulate[|r|b{$\star$}|ra{\percent}|b{=}|r|]
% \NC 500 \NC \NC 60 \NC \NC 300 \NC \NR
% \NC 500 \NC \NC 55 \NC \NC 275 \NC \NR
% \NC 500 \NC \NC 50 \NC \NC 250 \NC \NR
% \NC 500 \NC \NC 45 \NC \NC 225 \NC \NR
% \NC 500 \NC \NC 40 \NC \NC 200 \NC \NR
% \NC 500 \NC \NC 35 \NC \NC 175 \NC \NR
% \NC 500 \NC \NC 30 \NC \NC 150 \NC \NR
% \NC 500 \NC \NC 25 \NC \NC 125 \NC \NR
% \NC 500 \NC \NC 20 \NC \NC 100 \NC \NR
% \stoptabulate

\newtoks  \tabulatepreamble
\newtoks  \tabulatebefore
\newtoks  \tabulateafter
\newtoks  \tabulatebmath
\newtoks  \tabulateemath
\newtoks  \tabulatefont
\newtoks  \tabulatesettings
\newtoks  \tabulatedummy

\newcount \nofautotabulate
\newcount \tabulatecolumns
\newcount \tabulatecolumn

\newcount \tabulateminplines
\newcount \tabulatemaxplines

\newif    \ifautotabulate
\newif    \ifsplittabulate         \splittabulatetrue

\newif    \ifhandletabulatepbreak  \handletabulatepbreaktrue
\newif    \iftabulatenopbreak      \tabulatenopbreakfalse

\newif    \iftabulateequal
\newif    \iftracetabulate
\newif    \ifframedtabulate

\newdimen \tabulatepwidth
\newdimen \tabulatewidth
\newdimen \tabulateunit
\newdimen \tabulatemaxpheight

\newbox   \tabulatebox

% [|lg{.}|] => \NG 12.34 \NC

\gdef\handletabulatecharalign#1 % space delimited !
  {\edef\alignmentclass{\the\tabulatecolumn}%
   \edef\alignmentcharacter{\getvalue{\@@tabalign@@\the\tabulatecolumn}}%
   \ifcase\tabulatepass\or
     \setfirstpasscharacteralign\checkalignment{#1}%
   \fi % force hsize
   \setsecondpasscharacteralign\checkalignment{#1}}

\def\noftabcolumns{16}

\def\@@tabbox@@   {@@tabbox@}
\def\@@tabhook@@  {@@tabhook@}
\def\@@tabalign@@ {@@tabalign@}
\def\@@tabsetups@@{@@tabsetups@}

% \dorecurse\noftabcolumns % quick and dirty stack
%   {\@EA\newbox\csname\@@tabbox@@\recurselevel\endcsname}

\def\tablebox#1%
  {\csname\@@tabbox@@\number#1\endcsname}

% \def\checktablebox#1%
%   {\ifundefinedelse{\@@tabbox@@\number#1}%
%      \expandafter\newbox\csname\@@tabbox@@\number#1\endcsname
%    \fi}

\def\initializetablebox#1% also used elsewhere
  {\ifcsname\@@tabbox@@\number#1\endcsname
     \global\setbox\csname\@@tabbox@@\number#1\endcsname\emptybox
   \else
     \expandafter\newbox\csname\@@tabbox@@\number#1\endcsname
   \fi}

% \def\initializetableboxes#1% hm, not that efficient, best make a simple dedicated tail recurser
%   {\dorecurse#1{\initializetablebox\recurselevel}}

\def\initializetableboxes#1%
  {\scratchcounter#1\relax
   \doinitializetableboxes}

\def\doinitializetableboxes
  {\ifnum\scratchcounter>\zerocount
     \initializetablebox\scratchcounter
     \advance\scratchcounter\minusone
     \expandafter\doinitializetableboxes
   \fi}

\initializetableboxes\noftabcolumns

\def\dotabulatenobreak
  {\noalign
     {\nobreak
      \iftracetabulate
        \red\hrule\!!height.5\linewidth\!!depth.5\linewidth
        \par
        \kern-\linewidth
        \nobreak
      \fi}}

\let\notabulatehook\empty

\def\checktabulatehook
  {\ifnum\tabulatetype<\plustwo
     \global\let\tabulatehook\notabulatehook
   \else
     \global\let\tabulatehook\dotabulatehook
   \fi}

\def\checktabulatesetups
  {\getvalue{\@@tabsetups@@\the\tabulatecolumn}}

\let\pretabrule \donothing
\let\posttabrule\donothing

\def\dodosettabulatepreamble#1#2%
  {\ifzeropt\tabulatewidth
     \ifcase\tabulatemodus\relax
       \let\preamblebox\empty
     \else
       \def\preamblebox{\autotabulatetrue}%
     \fi
   \else
     \ifcase\tabulatemodus\relax
       \edef\preamblebox{\hbox to \the\tabulatewidth}%
     \else
       \edef\preamblebox{\hsize\the\tabulatewidth}%
     \fi
   \fi
  %
  % less bytes
  %
  %\edef\preamblebox%
  %  {\ifcase\tabulatewidth
  %     \ifcase\tabulatemodus\relax\else\noexpand\autotabulatetrue\fi
  %   \els
  %     \ifcase\tabulatemodus\relax\hbox to\else\hsize\fi\the\tabulatewidth
  %   \fi}%
  %
  % 0 = NC column next   EQ equal column
  % 1 = RC column raw    RQ equal column raw
  % 2 = HC column hook   HQ equal column hook
  % some entries can be left out if we test for them being set
   \@EA\appendtoks          \@EA&\@EA\hskip\pretabskip\pretabrule##&\to\!!toksa
       \appendtoks                                     \ignorespaces\to\!!toksa
   \@EA\appendtoks\@EA\global\@EA\tabulatecolumn\the\tabulatecolumns\relax\to\!!toksa
       \appendtoks                              \checktabulatesetups\to\!!toksa
       \appendtoks                                \checktabulatehook\to\!!toksa
   \@EA\appendtoks                                      \preamblebox\to\!!toksa
       \appendtoks                           \bgroup\bbskip\bgroup#1\to\!!toksa
       \appendtoks\ifnum\tabulatetype=\plusone \else                \to\!!toksa
   \@EA\appendtoks                                \the\tabulatebmath\to\!!toksa
   \@EA\appendtoks                                 \the\tabulatefont\to\!!toksa
   \@EA\appendtoks                             \the\tabulatesettings\to\!!toksa
   \@EA\appendtoks                               \the\tabulatebefore\to\!!toksa
       \appendtoks\fi                                               \to\!!toksa
       \appendtoks                              \bgroup\ignorespaces\to\!!toksa
       %
       \appendtoks                                   \tabulatehook##\to\!!toksa
       %
      %%\doifdefinedelse{\@@tabalign@@\tabulatecolumns}
       %\doifdefinedelse{\@@tabalign@@\the\tabulatecolumns}
       %  {\appendtoks\handletabulatecharalign## \to\!!toksa}
       %  {\appendtoks\tabulatehook ##\to \!!toksa}%
       % waarom kan ik hier geen \xx{##} geven, om een of
       % andere reden passeert dan tex de hele regel (incl \NC's)
       % als argument; elke delimiter <> space gaat trouwens fout
       \appendtoks     \unskip\unskip\ifmmode\else\endgraf\fi\egroup\to\!!toksa
       \appendtoks\ifnum\tabulatetype=1 \else                       \to\!!toksa
   \@EA\appendtoks                                \the\tabulateafter\to\!!toksa
   \@EA\appendtoks                                \the\tabulateemath\to\!!toksa
       \appendtoks\fi                                               \to\!!toksa
       \appendtoks                                  #2\egroup\egroup\to\!!toksa
   \@EA\appendtoks      \@EA&\@EA\posttabrule\@EA\hskip\postabskip##\to\!!toksa
   \appendtoks\NC\to\tabulatedummy
   \let\bbskip\empty
   \def\pretabskip{.5\tabulateunit}%
   \let\postabskip\pretabskip
   \let\gettabulateexit\dogettabulateexit
   \tabulatewidth\zeropoint}

% todo: we can speed up this module a bit
%
%   \expanded{\!!toksa{\the\!!toksa
%     &\hskip\pretabskip\noexpand\pretabrule####&
%     \ignorespaces
%     \global\tabulatecolumn\the\tabulatecolumns
%     \noexpand\checktabulatesetups
%     \noexpand\checktabulatehook
%     \preamblebox
%     \bgroup\noexpand\bbskip\bgroup\normalunexpanded{#1}%
%     \noexpand\ifnum\tabulatetype=\plusone \noexpand\else
%     \the\tabulatebmath
%     \the\tabulatefont
%     \the\tabulatesettings
%     \the\tabulatebefore
%     \noexpand\fi
%     \bgroup\ignorespaces
%     \noexpand\tabulatehook####%
%     \unskip\unskip\noexpand\ifmmode\noexpand\else\endgraf\noexpand\fi\egroup
%     \noexpand\ifnum\noexpand\tabulatetype=1 \noexpand\else
%     \the\tabulateafter
%     \the\tabulateemath
%     \noexpand\fi
%     \normalunexpanded{#2}\egroup\egroup
%     &\noexpand\posttabrule\hskip\noexpand\postabskip####}}%

\def\dosettabulatepreamble
  {\ifx\next\relax
     \let\nextnext\relax % == \expandafter\gobbleoneargument
   \else
     \let\nextnext\settabulatepreamble
     \ifx      x\next \let\tabulatealign\zerocount % internal
     \else\ifx l\next \let\tabulatealign\plusone
     \else\ifx r\next \let\tabulatealign\plustwo
     \else\ifx c\next \let\tabulatealign\plusthree
     \else\ifx p\next \let\nextnext\gettabulateparagraph
     \else\ifx s\next \let\nextnext\gettabulatesetups
     \else\ifx w\next \let\nextnext\gettabulatewidth
     \else\ifx f\next \let\nextnext\gettabulatefont
     \else\ifx B\next \tabulatefont{\bf}%
     \else\ifx I\next \tabulatefont{\it}%
     \else\ifx S\next \tabulatefont{\sl}%
     \else\ifx T\next \tabulatefont{\tt}%
     \else\ifx R\next \tabulatefont{\rm}%
     \else\ifx m\next \tabulatebmath{$}\tabulateemath{$}%
     \else\ifx M\next \tabulatebmath{$\displaystyle}\tabulateemath{$}%
     \else\ifx h\next \let\nextnext\gettabulatehook
     \else\ifx b\next \let\nextnext\gettabulatebefore
     \else\ifx a\next \let\nextnext\gettabulateafter
     \else\ifx i\next \let\nextnext\gettabulatepreskip
     \else\ifx j\next \let\nextnext\gettabulateposskip
     \else\ifx k\next \let\nextnext\gettabulatepreposskip
     \else\ifx X\next \let\nextnext\gettabulateexit % internal
     \else\ifx e\next \appendtoks\global\tabulateequaltrue\to\tabulatesettings
     \else\ifx ~\next \appendtoks\fixedspaces\to\tabulatesettings
     \else\ifx g\next \let\nextnext\gettabulatealign
     \else\ifx .\next \def\nextnext{\gettabulatealign.}%
     \else\ifx ,\next \def\nextnext{\gettabulatealign,}%
     \else            \message{unknown preamble key [\meaning\next]}%
     \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi
     \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi \fi\fi
   \fi
   \nextnext}

\def\dogettabulateexit
  {\let\postabskip\!!zeropoint
   \settabulatepreamble}

\let\gettabulateexit\dogettabulateexit

\def\gettabulatepreskip#1%
  {\doifnumberelse{#1}
     {\scratchdimen#1\tabulateunit\let\next\empty}
     {\scratchdimen.5\tabulateunit\def\next{#1}}%
   \edef\pretabskip{\the\scratchdimen}%
   \@EA\settabulatepreamble\next}

\def\gettabulateposskip#1%
  {\doifnumberelse{#1}
     {\scratchdimen#1\tabulateunit\let\next\empty}
     {\scratchdimen.5\tabulateunit\def\next{#1}}%
   \edef\postabskip{\the\scratchdimen}%
   \let\gettabulateexit\settabulatepreamble
   \@EA\settabulatepreamble\next}

\def\gettabulatepreposskip#1%
  {\doifnumberelse{#1}
     {\scratchdimen#1\tabulateunit\let\next\empty}
     {\scratchdimen.5\tabulateunit\def\next{#1}}%
   \edef\pretabskip{\the\scratchdimen}%
   \let\postabskip\pretabskip
   \let\gettabulateexit\settabulatepreamble
   \@EA\settabulatepreamble\next}

\def\gettabulatesetups#1%
  {\setvalue{\@@tabsetups@@\the\tabulatecolumns}{\setups[#1]}%
   \settabulatepreamble}

\def\gettabulatehook#1%
  {\setvalue{\@@tabhook@@\the\tabulatecolumns}{#1}%
   \settabulatepreamble}

\def\gettabulatealign#1%
  {\setvalue{\@@tabalign@@\the\tabulatecolumns}{#1}%
   \settabulatepreamble}

\def\gettabulatebefore#1%
  {\tabulatebefore{#1}%
   \settabulatepreamble}

\def\gettabulateafter#1%
  {\tabulateafter{#1}%
   \settabulatepreamble}

\def\gettabulatefont#1%
  {\tabulatefont{#1}%
   \settabulatepreamble}

\def\gettabulatewidth
  {\let\tabulatemodus\zerocount
   \let\tabulatedimen\zerocount
   \doifnextcharelse(\dogettabulatewidth\settabulatepreamble}

\def\gettabulateparagraph
  {\doifnextcharelse{(}
     {\let\tabulatemodus\plusone
      \let\tabulatedimen\plusone
      \dogettabulatewidth}
     {\let\tabulatemodus\plustwo
      \let\tabulatedimen\zerocount
      \settabulatepreamble}}

% \def\dogettabulatewidth(#1)%
%   {\tabulatewidth#1\relax
%    \ifnum\tabulatedimen=\plusone
%      \global\advance\tabulatepwidth\tabulatewidth
%    \fi
%    \settabulatepreamble}

% \def\dogettabulatewidth(#1)%
%   {\doifelse{#1}\v!passend
%      {\let\tabulatemodus\plusthree}
%      {\tabulatewidth#1\relax}%
%    \ifnum\tabulatedimen=\plusone
%      \global\advance\tabulatepwidth\tabulatewidth
%    \fi
%    \settabulatepreamble}

% \startbuffer
%   \toplinebox{\framed[width=3cm,height=2cm]{tufte}}
% \stopbuffer
% \starttabulate[|p(fixed)|p|]
%   \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
% \stoptabulate
% \starttabulate[|p(fit)|p|]
%   \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
% \stoptabulate

\def\dogettabulatewidth(#1)%
  {\processallactionsinset
     [#1]%
     [   \v!fit=>\let\tabulatemodus\plusthree,
       \v!fixed=>\let\tabulatemodus\plusthree
                 \tabulatenopbreaktrue,
     \s!unknown=>\tabulatewidth#1\relax]%
   \ifnum\tabulatedimen=\plusone
     \global\advance\tabulatepwidth\tabulatewidth
   \fi
   \settabulatepreamble}

\def\settabulatepreamble
  {\afterassignment\dosettabulatepreamble\let\next=}

\def\tabulateraggedright {\ifnum\tabulatetype=\plusone \else\raggedright \fi}
\def\tabulateraggedcenter{\ifnum\tabulatetype=\plusone \else\raggedcenter\fi}
\def\tabulateraggedleft  {\ifnum\tabulatetype=\plusone \else\raggedleft  \fi}
\def\tabulatenotragged   {\ifnum\tabulatetype=\plusone \else\notragged   \fi}
\def\tabulatehss         {\ifnum\tabulatetype=\plusone \else\hss         \fi} % never change this to a fill

\bgroup  \catcode`\|=\@@other

\gdef\nexttabulate#1|%
  {\let\tabulatealign\@@tabulatealign
   \let\tabulatemodus\zerocount
   \let\tabulatedimen\zerocount
   \tabulatebefore  \emptytoks
   \tabulateafter   \emptytoks
   \tabulatebmath   \emptytoks
   \tabulateemath   \emptytoks
   \tabulatefont    \emptytoks
   \tabulatesettings\emptytoks
   \global\advance\tabulatecolumns\plusone
   \letvalue{\@@tabsetups@@\the\tabulatecolumns}\donothing
   \settabulatepreamble#1\relax\relax % permits i without n
   \ifcase\tabulatemodus\relax
     \ifcase\tabulatealign\relax
       \dodosettabulatepreamble\empty      \tabulatehss   \or
       \dodosettabulatepreamble\empty      \tabulatehss   \or
       \dodosettabulatepreamble\tabulatehss\empty         \or
       \dodosettabulatepreamble\tabulatehss\tabulatehss   \fi
   \or % fixed width
     \ifcase\tabulatealign\relax
       \dodosettabulatepreamble \bskip                      \eskip \or
       \dodosettabulatepreamble{\bskip\tabulateraggedright }\eskip \or
       \dodosettabulatepreamble{\bskip\tabulateraggedleft  }\eskip \or
       \dodosettabulatepreamble{\bskip\tabulateraggedcenter}\eskip \fi
   \or % auto width
     \global\advance\nofautotabulate\plusone
     \ifcase\tabulatealign\relax
       \dodosettabulatepreamble \bskip                      \eskip \or
       \dodosettabulatepreamble{\bskip\tabulateraggedright }\eskip \or
       \dodosettabulatepreamble{\bskip\tabulateraggedleft  }\eskip \or
       \dodosettabulatepreamble{\bskip\tabulateraggedcenter}\eskip \fi
   \or % simple
     \dodosettabulatepreamble \xbskip \xeskip
   \fi
   \futurelet\next\donexttabulate}

\egroup

\def\donexttabulate
  {\ifx\next\relax\else
     \expandafter\nexttabulate
   \fi}

\def\splitofftabulatebox % overloaded in anch-pgr
  {\dontcomplain
   \global\setbox\tabulatebox % % % global ? % % %
     \vsplit\tablebox\tabulatecolumn to \lineheight
   \setbox\tabulatebox\normalvbox
     {\unvbox\tabulatebox}%
   \setbox\tabulatebox\hbox to \wd\tabulatebox
     {\hss\dotabulatehook{\box\tabulatebox}\hss}%
   \ht\tabulatebox\strutht
   \dp\tabulatebox\strutdp
   \box\tabulatebox}

\def\dotabulatehook  {\getvalue{\@@tabhook@@  \the\tabulatecolumn}}
\def\dotabulatealign {\getvalue{\@@tabalign@@ \the\tabulatecolumn}}

\def\resettabulatepheight
  {\global\tabulateminplines\plusone
   \getnoflines\tabulatemaxpheight
   \global\tabulatemaxplines\noflines
   \global\tabulatemaxpheight\zeropoint}

\def\settabulatepheight
  {\scratchdimen\ht\tablebox\tabulatecolumn\relax
   \ifdim\scratchdimen>\tabulatemaxpheight
     \global\tabulatemaxpheight\scratchdimen
   \fi}

\def\handletabulatepbreak
  {\TABLEnoalign
     {\ifhandletabulatepbreak
        \iftabulatenopbreak
          \dotabulatenobreak
        \else\ifnum\tabulatemaxplines>\plusone
          \ifnum\tabulateminplines=\plusone
            \dotabulatenobreak
          \fi
          \global\advance\tabulateminplines\plusone
          \ifnum\tabulateminplines=\tabulatemaxplines\relax
            \dotabulatenobreak
          \fi
        \fi \fi
      \fi}}

%D \startbuffer
%D \starttabulate[|c|p|p|]
%D \NC \bf Alpha \NC \bf Beta        \NC \bf Gamma          \NC\NR
%D \NC 1         \NC right indeed    \NC definitely wrong   \NC\NR
%D \NC 2         \NC \thinrules[n=3] \NC \thinrules[n=3]    \NC\NR
%D \NC 3         \NC oh yes          \NC simply no          \NC\NR
%D \NC 4         \NC very true       \NC as false as can be \NC\NR
%D \NC 5         \NC \thinrules[n=5] \NC \thinrules[n=5]    \NC\NR
%D \NC 6         \NC \thinrules[n=3] \NC \thinrules[n=4]    \NC\NR
%D \stoptabulate
%D \stopbuffer
%D
%D \typebuffer {\tracetabulatetrue\getbuffer}
%D
%D \startbuffer
%D \starttabulate[|c|p|p|]
%D \NC \bf Alpha \NC \bf Beta        \NC \bf Gamma          \NC\NR
%D \NC 1         \NC right indeed    \NC definitely wrong   \NC\NR
%D \NC 2         \NC oh yes          \NC simply no          \NC\NR
%D \NC 3         \NC very true       \NC as false as can be \NC\NR
%D \NC 4         \NC the whole truth \NC but the truth      \NC\NR
%D \stoptabulate
%D \stopbuffer
%D
%D \typebuffer {\tracetabulatetrue\getbuffer}

% \definetabulate
% \redefinetabulate
% \starttabulate[preamble]
% \starttabulate -> \starttabulate[|l|p|]

\bgroup  \catcode`\|=\@@other

\gdef\definetabulate
  {\dotripleempty\dodefinetabulate}

\gdef\dodefinetabulate[#1][#2][#3]%
  {\ifthirdargument
     \doifundefined{\??tt#1::\c!unit}
       {\copyparameters
          [\??tt#1::][\??tt\v!tabulate::]%
          [\c!frame,\c!distance,\c!unit,\c!before,\c!bodyfont,\c!after,
           \c!inner,\c!indenting,\c!margin,\c!align,\c!header,\c!title,
           \c!rulecolor,\c!rulethickness,\c!split,EQ]}%
     \copyparameters
       [\??tt#1::#2][\??tt#1::]%
       [\c!unit,\c!distance,\c!before,\c!bodyfont,\c!after,
        \c!inner,\c!indenting,\c!frame,\c!split,\c!header,\c!title,
        \c!margin,\c!align,\c!rulecolor,\c!rulethickness,EQ]%
     \setvalue{\e!start#1::#2}{\dofinalstarttabulate[#1][#2][#3]}%
     \setvalue{\e!start#1}{\bgroup\dosubstarttabulate[#1]}%
     \letvalue{\??tt#1-\v!header}\empty
     \letvalue{\??tt#1-\v!footer }\empty
   \else\ifsecondargument
     \definetabulate[#1][][#2]%
   \else
     \definetabulate[#1][][|l|p|]%
   \fi\fi}

\egroup

\let\tabulateheadcontent\empty
\let\tabulatetailcontent\empty

\newconditional\tabulatesomeamble

\def\checkfulltabulatecontent % - needed, else confusion with \c!header
  {\ifundefined{\??tt\currenttabulate-\v!header}%
     \let\tabulateheadcontent\empty
   \else
     \def\tabulateheadcontent
       {\TABLEnoalign{\global\settrue\tabulatesomeamble}%
        \csname\??tt\currenttabulate-\v!header\endcsname
        \TABLEnoalign{\global\setfalse\tabulatesomeamble}}%
   \fi
   \ifundefined{\??tt\currenttabulate-\v!footer}%
     \let\tabulatetailcontent\empty
   \else
     \def\tabulatetailcontent
       {\TABLEnoalign{\global\settrue\tabulatesomeamble}%
        \csname\??tt\currenttabulate-\v!footer\endcsname
        \TABLEnoalign{\global\setfalse\tabulatesomeamble}}%
   \fi}

% \def\fulltabulatecontent
%   {\tabulateheadcontent
%    \tabulatecontent
%    \tabulatetailcontent}

\def\fulltabulatecontent
  {\tabulateheadcontent
   \tabulatecontent
   \tabulatetailcontent
   \removefunnytabulateline}

\def\removefunnytabulateline
  {\ifhmode
     \strut\crcr
     \TABLEnoalign{\kern-\lineheight}%
   \fi}

\setvalue{\e!start\v!tabulatehead}%
  {\dosingleempty\dostartstarttabulatehead}

\def\dostartstarttabulatehead[#1]%
  {\processcontent{\e!stop\v!tabulatehead}\next
     {\letvalue{\??tt\iffirstargument#1\else\v!tabulate\fi::-\v!header}\next}}

\setvalue{\e!start\v!tabulatetail}%
  {\dosingleempty\dostartstarttabulatetail}

\def\dostartstarttabulatetail[#1]%
  {\processcontent{\e!stop\v!tabulatetail}\next
     {\letvalue{\??tt\iffirstargument#1\else\v!tabulate\fi::-\v!footer}\next}}

\def\dosubstarttabulate
  {\dodoubleempty\dodosubstarttabulate}

\def\dodosubstarttabulate[#1][#2]%
  {\getvalue{\e!start#1::\ifundefined{\e!start#1::#2}\else#2\fi}}

\setvalue{\e!start\v!tabulate}%
  {\bgroup\dodoubleempty\donormalstarttabulate}

\bgroup

\gdef\donormalstarttabulate[#1][#2]%
  {\ifsecondargument
     \getparameters[\??tt\v!tabulate::][#2]%
   \fi
   \iffirstargument
     \def\next{\dofinalstarttabulate[\v!tabulate][][#1]}%
   \else
     \def\next{\dofinalstarttabulate[\v!tabulate][][|l|p|]}%
   \fi
   \next}

\egroup

% The much neede hook:

\newtoks\everytabulate

% An example of its usage:

\appendtoks \optimizeverbatimfalse          \to \everytabulate
\appendtoks \let\recodeverbatimmode\plustwo \to \everytabulate

% A status variable:

\chardef\tabulatepass=0

\def\tabulateparameter#1{\csname\??tt\currenttabulate#1\endcsname}

\bgroup
    \catcode`\|=\@@other  \gdef\@@otherbar{|}
    \catcode`\|=\@@active \gdef\@@useotherbar{\let|\@@otherbar}
\egroup

\def\dofinalstarttabulate[#1][#2][#3]% identifier sub preamble
  {\edef\currenttabulate{#1::#2}%
   \ifinsidefloat \else
     \whitespace
     \tabulateparameter\c!before
   \fi
   \bgroup
   \resetcharacteralign
   % todo: spacing around tabulate when bodyfont is set
   % expansion en test needed ?
   \splittabulatetrue
   \processaction
     [\tabulateparameter\c!split]
     [%    \v!yes=>\splittabulatetrue,
      % \v!repeat=>\splittabulatetrue, % todo, default yes
            \v!no=>\splittabulatefalse,
          \v!auto=>\ifinsidefloat\ifinsidesplitfloat\else\splittabulatefalse\fi\fi]%
   \doifvaluesomething{\??tt\currenttabulate\c!bodyfont}
     {\expanded{\switchtobodyfont[\tabulateparameter\c!bodyfont]}}%
   \postponenotes % new, to be tested / will be configurable
   \let\tabulatepass\plusone
   \widowpenalty\zerocount % otherwise lines are not broken
   \clubpenalty \zerocount % but overlap in funny ways
   \the\everytabulate
   \tabulateparameter\c!inner
   \scratchdimen\leftskip
   \advance\scratchdimen \hangindent
   \doifvalue{\??tt\currenttabulate\c!indenting}\v!yes
     {\advance\scratchdimen \parindent}% \ctxparindent
   \edef\tabulateindent{\the\scratchdimen}%
   \!!toksb\emptytoks
   \def\dorepeat*##1##2%
     {\dorecurse{##1}{\appendtoks##2\to\!!toksb}\do}%
   \def\do
     {\futurelet\next\dodo}%
   \def\dodo % \@EAEAEA gebruiken
     {\ifx\next\relax
        % exit
      \else\ifx*\next
        \let\next\dorepeat
      \else\ifx\bgroup\next
        \let\next\dododo
      \else
        \let\next\dodododo
      \fi\fi\fi
      \next}%
   \def\dododo##1%
     {\appendtoks{##1}\to\!!toksb\do}%
   \def\dodododo##1%
     {\appendtoks##1\to\!!toksb\do}%
   \global\tabulatecolumn\zerocount
%    \do#3\relax
\bgroup\@@useotherbar\expanded{\egroup\noexpand\do#3\relax}%
   \processcontent
     {\e!stop#1}% \currenttabulate}
     \tabulatecontent
     {\@EA\processtabulate\@EA[\the\!!toksb]}}

\chardef\tabulatetype=0

% 0 = NC column next   EQ equal column
% 1 = RC column raw    RQ equal column raw
% 2 = HC column hook   HQ equal column hook

\newif\iftabulatefirstflushed

\def\tabulateEQ
  {\iftabulatefirstflushed\else\tabulateparameter{EQ}\fi
   \global\tabulateequalfalse}

% \def\tabulatenormalcolumn#1%
%   {&\iftabulateequal\tabulateEQ\fi&\global\chardef\tabulatetype#1&}
%
% \def\tabulateequalcolumn#1%
%   {&\tabulateEQ&\global\chardef\tabulatetype#1&}
%
% however, \unskip en \ignorespaces permit usage in complex XML/\starttabulate

\def\tabulatenormalcolumn#1%
  {\unskip&\iftabulateequal\tabulateEQ\fi&\global\chardef\tabulatetype#1&%
   \ignorespaces}

\def\tabulateequalcolumn#1%
  {\unskip&\tabulateEQ&\global\chardef\tabulatetype#1&%
   \ignorespaces}

\def\tabulateautocolumn
  {\tabulatenormalcolumn\zerocount
   \ifnum\tabulatecolumn>\tabulatecolumns\relax
     \expandafter\NR
   \else
     \expandafter\ignorespaces % interferes with the more tricky hooks
   \fi}

\def\setquicktabulate#1% see \startlegend \startgiven
  {\let#1\tabulateautocolumn
   \let\\\tabulateautocolumn}

%\def\dotabulateruleseperator
%  {\vskip\strutdp}

\def\dotabulateruleseperator % can be sped up
  {\bgroup
   \let\factor\!!plusone
   \scratchskip\strutdp
   \ExpandFirstAfter\processallactionsinset
     [\tabulateparameter\c!distance]
     [ \v!blank=>\scratchskip\bigskipamount,
       \v!depth=>\scratchskip\strutdp,
       \v!small=>\def\factor{.25},
      \v!medium=>\def\factor{.5},
         \v!big=>,
        \v!none=>\scratchskip\zeropoint\def\factor{0},
        \v!grid=>\scratchskip\zeropoint\def\factor{0},
     \s!unknown=>\scratchskip\commalistelement]%
   \scratchdimen\factor\scratchskip
   \ifconditional\tabulatesomeamble\kern\else\vskip\fi\scratchdimen % new
   \egroup}

\def\dodotabulaterule#1%
  {\color
     [\tabulateparameter\c!rulecolor]
     {\scratchdimen\tabulateparameter\c!rulethickness#1}}

\def\dotabulaterule
  {\dodotabulaterule
     {\hrule\!!height.5\scratchdimen\!!depth.5\scratchdimen\relax
      \doifvalue{\??tt\currenttabulate\c!distance}\v!grid
        {\kern-\scratchdimen}}} % experimental tm-prikkels

\def\dotabulatelinerule
  {\multispan\totaltabulatecolumns % \multispan is a plain macro
   % for the moment this one
   \strut\hskip\tabulateparameter\c!margin
   % neg values are ok !
   \hskip\tabulateindent % new august 2003
   \dodotabulaterule
     {\!!heighta.5\lineheight
      \advance\!!heighta-\strutdepth
      \!!deptha-\!!heighta
      \advance\!!deptha\scratchdimen
      \leaders\hrule\!!height\!!heighta\!!depth\!!deptha\hfill}%
   \cr}

%D When set to true, no (less) break optimization is done.

\newif\iftolerantTABLEbreak

%D The main processing macro is large but splitting it up
%D would make things less clear.

\def\doregistertabulateparoptions
  {\iftrialtypesetting \else
     \registerparoptions
     \ifinsidefloat
       % that is, an unbreakable one
       \global\let\registertabulateparoptions\empty
     \else
       % unsafe in crossing pages, at each b...
       % \global\let\registertabulateparoptions\empty
     \fi
   \fi}

\appendtoks
  \global\let\registertabulateparoptions\doregistertabulateparoptions
\to \everytabulate

\newtoks\everytabulaterow

\appendtoks
  \registertabulateparoptions
\to \everytabulaterow

\def\flushtabulateindent
  {\ifnum\tabulatecolumn=\zerocount
     \hbox to \tabulateindent
       {% we now have a local hsize, and since we want to
        % register positional info (i.e. real hsizes) we
        % need to reconstitute the original hsize
        \advance\hsize\tabulateindent
        % this is indeed rather messy and took a few hours
        % to dis/uncover
        \the\everytabulaterow
        \hss}%
   \fi}

\def\totaltabulatecolumns{0}

\def\handletabulatedigits{\digits}

%D Beware, we cannot use \type {\unexpanded} on \type {\HL}
%D cum suis, since \TEX's hard coded noalign lookahead fails
%D on it! I mistakenly added this for a while.

\chardef\tabulaterepeathead\zerocount

\newcount\noftabulatelines
\newcount\totalnoftabulatelines
\newcount\minusnoftabulatelines

\setvalue{\??tt:\c!align:\v!normal}{0}
\setvalue{\??tt:\c!align:\v!right }{1}
\setvalue{\??tt:\c!align:\v!left  }{2}
\setvalue{\??tt:\c!align:\v!middle}{3}

\setvalue{\??tt:\c!header:\v!repeat}{\plusone}
\setvalue{\??tt:\c!header:\v!text  }{\plustwo}

\bgroup  \catcode`\|=\@@other

\newtoks\everyaftertabulaterow

\gdef\processtabulate[|#1|]% in the process of optimizing
  {\tabulateunit\tabulateparameter\c!unit
   \checkfulltabulatecontent
   \globallet\tabulateruledepth \!!zeropoint
   \globallet\tabulateruleheight\!!zeropoint
   \edef\@@tabulatealign{\executeifdefined{\??tt:\c!align:\tabulateparameter\c!align}0}%
%    \ExpandFirstAfter\processaction % use \setalignmentswitch instead
%      [\tabulateparameter\c!align]
%      [ \v!normal=>\def\@@tabulatealign{0},% = default value
%         \v!right=>\def\@@tabulatealign{1},% chardefs gebruiken
%          \v!left=>\def\@@tabulatealign{2},%
%        \v!middle=>\def\@@tabulatealign{3},%
%       \s!default=>\def\@@tabulatealign{0},%
%       \s!unknown=>\def\@@tabulatealign{0}]%
   \let\pretabskip\!!zeropoint
   \def\postabskip{.5\tabulateunit}%
   \global\tabulatecolumns\zerocount
   \global\nofautotabulate\zerocount
   \global\noftabulatelines\zerocount
   \totalnoftabulatelines\noftabulatelines
   \minusnoftabulatelines\noftabulatelines
   \global\tabulatepwidth\zeropoint
   \global\tabulateequalfalse
   \resettabulatepheight
   \ifinsidesplitfloat
     \donetrue
   \else\ifinsidefloat
     \donefalse
   \else
     \donetrue
   \fi\fi
   \ifdone
     \chardef\tabulaterepeathead\executeifdefined{\??tt:\c!header:\tabulateparameter\c!header}\zerocount
%      \processaction
%        [\tabulateparameter\c!header]
%        [\v!repeat=>\let\tabulaterepeathead\plusone,
%           \v!text=>\let\tabulaterepeathead\plustwo]%
   \fi
   \unexpanded \def\NC{\tabulatenormalcolumn0}%
   \unexpanded \def\RC{\tabulatenormalcolumn1}%
   \unexpanded \def\HC{\tabulatenormalcolumn2}%
   \unexpanded \def\EQ{\tabulateequalcolumn 0}%
   \unexpanded \def\RQ{\tabulateequalcolumn 1}%
   \unexpanded \def\HQ{\tabulateequalcolumn 2}%
   \unexpanded \def\NG{\NC\handletabulatecharalign}%
   \unexpanded \def\NN{\NC\handletabulatedigits}% new, undocumented, test first
   \unexpanded \def\ND{\NC\handletabulatedigits}% same, for old times sake
   \def\tabulaterule{\HR}% a rule with lineheight
   \def\tabulateline{\HL}% just a spaced rule
   \def\tabulateautorule{\doHR\plusone}%
   \def\tabulateautoline{\doHL\plusone}%
   \def\HR{\doHR\zerocount}
   \def\HL{\doHL\zerocount}
   \unexpanded \def\NR % next row
     {\global\advance\noftabulatelines\plusone
      \global\tabulatefirstflushedfalse
      \global\tabulateequalfalse
      \global\tabulatecolumn\zerocount
      \resettabulatepheight
      \unskip\unskip\crcr\flushtabulated
\TABLEnoalign
  {\the\everyaftertabulaterow}%
      \TABLEnoalign
        {\iftolerantTABLEbreak\else
           \ifconditional\tabulatesomeamble \ifcase\tabulaterepeathead \else
             \allowbreak
           \fi \fi
           \ifnum\noftabulatelines=\plusone
             \dotabulatenobreak
           \else\ifnum\noftabulatelines=\minusnoftabulatelines
             \ifnum\tabulatemaxplines<\plustwo
               \dotabulatenobreak
             \else
               \allowbreak % needed with pbreak prevention
             \fi
           \else
             \allowbreak % needed with pbreak prevention
           \fi\fi
         \fi
         \global\tabulatefirstflushedfalse}}%
   \let\HL\empty % not needed
   \let\SR\NR    \let\AR\NR
   \let\FL\empty \let\FR\NR
   \let\ML\empty \let\MR\NR
   \let\LL\empty \let\LR\NR
   \let\doHR\gobbleoneargument
   \let\doHL\gobbleoneargument
   \global\let\flushtabulated\empty
%    \let\savedbar|\let|\nexttabulate
   \tabskip\zeropoint
   \ifdim\tabulateparameter\c!margin>\zeropoint
     \!!toksa{&\flushtabulateindent\strut##%
               \tabskip\tabulateparameter\c!margin\strut
              &##\tabskip\zeropoint}%
   \else
     \!!toksa{&\flushtabulateindent\strut##%
              &##\tabskip\zeropoint}%
   \fi
   \tabulatewidth\zeropoint
    %    |#1X|\relax
   \nexttabulate #1X|\relax
   \scratchcounter\tabulatecolumns
   \multiply\scratchcounter3%
   \advance\scratchcounter4%
   \edef\totaltabulatecolumns{\the\scratchcounter}%
   \tabulatewidth\zeropoint
   % \dorecurse\tabulatecolumns % can be made faster
   %   {\doifundefinedelse{\@@tabbox@@\recurselevel}
   %      {\expandafter\newbox\csname\@@tabbox@@\recurselevel\endcsname}%
   %      {\global\setbox\csname\@@tabbox@@\recurselevel\endcsname\emptybox}}%
   \initializetableboxes\tabulatecolumns
   \appendtoks&##\to\!!toksa
   \appendtoks\global\advance\tabulatecolumn\plusone\to\!!toksa
   \appendtoks\NC\unskip\unskip\crcr\flushtabulated\to\tabulatedummy % no count
   \global\tabulatecolumn\zerocount
   \resettabulatepheight
   \def\bskip
     {\setbox\tabulatebox\vbox\bgroup
        \global\let\tabulatehook\notabulatehook}%
   \def\eskip
     {\par\egroup
      \global\let\tabulatehook\dotabulatehook}%
   \def\xbskip
     {\hbox\bgroup\vbox\bgroup
        \global\let\tabulatehook\notabulatehook}%
   \def\xeskip
     {\par\egroup\egroup
      \global\let\tabulatehook\dotabulatehook}%
    %    \let|\savedbar
   \global\let\tabulatehook\dotabulatehook
   \doifvalue{\??tt\currenttabulate\c!indenting}\v!no\forgetparindent
   \ifinsidefloat
     \let\tabulateindent\!!zeropoint
   \else
     \setlocalhsize \hsize\localhsize
   \fi
   \dontcomplain
   \forgetall % hm, interference with \forgetparindent ^^^ probably bug, to be solved
   \setbox0\vbox % outside \if because of line counting
     {\notesenabledfalse
      \let\tabulateindent\!!zeropoint
      \trialtypesettingtrue % very important
      \@EA\halign\@EA{\the\!!toksa\crcr\fulltabulatecontent\crcr}}%
   \ifnum\nofautotabulate>\zerocount
     % so, even if the natural size is larger, in the final
     % run, we force the calculated width
     \tabulatewidth\hsize
     \advance\tabulatewidth -\wd0
     \advance\tabulatewidth -\tabulatepwidth
     \ifnum\nofautotabulate>\zerocount
       \divide\tabulatewidth \nofautotabulate\relax
     \fi
   \fi
   \def\xbskip{\bskip}%
   \def\xeskip{\eskip}%
   \ifsplittabulate
     \splittopskip\strutht
     \global\let\flushtabulatedindeed\empty
     \long\def\bbskip
       {\ifvoid\tablebox\tabulatecolumn
          \ifx\flushtabulatedindeed\empty\else
            \setbox0\hbox
          \fi
       \fi}%
     \def\bskip
       {\ifvoid\tablebox\tabulatecolumn
          \global\setbox\tablebox\tabulatecolumn\vbox
          \bgroup
          \global\let\tabulatehook\notabulatehook
          \ifautotabulate\hsize\tabulatewidth\fi
          % \begstrut % interferes with pre-\pars
          % evt: \appendtoks\begstrut\to\everypar
          \ignorespaces
          \def\eskip
            {\par\egroup
             \settabulatepheight
             \global\let\tabulatehook\dotabulatehook
             \splitofftabulatebox}%
        \else
          \let\eskip\empty
          \dontcomplain
          \global\let\tabulatehook\dotabulatehook
          \expandafter\splitofftabulatebox
        \fi}%
     \gdef\flushtabulated
       {\TABLEnoalign % noalign % no interference !
          {\global\let\flushtabulatedindeed\empty
           \global\tabulatecolumn\zerocount
           \handletabulatepbreak
           \dorecurse\tabulatecolumns % was: \noftabcolumns
             {\ifvoid\tablebox\recurselevel\else
                \gdef\flushtabulatedindeed{\the\tabulatedummy}%
              \fi}%
           \global\tabulatefirstflushedtrue}%
        \flushtabulatedindeed}%
   \else
     % tabhook op alles ?
     \def\bskip
       {\vtop\bgroup
          \ifautotabulate\hsize\tabulatewidth\fi
          % \begstrut % interferes with pre-\pars
          % evt: \appendtoks\begstrut\to\everypar
          \ignorespaces}%
     \def\eskip % vertical strut added august 2003
       {\par\verticalstrut\vskip-\struttotal\egroup}%
   \fi
   \totalnoftabulatelines\noftabulatelines
   \minusnoftabulatelines\numexpr\noftabulatelines+\minusone\relax
   \global\noftabulatelines\zerocount
   \def\doHL##1% ##1 ignored
     {\TABLEnoalign
        {\csname
           \ifnum\noftabulatelines=\zerocount             F\else
           \ifnum\noftabulatelines=\totalnoftabulatelines L\else
                                                          M\fi\fi
         L\endcsname}}%
   \def\doHR##1% horizontal rule line (break untested)
     {\TABLEnoalign
        {\globallet\TABLEautoline\dotabulatelinerule
         \ifcase##1\or
           \ifnum\noftabulatelines=\zerocount
             \gdef\TABLEautoline{\TABLEnoalign{}}%
           \else\ifnum\noftabulatelines=\totalnoftabulatelines
             \gdef\TABLEautoline{\TABLEnoalign{}}%
           \fi\fi
         \fi
         \dotabulatenobreak}%
      \TABLEautoline
      \TABLEnoalign
        {\nobreak
         \ifx\TABLEautoline\dotabulatelinerule\kern-\lineheight\fi
         \ifnum\noftabulatelines=\totalnoftabulatelines
           \@EA\dotabulatenobreak
         \else
           \@EA\allowbreak
         \fi}%
      \TABLEautoline
      \TABLEnoalign
        {\dotabulatenobreak}}%
   \doifelsevalue{\??tt\currenttabulate\c!rule}\v!line
     {\let\HL              \HR
      \let\tabulateautoline\tabulateautorule
      \let\tabulateline    \tabulaterule}%
     {\def\HL{\doHL\zerocount}}%
   \def\tablebaselinecorrection
     {\def\dobaselinecorrection
        {\vskip-\prevdepth
         \vskip\strutdp
         \vskip\strutdp}%
      \baselinecorrection}%
   \def\FL{\TABLEnoalign
     {\ifinsidefloat\else
        \doifemptyvalue{\??tt\currenttabulate\c!before} % no expansion
          {\tablebaselinecorrection}%
      \fi
      \dotabulaterule
      \dotabulatenobreak
      \dotabulateruleseperator
      \prevdepth\strutdp
      \dotabulatenobreak}}%
   \def\ML{\TABLEnoalign
     {\dotabulateruleseperator
      \dotabulaterule
      \ifnum\noftabulatelines>\plusone
        \ifnum\noftabulatelines<\minusnoftabulatelines
        % \vskip \topskip\allowbreak \vskip-\topskip
          \vskip1\topskip\allowbreak\vskip-1\topskip
          \vskip-\tabulateparameter\c!rulethickness
          \dotabulaterule
        \fi
      \fi
      \dotabulateruleseperator}}%
   \def\LL{\TABLEnoalign
     {\dotabulatenobreak
      \dotabulateruleseperator
      \dotabulatenobreak
      \dotabulaterule
      \ifinsidefloat\else
        \doifemptyvalue{\??tt\currenttabulate\c!after} % no expansion
          {\vskip\strutdp
           \verticalstrut
           \vskip-\struttotal}%
      \fi}}%
   \let\tabulatepass\plustwo
   %
   \ifcase\tabulaterepeathead
     \ifinsidesplitfloat
       \setbox\tabulatebox\vbox \bgroup
      \else
        \startframedcontent[\tabulateparameter\c!frame]%
      \fi
   \else
     \setbox\tabulatebox\vbox \bgroup
   \fi
   %
   \@EA\halign\@EA{\the\!!toksa\crcr\fulltabulatecontent\crcr}%
   \prevdepth\strutdp % nog eens beter, temporary hack
   \doifvalue{\??tt\currenttabulate\c!distance}\v!grid
     {\vskip-\strutdp}% experimental tm-prikkels
   %
   \ifcase\tabulaterepeathead
     \ifinsidesplitfloat
       \egroup \splittabulatebox\tabulatebox
     \else
       \stopframedcontent
     \fi
   \else
     \egroup \splittabulatebox\tabulatebox
   \fi
   %
   \egroup
   \ifinsidefloat \else
     \tabulateparameter\c!after
   \fi
   \egroup}

\egroup

% \setuptabulate[split=yes,header=text,title=Vervolg van Tabel]
%
% % \starttabulatehead
% % \NC test \NC hans\NC \NR
% % \stoptabulatehead
%
% \starttabulate
% \NC test \NC \input tufte \relax \NC \NR
% \NC test \NC \input knuth \relax \NC \NR
% \NC test \NC \input knuth \relax \NC \NR
% \NC test \NC \input tufte \relax \NC \NR
% \NC test \NC \input tufte \relax \NC \NR
% \NC test \NC \input tufte \relax \NC \NR
% \stoptabulate

% \def\splittabulatebox#1% #1 <> 0/2 / derived from the one in core-ntb.tex
%   {\ifinsidefloat
%      \unvbox#1%
%    \else
%      \ifcase\tabulaterepeathead\or
%        \setbox2\copy#1%
%        \setbox2\vsplit2 to \lineheight
%        \setbox2\vbox{\unvbox2}%
%      \fi
%      \doloop
%        {\setbox0\vsplit#1 to \onepoint % \lineheight
%         \ifdim\pagegoal<\maxdimen
%           \donetrue
%         \else\ifdim\pagetotal=\zeropoint
%           \donetrue
%         \else
%           \donefalse
%         \fi\fi
%         \ifdone
%           \setbox0\vbox{\unvbox0}%
%           \dimen0\pagetotal
%           \advance\dimen0\dp0
%           \advance\dimen0\ht0
%           \ifdim\dimen0>\pagegoal
%             \bgroup \page \egroup % make sure that local vars are kept
%             \ifcase\tabulaterepeathead\or
%               \unvcopy2
%             \or
%               \hbox{\strut\tabulateparameter\c!title}%
%             \fi
%           \fi
%         \fi
%         % test this on icare checklists / quite hacky ! ! !
%         \ifdim\ht0>\tabulateparameter\c!rulethickness\else
%           \kern-2\ht0 % brrrr
%         \fi
%         %
%         \unvbox0
%         \allowbreak
%         \ifvoid#1 \exitloop \fi}%
%    \fi}

\def\splittabulatebox#1% #1 <> 0/2 / derived from the one in core-ntb.tex
  {\ifinsidesplitfloat
     \dosplittabulatebox#1%
   \else\ifinsidefloat
     \unvbox#1%
   \else
     \dosplittabulatebox#1%
   \fi\fi}

\def\dosplittabulatebox#1%
  {\resettsplit
   \def\tsplitminimumfreelines{2}%
   \def\tsplitminimumfreespace{0pt}%
   \setbox\tsplitcontent\box#1%
   \ifcase\tabulaterepeathead\or
     \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
     \setbox\tsplithead\vbox{\unvbox\tsplithead}%
   \or
     \setbox\tsplithead\vbox{\hbox{\strut\tabulateparameter\c!title}}%
   \fi
   \handletsplit}

%D \starttyping
%D \setuptabulate[split=no,rule=line]
%D
%D \starttabulate
%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
%D \stoptabulate
%D \stoptyping

% \starttabulatie[|mc|]
% \NC \digits{100.000,00} \NC\NR
% \NC \digits{@10.000,00} \NC\NR
% \NC \digits{@@@.100,00} \NC\NR
% \NC \digits{@@@.@10,@@} \NC\NR
% \NC \digits{@@@.@@1,@@} \NC\NR
% \stoptabulatie
%
% \starttabulatie[|mc|]
% \ND 100.000,00 \NC\NR
% \ND @10.000,00 \NC\NR
% \ND @@@.100,00 \NC\NR
% \ND @@@.@10,@@ \NC\NR
% \ND @@@.@@1,@@ \NC\NR
% \stoptabulatie
%
% \starttabulatie[|c|]
% \ND $100.000,00$ \NC\NR
% \ND $@10.000,00$ \NC\NR
% \ND $@@@.100,00$ \NC\NR
% \ND $@@@.@10,@@$ \NC\NR
% \ND $@@@.@@1,@@$ \NC\NR
% \stoptabulatie
%
% \starttabulatie[|c|]
% \NC $\digits 100.000,00 $ \NC\NR
% \NC $\digits @10.000,00 $ \NC\NR
% \NC $\digits @@@.100,00 $ \NC\NR
% \NC $\digits @@@.@10,@@ $ \NC\NR
% \NC $\digits @@@.@@1,@@ $ \NC\NR
% \stoptabulatie
%
% \starttabulatie[|c|]
% \NC \digits $100.000,00$ \NC\NR
% \NC \digits $@10.000,00$ \NC\NR
% \NC \digits $@@@.100,00$ \NC\NR
% \NC \digits $@@@.@10,@@$ \NC\NR
% \NC \digits $@@@.@@1,@@$ \NC\NR
% \stoptabulatie

\def\setuptabulate
  {\dotripleempty\dosetuptabulate}

\def\dosetuptabulate[#1][#2][#3]%
  {\ifthirdargument
     \getparameters[\??tt#1::#2][#3]%
   \else\ifsecondargument
     \getparameters[\??tt#1::][#2]%
   \else
     \getparameters[\??tt\v!tabulate::][#1]%
   \fi\fi}

\setuptabulate
  [\c!unit=1em,
   EQ={:},
   \c!frame=\v!off,
   \c!bodyfont=,
   \c!rule=\v!normal,
   \c!rulecolor=,
   \c!rulethickness=\linewidth,
   \c!inner=,
   \c!before=\blank,
   \c!after=\blank,
   \c!distance={\v!depth,\v!medium},
   \c!align=\v!normal,
   \c!margin=\!!zeropoint,
   \c!split=\v!auto,
   \c!header=\v!yes,
   \c!title=,
   \c!indenting=\v!no]

\protect \endinput
