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

%D This module has a more modern variant in xtables but as we follow a bit different
%D approach with settings there, this mechanism will stay. In fact each of them has
%D its advantages. This module could be sped up a bit and made more efficient by
%D delegating some housekeeping to \LUA\ but it's not worth the effort. The code
%D could me made more readable but again, there is no real purpose in it. If needed
%D I can squeeze out a few more percentages runtime.

% columndistance 'optimized' ... needs checking
%
% we don't need the alignment mechanism .. we can just pack the row in a box

\writestatus{loading}{ConTeXt Table Macros / Natural Tables}

\registerctxluafile{tabl-ntb}{autosuffix}

% sometimes this helps (with nc going wild): \setupTABLE[maxwidth=100cm]
%
% bug: width 3cm is not honored and column becomes too wide as given width is added
% to distributed width
%
% \bTABLE
%     \bTR
%         \bTD test \eTD
%         \bTD \framed[height=3cm]{test} \eTD
%         \bTD[width=3cm] \dorecurse{30}{a } \eTD
%         \bTD \input ward \eTD
%     \eTR
%     \bTR
%         \bTD test \eTD
%         \bTD \framed[height=3cm]{test} \eTD
%         \bTD \dorecurse{30}{a } \eTD
%         \bTD \input ward \eTD
%     \eTR
% \eTABLE

% \protected\def\startrow            {\bTR}
% \protected\def\stoprow             {\eTR}
% \protected\def\startcell#1\stopcell{\bTD#1\eTD}
%           \let\stopcell             \relax
%           \let\startcelltable       \bTABLE
%           \let\stopcelltable        \eTABLE

% \starttext
%     \startcelltable
%         \startrow \startcell a \stopcell \stoprow
%         \startrow \startcell a \stopcell \stoprow
%         \startrow \startcell a \stopcell \stoprow
%         \startrow \startcell a \stopcell \stoprow
%     \stopcelltable
% \stoptext

%D As always, this is the n\high{th} version. Much time went in trying to speed up
%D the many cell calculations, some optimizations were rejected in order not to
%D complicate this module too much (and in order to prevail extensibility). In the
%D meantime we've sacrified some speed for readability.

\unprotect

%D The next alternative also takes care of preceding and following white space.
%D
%D \startbuffer
%D \bTABLE[left={(},right={)},top=\startnarrower,bottom=\stopnarrower]
%D \bTR \bTD something \eTD \eTR
%D \eTABLE
%D \stopbuffer
%D
%D \typebuffer \getbuffer

\ifdefined\dotagTABLEcell   \else \aliased\let\dotagTABLEcell  \relax \fi % todo: namespace
\ifdefined\dotagTABLEsignal \else \aliased\let\dotagTABLEsignal\relax \fi % todo: namespace

\let\tabl_ntb_next_level\relax

\newtoks\t_tabl_ntb_cell_start
\newtoks\t_tabl_ntb_cell_stop

\appendtoks
    \naturaltablelocalparameter\c!left
    \delayedbegstrut
\to \t_tabl_ntb_cell_start

\appendtoks
    \delayedendstrut
    \naturaltablelocalparameter\c!right
\to \t_tabl_ntb_cell_stop

\appendtoks
    \flushpostponednodedata
    % maybe: \the\neverypar
\to \t_tabl_ntb_cell_start

\protected\def\tabl_ntb_cell_start
  {% \inhibitblank
   \dotagTABLEcell
  %\tabl_ntb_next_level
   \font_styles_math_reset
   \usenaturaltablelocalstyleandcolor\c!style\c!color % done twice ? needed for style (test onbly style)
   \everypar\t_tabl_ntb_cell_start
   \font_styles_math_start}

\protected\def\tabl_ntb_cell_stop
  {\font_styles_math_stop
   \ifhmode
     \expand\t_tabl_ntb_cell_stop
     \par % added 13/4/2006
   \orelse\ifdim\prevdepth<\zeropoint % =-1000pt ?
     % not sure yet:\naturaltablelocalparameter\c!right
     \vskip-\strutdp
   \else
     \removebottomthings
   \fi}

% maybe:
%
% \protected\def\tabl_ntb_cell_stop
%   {\ifhmode
%      \expand\t_tabl_ntb_cell_stop
%      \par % added 13/4/2006
%    \else
%      % not sure yet:\naturaltablelocalparameter\c!right
%      \par
%      \ifhmode
%         % \removeunwantedspaces
%      \orelse\ifdim\prevdepth<\zeropoint % =-1000pt ?
%        \vskip-\strutdp
%      \else
%        \removebottomthings
%      \fi
%    \fi}

\newinteger    \c_tabl_ntb_row
\newinteger    \c_tabl_ntb_col
\newinteger    \c_tabl_ntb_spn

\newinteger    \c_tabl_ntb_nx
\newinteger    \c_tabl_ntb_ny

\setnewconstant\c_tabl_ntb_cell \plusone
\setnewconstant\c_tabl_ntb_none \plustwo

\newinteger    \c_tabl_ntb_current_row
\newinteger    \c_tabl_ntb_current_col
\newinteger    \c_tabl_ntb_current_row_one
\newinteger    \c_tabl_ntb_current_col_one
\newinteger    \c_tabl_ntb_current_row_two
\newinteger    \c_tabl_ntb_current_col_two
\newinteger    \c_tabl_ntb_current_row_three
\newinteger    \c_tabl_ntb_current_col_three
\newinteger    \c_tabl_ntb_current_row_four
\newinteger    \c_tabl_ntb_current_col_four

\newinteger    \c_tabl_ntb_running_col        \def\c_tabl_ntb_running_col_reference{\c_tabl_ntb_running_col}
\newinteger    \c_tabl_ntb_maximum_row
\newinteger    \c_tabl_ntb_maximum_col
\newinteger    \c_tabl_ntb_maximum_row_span
\newinteger    \c_tabl_ntb_maximum_col_span

\newinteger    \c_tabl_ntb_encountered_col
\newinteger    \c_tabl_ntb_encountered_max

\newtoks       \t_tabl_ntb
\newtoks       \t_tabl_ntb_row

\newconstant   \c_tabl_tbl_pass

\newtoks       \t_tabl_ntb_head
\newtoks       \t_tabl_ntb_next
\newtoks       \t_tabl_ntb_body
\newtoks       \t_tabl_ntb_foot

\newinteger    \c_tabl_ntb_n_of_head_lines
\newinteger    \c_tabl_ntb_n_of_next_lines
\newinteger    \c_tabl_ntb_n_of_hdnx_lines

\newdimension  \d_tabl_ntb_height
\newdimension  \d_tabl_ntb_width

\newdimension  \d_tabl_ntb_leftmargindistance
\newdimension  \d_tabl_ntb_rightmargindistance
\newdimension  \d_tabl_ntb_columndistance
\newdimension  \d_tabl_ntb_maxwidth

\newtoks       \everyTABLEpass    % public

\newtoks       \t_tabl_ntb_initializers_first  % trial
\newtoks       \t_tabl_ntb_initializers_second % final

\newinteger    \tablecellrows    % public (needs checking)
\newinteger    \tablecellcolumns % public (needs checking)

\newbox        \b_tabl_ntb_final

%D For tagging and export:

\newconstant    \c_tabl_ntb_head
\newconstant    \c_tabl_ntb_body
\newconstant    \c_tabl_ntb_foot
\newconditional \c_tabl_ntb_okay

%D For local anchoring:

\installcorenamespace{naturaltableanchor}

\let\tabl_ntb_anchor_start  \gobbletwoarguments
\let\tabl_ntb_anchor_stop   \relax
\let\tabl_ntb_anchor_process\gobbleoneargument

\lettonothing\m_tabl_ntb_anchor_background

\let\xanchor\!!zerocount
\let\yanchor\!!zerocount

\def\tabl_ntb_anchor_start_indeed#1#2%
  {\hpack\bgroup
   \edef\xanchor{\number#2}%
   \edef\yanchor{\number#1}%
   \markanchor{matrix}{#1}{#2}}

\let\tabl_ntb_anchor_stop_indeed\egroup

\def\tabl_ntb_anchor_process_indeed#1%
  {\localframed[\??naturaltableanchor]{\box#1}}

\definesimplifiedframed
  [\??naturaltableanchor]

\setupframed
  [\??naturaltableanchor]
  [\c!synchronize=\v!background,
   \c!background=\m_tabl_ntb_anchor_background]

\def\tabl_ntb_anchor_setup
  {\ifcstok{\naturaltablelocalparameter\c!synchronize}\v!background
     \let\tabl_ntb_anchor_start\tabl_ntb_anchor_start_indeed
     \let\tabl_ntb_anchor_stop\tabl_ntb_anchor_stop_indeed
     \let\tabl_ntb_anchor_process\tabl_ntb_anchor_process_indeed
     \edef\m_tabl_ntb_anchor_background{\naturaltablelocalparameter\c!background}%
     \resetnaturaltablelocalparameter\c!background
     \setlocalanchoring
   \else
     \lettonothing\m_tabl_ntb_anchor_background
     \let\tabl_ntb_anchor_start\gobbletwoarguments
     \let\tabl_ntb_anchor_stop\relax
     \let\tabl_ntb_anchor_process\gobbleoneargument
   \fi
   \resetnaturaltablelocalparameter\c!synchronize}

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

\newinteger\c_tabl_level

\installglobalmacrostack\m_tabl_ntb_saved_row
\installglobalmacrostack\m_tabl_ntb_saved_col

\protected\def\tabl_ntb_table_push
  {\ifnum\m_tabl_ntb_level>\plusone
     \tabl_ntb_parameters_reset
     % we need a proper count push/pop
     \xdef\m_tabl_ntb_saved_row{\the\c_tabl_ntb_row}\push_macro_m_tabl_ntb_saved_row
     \xdef\m_tabl_ntb_saved_col{\the\c_tabl_ntb_col}\push_macro_m_tabl_ntb_saved_col
   \else
     \global\intabletrue
   \fi}

\protected\def\tabl_ntb_table_pop
  {\ifnum\m_tabl_ntb_level>\plusone
     \pop_macro_m_tabl_ntb_saved_row\global\c_tabl_ntb_row\m_tabl_ntb_saved_row
     \pop_macro_m_tabl_ntb_saved_col\global\c_tabl_ntb_col\m_tabl_ntb_saved_col
   \else
     \global\intablefalse
   \fi}

\lettonothing\m_tabl_ntb_level

\protected\def\tabl_ntb_next_level
  {\advanceby\c_tabl_level\plusone
   \cdef\m_tabl_ntb_level{\the\c_tabl_level}}

\protected\def\tabl_ntb_prev_level
  {\advanceby\c_tabl_level\minusone
   \cdef\m_tabl_ntb_level{\the\c_tabl_level}}

\tabl_ntb_next_level % go to level 1

\installcorenamespace{naturaltable}      % was tbl
\installcorenamespace{naturaltablelocal} % was tbltbl

\installdirectcommandhandler       \??naturaltable      {naturaltable}      % \??naturaltable
\installsimpleframedcommandhandler \??naturaltablelocal {naturaltablelocal} \??naturaltablelocal

\permanent\protected\def\bTABLEnested{\tabl_ntb_next_level\bTABLE}
\permanent\protected\def\eTABLEnested{\eTABLE\tabl_ntb_prev_level}

\installcorenamespace{naturaltabletal}
\installcorenamespace{naturaltablegal}
\installcorenamespace{naturaltablenob}
\installcorenamespace{naturaltabletag}
\installcorenamespace{naturaltablecol}
\installcorenamespace{naturaltablerow}
\installcorenamespace{naturaltablewd}
\installcorenamespace{naturaltableht}
\installcorenamespace{naturaltabledp}
\installcorenamespace{naturaltablewid}
\installcorenamespace{naturaltablehei}
\installcorenamespace{naturaltabledis}
\installcorenamespace{naturaltableaut}
\installcorenamespace{naturaltablebck}
%installcorenamespace{naturaltablefwd} % forcedwidth
\installcorenamespace{naturaltabletxt}
\installcorenamespace{naturaltablespn}
\installcorenamespace{naturaltableref}
\installcorenamespace{naturaltableset}
\installcorenamespace{naturaltablecell}
\installcorenamespace{naturaltablesqueeze}
\installcorenamespace{naturaltabletok}

% \integerdefcsname
% \dimensiondefcsname

\letcsname\??naturaltablesqueeze        \endcsname\donefalse
\letcsname\??naturaltablesqueeze\v!fit  \endcsname\donetrue
\letcsname\??naturaltablesqueeze\v!fixed\endcsname\donetrue
\letcsname\??naturaltablesqueeze\v!broad\endcsname\donetrue
\letcsname\??naturaltablesqueeze\v!local\endcsname\donetrue

\def\tabl_ntb_let_gal{\gletcsname\??naturaltablegal\m_tabl_ntb_level\endcsname}
\def\tabl_ntb_get_gal{\csname    \??naturaltablegal\m_tabl_ntb_level\endcsname}

\def\tabl_ntb_let_tal#1{\gletcsname\??naturaltabletal\m_tabl_ntb_level:\number#1\endcsname}
\def\tabl_ntb_get_tal#1{\csname    \??naturaltabletal\m_tabl_ntb_level:\number#1\endcsname}

\def\tabl_ntb_set_nob#1{\letcsname\??naturaltablenob\m_tabl_ntb_level:\number#1\endcsname\plusone}
\def\tabl_ntb_get_nob#1{\ifcsname \??naturaltablenob\m_tabl_ntb_level:\number#1\endcsname\plusone\else\zerocount\fi}

%def\tabl_ntb_set_tag#1#2{\expandafter\integerdef\csname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_set_col#1#2{\expandafter\integerdef\csname\??naturaltablecol\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_set_row#1#2{\expandafter\integerdef\csname\??naturaltablerow\m_tabl_ntb_level:\number#1:\number#2\endcsname}

\def\tabl_ntb_let_tag#1#2{\letcsname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_let_col#1#2{\letcsname\??naturaltablecol\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_let_row#1#2{\letcsname\??naturaltablerow\m_tabl_ntb_level:\number#1:\number#2\endcsname}

%     \let\tabl_ntb_let_col\tabl_ntb_set_col
%     \let\tabl_ntb_let_row\tabl_ntb_set_row

%def\tabl_ntb_set_wd#1#2{\global\expandafter\dimensiondef\csname\??naturaltablewd\m_tabl_ntb_level:\number#1:\number#2\endcsname} % global !
\def\tabl_ntb_set_ht#1#2{\global\expandafter\dimensiondef\csname\??naturaltableht\m_tabl_ntb_level:\number#1:\number#2\endcsname} % global !

%def\tabl_ntb_let_wd#1#2{\letcsname\??naturaltablewd\m_tabl_ntb_level:\number#1:\number#2\endcsname} % global !
\def\tabl_ntb_let_ht#1#2{\letcsname\??naturaltableht\m_tabl_ntb_level:\number#1:\number#2\endcsname} % global !

%     \let\tabl_ntb_let_ht\tabl_ntb_set_ht

\def\tabl_ntb_get_tag#1#2{\csname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_get_col#1#2{\csname\??naturaltablecol\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_get_row#1#2{\csname\??naturaltablerow\m_tabl_ntb_level:\number#1:\number#2\endcsname}

%def\tabl_ntb_get_wd#1#2{\csname\??naturaltablewd\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_get_ht#1#2{\csname\??naturaltableht\m_tabl_ntb_level:\number#1:\number#2\endcsname}

\def\tabl_ntb_set_wid#1{\global\expandafter\dimensiondef\csname\??naturaltablewid\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !
\def\tabl_ntb_set_hei#1{\global\expandafter\dimensiondef\csname\??naturaltablehei\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !
\def\tabl_ntb_set_dis#1{\global\expandafter\dimensiondef\csname\??naturaltabledis\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !
\def\tabl_ntb_set_aut#1{\global\expandafter\dimensiondef\csname\??naturaltableaut\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !

\def\tabl_ntb_let_wid#1{\gletcsname\??naturaltablewid\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !
\def\tabl_ntb_let_hei#1{\gletcsname\??naturaltablehei\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !
\def\tabl_ntb_let_dis#1{\gletcsname\??naturaltabledis\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !
\def\tabl_ntb_let_aut#1{\gletcsname\??naturaltableaut\m_tabl_ntb_level:\number#1\endcsname} % {#2} global !

%     \let\tabl_ntb_let_wid\tabl_ntb_set_wid
%     \let\tabl_ntb_let_hei\tabl_ntb_set_hei
%     \let\tabl_ntb_let_dis\tabl_ntb_set_dis
%     \let\tabl_ntb_let_aut\tabl_ntb_set_aut

\def\tabl_ntb_get_wid#1{\ifcsname\??naturaltablewid\m_tabl_ntb_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
\def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_ntb_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
\def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_ntb_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi}
\def\tabl_ntb_get_aut#1{\csname  \??naturaltableaut\m_tabl_ntb_level:\number#1\endcsname}

\def\tabl_ntb_let_bck#1#2{\global\expandafter\integerdef\csname\??naturaltablebck\m_tabl_ntb_level:\number#1:\number#2\endcsname}

\def\tabl_ntb_get_bck#1#2{\csname\??naturaltablebck\m_tabl_ntb_level:\number#1:\number#2\endcsname}

\def\tabl_ntb_tag_pattern#1#2{\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2}
\def\tabl_ntb_row_pattern#1#2{\??naturaltablerow\m_tabl_ntb_level:\number#1:\number#2}
\def\tabl_ntb_col_pattern#1#2{\??naturaltablecol\m_tabl_ntb_level:\number#1:\number#2}

\def\tabl_ntb_tag_doif    #1#2{\ifcsname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument   \fi}
\def\tabl_ntb_tag_doifnot #1#2{\ifcsname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument  \else\expandafter\firstofoneargument  \fi}
\def\tabl_ntb_tag_doifelse#1#2{\ifcsname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi}
\def\tabl_ntb_row_doif    #1#2{\ifcsname\??naturaltablerow\m_tabl_ntb_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument   \fi}
\def\tabl_ntb_col_doif    #1#2{\ifcsname\??naturaltablecol\m_tabl_ntb_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument   \fi}
\def\tabl_ntb_col_doifnot #1#2{\ifcsname\??naturaltablecol\m_tabl_ntb_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument  \else\expandafter\firstofoneargument  \fi}

%D If we ever run into memory issues we can do:
%
% \def\tabl_ntb_let_tag#1#2#3%
%   {\ifx#3\c_tabl_ntb_none\else
%      \letcsname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname#3%
%    \fi}
%
% \def\tabl_ntb_get_tag#1#2%
%   {\ifcsname\??naturaltabletag\m_tabl_ntb_level:\number#1:\number#2\endcsname
%      \lastnamedcs
%    \else
%      \c_tabl_ntb_none
%    \fi}

\def\tabl_ntb_let_ref   #1#2{\gletcsname\??naturaltableref\m_tabl_ntb_level:\number#1:\number#2\endcsname}
\def\tabl_ntb_set_ref   #1#2{\xdefcsname\??naturaltableref\m_tabl_ntb_level:\number#1:\number#2\endcsname}
%def\tabl_ntb_get_ref   #1#2{\ifcsname\??naturaltableref\m_tabl_ntb_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_ntb_level:\number#1:\number#2\endcsname\fi}
\def\tabl_ntb_get_ref   #1#2{\begincsname\??naturaltableref\m_tabl_ntb_level:\number#1:\number#2\endcsname}

% \def\tabl_ntb_set_spn     #1{\letcsname\??naturaltablespn\m_tabl_ntb_level:\number#1\endcsname \!!plusone}
% \def\tabl_ntb_spn_doifelse#1{\ifcase0\csname\??naturaltablespn\m_tabl_ntb_level:\number#1\endcsname\relax % could be inlined
%                                \expandafter\secondoftwoarguments % unset
%                              \else
%                                \expandafter\firstoftwoarguments  % a span
%                              \fi}

\def\tabl_ntb_set_spn      #1{\letcsname\??naturaltablespn\m_tabl_ntb_level:\number#1\endcsname\plusone}
%def\tabl_ntb_spn_doifelse #1{\ifcsname\??naturaltablespn\m_tabl_ntb_level:\number#1\endcsname
%                               \expandafter\firstoftwoarguments  % a span
%                             \else
%                               \expandafter\secondoftwoarguments % unset
%                             \fi}
\def\tabl_ntb_spn_condition#1{\ifcsname\??naturaltablespn\m_tabl_ntb_level:\number#1\endcsname}

\protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6%
  {\defcsname\??naturaltabletxt\m_tabl_ntb_level:\number#1:\number#2\endcsname
     {\tabl_ntb_cell_process{#3}{#4}[#5]{\tabl_ntb_next_level#6\tabl_ntb_prev_level}}}

\def\tabl_ntb_get_txt#1#2%
  {\csname\??naturaltabletxt\m_tabl_ntb_level:\number#1:\number#2\endcsname}

% to be changed:

\newif\ifsqueezeTBLspan     \squeezeTBLspantrue     % spans one column cell over multi column par cells
\newif\ifautosqueezeTBLspan \autosqueezeTBLspantrue % unless explicit widths are given
\newif\ifautoTBLspread      \autoTBLspreadfalse
\newif\ifautoTBLhsize       \autoTBLhsizetrue
\newif\ifautoTBLrowspan     \autoTBLrowspantrue
\newif\ifautoTBLemptycell   \autoTBLemptycelltrue
\newif\ifautoTBLcheckwidth  \autoTBLcheckwidthtrue
\newif\ifappendTBLsetups    \appendTBLsetupstrue
\newif\ifenableTBLbreak     \enableTBLbreakfalse
\newif\ifforceTBLpageflow   \forceTBLpageflowfalse
\newif\ifmultipleTBLheads   \multipleTBLheadsfalse
\newif\iftightTBLrowspan    \tightTBLrowspantrue
\newif\iftightTBLcolspan    \tightTBLcolspanfalse

\newconditional \c_tabl_ntb_trace_widths

\installtextracker
  {tables.natural.widths}
  {\c_tabl_ntb_trace_widths\conditionaltrue}
  {\c_tabl_ntb_trace_widths\conditionalfalse}

% so far

\protected\def\tabl_ntb_cell_process#1#2[#S#3]{}

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

%D We have an extensive setup mechanism, it's flexible but also comes with
%D overhead, mainly due to the many possible combinations.

\installcorenamespace{naturaltablesetupthree}
\installcorenamespace{naturaltablesetuptwo}

\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal

\let\tabl_ntb_setup_step     \gobbleoneargument
\let\tabl_ntb_setup_step_step\gobbleoneargument

\permanent\tolerant\protected\def\setupTABLE[#S#1]#*[#S#2]#*[#S#3]%
  {\ifarguments
     \expandafter\gobblethreearguments
   \or
     \expandafter\tabl_ntb_setup_one
   \or
     \expandafter\tabl_ntb_setup_two
   \or
     \expandafter\tabl_ntb_setup_three
   \fi{#1}{#2}{#3}}

\def\tabl_ntb_setup_one#1#2#3%
  {\setupcurrentnaturaltablelocal[#1]}

\def\tabl_ntb_setup_xy#1#2#3%
  {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set{#1##1}{#3}}%
   \processcommalist[#2]\tabl_ntb_setup_step}

\def\tabl_ntb_setup_un#1#2#3%
  {\def\tabl_ntb_setup_step##1%
     {\def\tabl_ntb_setup_step_step####1{\tabl_ntb_parameters_set{\c!x##1\c!y####1}{#3}}%
      \processcommalist[#2]\tabl_ntb_setup_step_step}%
   \processcommalist[#1]\tabl_ntb_setup_step}

\def\tabl_ntb_setup_each#1#2#3% ignores #3
  {\tabl_ntb_parameters_set{#1\v!each}{#2}}

\def\tabl_ntb_setup_ux#1#2#3% ignores #3
  {\def\tabl_ntb_setup_step##1{\tabl_ntb_parameters_set{\c!x##1}{#2}}%
   \processcommalist[#1]\tabl_ntb_setup_step}

\def\tabl_ntb_setup_three#1{\ifcsname\??naturaltablesetupthree#1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_un\fi{#1}}
\def\tabl_ntb_setup_two  #1{\ifcsname\??naturaltablesetuptwo  #1\endcsname\expandafter\lastnamedcs\else\expandafter\tabl_ntb_setup_ux\fi{#1}}

\defcsname\??naturaltablesetupthree    \v!row\endcsname#-{\tabl_ntb_setup_xy  \c!y}
\defcsname\??naturaltablesetupthree \v!column\endcsname#-{\tabl_ntb_setup_xy  \c!x}
\defcsname\??naturaltablesetupthree  \v!start\endcsname#-{\tabl_ntb_setup_xy  \v!start}
\defcsname\??naturaltablesetupthree \v!header\endcsname#-{\tabl_ntb_setup_xy  \v!header}

\defcsname\??naturaltablesetuptwo      \v!row\endcsname#-{\tabl_ntb_setup_each\c!y}
\defcsname\??naturaltablesetuptwo   \v!column\endcsname#-{\tabl_ntb_setup_each\c!x}
\defcsname\??naturaltablesetuptwo    \v!start\endcsname#-{\tabl_ntb_setup_each\v!start}
\defcsname\??naturaltablesetuptwo   \v!header\endcsname#-{\tabl_ntb_setup_each\v!header}

\letcsname\??naturaltablesetupthree\s!unknown\endcsname\tabl_ntb_setup_un
\letcsname\??naturaltablesetuptwo  \s!unknown\endcsname\tabl_ntb_setup_ux

\letcsname\??naturaltablesetupthree r\expandafter\endcsname\csname\??naturaltablesetupthree   \v!row\endcsname
\letcsname\??naturaltablesetupthree c\expandafter\endcsname\csname\??naturaltablesetupthree\v!column\endcsname
\letcsname\??naturaltablesetupthree y\expandafter\endcsname\csname\??naturaltablesetupthree   \v!row\endcsname
\letcsname\??naturaltablesetupthree x\expandafter\endcsname\csname\??naturaltablesetupthree\v!column\endcsname

\letcsname\??naturaltablesetuptwo   r\expandafter\endcsname\csname\??naturaltablesetuptwo     \v!row\endcsname
\letcsname\??naturaltablesetuptwo   c\expandafter\endcsname\csname\??naturaltablesetuptwo  \v!column\endcsname
\letcsname\??naturaltablesetuptwo   y\expandafter\endcsname\csname\??naturaltablesetuptwo     \v!row\endcsname
\letcsname\??naturaltablesetuptwo   x\expandafter\endcsname\csname\??naturaltablesetuptwo  \v!column\endcsname

\def\tabl_ntb_parameters_set#1#2%
  {\ifappendTBLsetups
     \ifcsname\??naturaltableset\m_tabl_ntb_level:#1\endcsname
       \enforced\def\tabl_ntb_parameters_get[##S##1]%
         {\defcsname\??naturaltableset\m_tabl_ntb_level:#1\endcsname{\tabl_ntb_parameters_get[##1,#2]}}%
       \csname\??naturaltableset\m_tabl_ntb_level:#1\endcsname
       \enforced\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal
     \else
       \defcsname\??naturaltableset\m_tabl_ntb_level:#1\endcsname{\tabl_ntb_parameters_get[#2]}%
     \fi
   \else
     \defcsname\??naturaltableset\m_tabl_ntb_level:#1\endcsname{\tabl_ntb_parameters_get[#2]}%
   \fi}

% % \setupTABLE [y]    [first][background=color,backgroundcolor=blue,frame=off,bottomframe=on,topframe=on,framecolor=white]
% \setupTABLE [first][first][backgroundcorner=2,corner=10,frame=on]
% \setupTABLE [last] [first][backgroundcorner=4,corner=12,frame=on]
%
% \setupTABLE [row]  [each] [background=color,backgroundcolor=blue,frame=on,framecolor=white]
% \setupTABLE [first][2]    [corner=8]
% \setupTABLE [last] [2]    [corner=5]
% \setupTABLE [first][last] [corner=7]
% \setupTABLE [last] [last] [corner=6]
%
% \startTEXpage
% \bTABLE[frame=off,align=middle]
% \bTR \bTD one   \eTD \bTD two    \eTD \bTD three \eTD \eTR
% \bTR \bTD first \eTD \bTD second \eTD \bTD third \eTD \eTR
% \bTR \bTD alpha \eTD \bTD beta   \eTD \bTD gamma \eTD \eTR
% \eTABLE
% \stopTEXpage
%
% \setupTABLE [first] [two][corner=2] % special case
% \setupTABLE [last]  [two][corner=4] % special case
%
% % % \setupTABLE [one] [first] ... special case of span
%
% \startTEXpage
% \bTABLE[frame=off,align=middle]
% \bTR \bTD one   \eTD \bTD two    \eTD \bTD three \eTD \eTR
% \bTR \bTD first \eTD \bTD second \eTD \bTD third \eTD \eTR
% \eTABLE
% \stopTEXpage

%D By default rowspans are tight but you can change that:
%D
%D \startbuffer
%D \bTABLE
%D \bTR[height=20pt] \bTH 1. col                \eTH \bTH 2. col                 \eTH  \eTR
%D \bTR[height=20pt] \bTD 1 row in 1. col       \eTD \bTD[nr=2] 2 rows in 2. col \eTD  \eTR
%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 1. col\eTD                                   \eTR
%D \bTR[height=20pt]                                 \bTD[nr=3] 3 rows in 2. col \eTD  \eTR
%D \bTR[height=20pt] \bTD 1 row in 1. col       \eTD                                   \eTR
%D \bTR[height=20pt] \bTD 1 row in 1. col       \eTD                                   \eTR
%D \eTABLE
%D
%D \bTABLE
%D \bTR[height=20pt] \bTH 2. col                 \eTH  \bTH 1. col                \eTH \eTR
%D \bTR[height=20pt] \bTD[nr=2] 2 rows in 2. col \eTD  \bTD 1 row in 1. col       \eTD \eTR
%D \bTR[height=20pt]                                   \bTD[nr=2] 2 rows in 1. col\eTD \eTR
%D \bTR[height=20pt] \bTD[nr=3] 3 rows in 2. col \eTD                                  \eTR
%D \bTR[height=20pt]                                   \bTD 1 row in 1. col       \eTD \eTR
%D \bTR[height=20pt]                                   \bTD 1 row in 1. col       \eTD \eTR
%D \eTABLE
%D \stopbuffer
%D
%D \typebuffer
%D
%D \getbuffer
%D
%D With \type {\tightTBLrowspanfalse} we get:
%D
%D \start \tightTBLrowspanfalse \getbuffer \stop

\let\tabl_ntb_setup_section\relax

\lettonothing\m_tabl_ntb_negative_col
\lettonothing\m_tabl_ntb_negative_row
\lettonothing\m_tabl_ntb_positive_col
\lettonothing\m_tabl_ntb_positive_row

\lettonothing\m_tabl_ntb_prefix

\protected\def\tabl_ntb_setup_cell#1#2% cell over col over row
  {\tabl_ntb_setup_section % already forgotten
   \edef\m_tabl_ntb_positive_row{\tointeger#1}%
   \edef\m_tabl_ntb_positive_col{\tointeger#2}%
   \edef\m_tabl_ntb_negative_row{\tointeger{-\c_tabl_ntb_maximum_row+#1+\minusone}}%
   \edef\m_tabl_ntb_negative_col{\tointeger{-\c_tabl_ntb_maximum_col+#2+\minusone}}%
   % saves tokens (no speed gain)
   \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_ntb_level:}% can move to \tabl_ntb_next_level etc
   % each each
   \begincsname\m_tabl_ntb_prefix\c!x\v!each\c!y\v!each\endcsname
   \begincsname\m_tabl_ntb_prefix\c!y\v!each\endcsname
   \begincsname\m_tabl_ntb_prefix\c!x\v!each\endcsname
   % odd even
   \begincsname\m_tabl_ntb_prefix\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
   \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\endcsname
   \begincsname\m_tabl_ntb_prefix\c!x\v!oddeven\m_tabl_ntb_positive_col\c!y\v!oddeven\m_tabl_ntb_positive_row\endcsname
   % row/col number combinations
   \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_positive_row\endcsname
   \begincsname\m_tabl_ntb_prefix\c!y\m_tabl_ntb_negative_row\endcsname
   \naturaltablelocalparameter\c!extras
   \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\endcsname
   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\endcsname
   \naturaltablelocalparameter\c!extras
   \letnaturaltablelocalparameter\c!extras\relax % new, see x-fo
   % first/last combinations
   \ifnum\m_tabl_ntb_positive_row=\plusone
     \begincsname\m_tabl_ntb_prefix\c!y\v!first\endcsname
     \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!first\endcsname
   \fi
   \ifnum\m_tabl_ntb_positive_col=\plusone
     \begincsname\m_tabl_ntb_prefix\c!x\v!first\endcsname
     \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\m_tabl_ntb_positive_row\endcsname
   \fi
   \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
     \begincsname\m_tabl_ntb_prefix\c!y\v!last\endcsname
     \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\v!last\endcsname
   \fi
   \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
     \begincsname\m_tabl_ntb_prefix\c!x\v!last\endcsname
     \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\m_tabl_ntb_positive_row\endcsname
   \fi
   \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
     \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!last\endcsname
   \fi\fi
   \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\plusone
     \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!first\endcsname
   \fi\fi
   \ifnum\m_tabl_ntb_positive_row=\plusone \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
     \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!first\endcsname
   \fi\fi
   \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
     \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!last\endcsname
   \fi\fi
   % special case: two rows and last row : two&first and two&last (round corners)
   \ifnum\c_tabl_ntb_maximum_row=\plustwo\relax
     \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\plusone
       \begincsname\m_tabl_ntb_prefix\c!x\v!first\c!y\v!two\endcsname
     \fi\fi
     \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax \ifnum\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax
       \begincsname\m_tabl_ntb_prefix\c!x\v!last\c!y\v!two\endcsname
     \fi\fi
   \fi
   \ifnum\tabl_ntb_get_col\m_tabl_ntb_positive_row\m_tabl_ntb_positive_col=\c_tabl_ntb_maximum_col\relax % top span over whole width
     \ifnum\m_tabl_ntb_positive_row=\plusone
       \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!first\endcsname
     \fi
     \ifnum\m_tabl_ntb_positive_row=\c_tabl_ntb_maximum_row\relax
       \begincsname\m_tabl_ntb_prefix\c!x\v!one\c!y\v!last\endcsname
     \fi
   \fi
   % header things
   \ifnum#1>\c_tabl_ntb_n_of_hdnx_lines\else
     \begincsname\m_tabl_ntb_prefix\v!header\v!each\endcsname
     \begincsname\m_tabl_ntb_prefix\v!header\m_tabl_ntb_positive_col\endcsname
   \fi
   % explicit cells
   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_positive_col\c!y\m_tabl_ntb_positive_row\endcsname
   \begincsname\m_tabl_ntb_prefix\c!x\m_tabl_ntb_negative_col\c!y\m_tabl_ntb_negative_row\endcsname
   % local
   \begincsname\m_tabl_ntb_prefix\c!y++\m_tabl_ntb_positive_row\endcsname
   % done
   \relax}

% we cannot use +n (checking on number/last/first would slow down too much)
%
% \setupTABLE[r]  [2][color=red]
% \setupTABLE[r] [-2][color=red]
% \setupTABLE[c]  [2][color=green]
% \setupTABLE[c] [-2][color=green]
% \setupTABLE[4]  [4][color=blue]
% \setupTABLE[-4][-4][color=blue]
%
% \bTABLE
% \dorecurse{10}{\bTR \dorecurse{6}{\bTD xxx \eTD} \eTR}
% \eTABLE

\lettonothing\m_tabl_ntb_before_split
\lettonothing\m_tabl_ntb_after_split
\lettonothing\m_tabl_ntb_same_page

% 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

% plugin

\let\tabl_ntb_section_mark   \relax
\let\tabl_ntb_section_checkup\relax
\let\tabl_ntb_section_split  \relax
\let\tabl_ntb_section_install\relax
\let\tabl_ntb_section_setup  \relax
\let\tabl_ntb_section_wrapup \relax

% till here

\tolerant\protected\def\tabl_ntb_tr[#S#1]%
  {\c_tabl_ntb_running_col\zerocount
   \c_tabl_ntb_encountered_col\zerocount
   %
   \tabl_ntb_section_mark
   %
   \advanceby\c_tabl_ntb_maximum_row\plusone
   \ifparameter#1\or
     \expandafter\tabl_ntb_tr_yes
   \else
     \expandafter\gobbleoneargument
   \fi{#1}}

\protected\def\tabl_ntb_tr_yes#1%
  {\defcsname\??naturaltableset\m_tabl_ntb_level:\c!y++\the\c_tabl_ntb_maximum_row\endcsname{\setupcurrentnaturaltablelocal[#1]}}

\def\m_tabl_ntb_default_nr{\naturaltableparameter\c!nr}
\def\m_tabl_ntb_default_nc{\naturaltableparameter\c!nc}

\tolerant\protected\def\tabl_ntb_td[#S#1]%
  {\advanceby\c_tabl_ntb_encountered_col\plusone
   \ifparameter#1\or
     \expandafter\tabl_ntb_td_yes
   \else
     \expandafter\tabl_ntb_td_nop
   \fi{#1}}

\lettonothing\m_tabl_ntb_m
\lettonothing\m_tabl_ntb_n

\protected\def\tabl_ntb_td_yes#1#2\eTD
  {\letnaturaltableparameter  \c!ny\m_tabl_ntb_default_nr
   \letnaturaltableparameter  \c!nx\m_tabl_ntb_default_nc
   \letnaturaltableparameter  \c!nc\plusone
   \letnaturaltableparameter  \c!nr\plusone
   \letnaturaltableparameter  \c!n \c_tabl_ntb_running_col_reference
   \resetnaturaltableparameter\c!m
   \resetnaturaltableparameter\c!action% not that important
   \setupcurrentnaturaltable[#1]%
   %
   \c_tabl_ntb_nx{\naturaltableparameter\c!nx}%
   \c_tabl_ntb_ny{\naturaltableparameter\c!ny}%
   % goto first cell n/m=cellnumber
   \edef\m_tabl_ntb_n{\naturaltableparameter\c!n}%
   \edef\m_tabl_ntb_m{\naturaltableparameter\c!m}%
   %
   \ifempty\m_tabl_ntb_n
     \global\advanceby\c_tabl_ntb_spn\c_tabl_ntb_nx\relax
   \orelse\ifnum\m_tabl_ntb_n=\c_tabl_ntb_running_col
   \else
     \tabl_ntb_td_pass_n{#1}%
   \fi
   \ifempty\m_tabl_ntb_m
   \orelse\ifnum\m_tabl_ntb_m=\c_tabl_ntb_running_col
   \else
     \tabl_ntb_td_pass_m{#1}%
   \fi
   \localcontrolledloop\plusone\maxcard\plusone % skip over columns that result from earlier span
     {\advanceby\c_tabl_ntb_running_col\plusone
      \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
        \quitloop
      \fi}%
   % fill r*c cells and set span
   \c_tabl_ntb_nx{\naturaltableparameter\c!nx}%
   \c_tabl_ntb_ny{\naturaltableparameter\c!ny}%
   \ifnum\c_tabl_ntb_nx=\plusone
     \ifnum\c_tabl_ntb_ny=\plusone
       \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
         \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
       \fi
     \else
       \tabl_ntb_cell_preset
     \fi
   \else
     \tabl_ntb_cell_preset
   \fi
   % set values
   \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
   \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_nx
   \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_ny
   % the action key will change!
   \tabl_ntb_set_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\naturaltableparameter\c!action}%
   % save text
   \expanded
     {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
     {#1}{#2}%
   \ifnum\c_tabl_ntb_encountered_col>\c_tabl_ntb_encountered_max
     \c_tabl_ntb_encountered_max\c_tabl_ntb_encountered_col
   \fi}

\protected\def\tabl_ntb_td_nop#1#2\eTD
  {\global\advanceby\c_tabl_ntb_spn\plusone\relax
   \localcontrolledloop\plusone\maxcard\plusone
     {\advanceby\c_tabl_ntb_running_col\plusone
      \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\endcsname \else
        \quitloop
      \fi}%
   \c_tabl_ntb_nx\plusone
   \c_tabl_ntb_ny\plusone
   \ifnum\c_tabl_ntb_running_col>\c_tabl_ntb_maximum_col\relax
     \c_tabl_ntb_maximum_col\c_tabl_ntb_running_col
   \fi
   \tabl_ntb_let_tag\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_cell
   \tabl_ntb_set_col\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_nx
   \tabl_ntb_set_row\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\c_tabl_ntb_ny
   \tabl_ntb_let_ref\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col\empty
   \expanded
     {\tabl_ntb_set_txt_process\c_tabl_ntb_maximum_row\c_tabl_ntb_running_col{\the\c_tabl_ntb_maximum_row}{\the\c_tabl_ntb_running_col}}%
     {#1}{#2}%
   \ifnum\c_tabl_ntb_encountered_col>\c_tabl_ntb_encountered_max
     \c_tabl_ntb_encountered_max\c_tabl_ntb_encountered_col
   \fi}

\protected\def\tabl_ntb_td_pass_n#1%
  {\scratchcounter{\m_tabl_ntb_n-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn}%
   \ifnum\scratchcounter>\zerocount
     \expanded{\tabl_ntb_td[\c!nx=\the\scratchcounter,\c!n=,\c!m=,*sq=\v!no]}\eTD
     % could be a faster inline
     % \advanceby\c_tabl_ntb_encountered_col\plusone
     % \expanded{\tabl_ntb_td_yes[\c!nx=\the\scratchcounter},\c!n=,\c!m=,*sq=\v!no]\eTD
   \fi
   \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
   \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
   \letnaturaltableparameter\c!nc\plusone
   \letnaturaltableparameter\c!nr\plusone
   \setupcurrentnaturaltable[#1]%
   \resetnaturaltableparameter\c!n
   \resetnaturaltableparameter\c!m}

\protected\def\tabl_ntb_td_pass_m#1%
  {\localcontrolledloop
     \plusone
     {\m_tabl_ntb_m-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn}%
     \plusone
     {\expanded{\tabl_ntb_td[\c!n=,\c!m=]}\eTD}%
   % can be sped up
   \letnaturaltableparameter\c!ny\m_tabl_ntb_default_nr
   \letnaturaltableparameter\c!nx\m_tabl_ntb_default_nc
   \letnaturaltableparameter\c!nc\plusone
   \letnaturaltableparameter\c!nr\plusone
   \setupcurrentnaturaltable[#1]%
   \resetnaturaltableparameter\c!n
   \resetnaturaltableparameter\c!m}

\def\tabl_ntb_cell_preset
  {\c_tabl_ntb_current_row\c_tabl_ntb_maximum_row
   \c_tabl_ntb_current_col\c_tabl_ntb_running_col
   \localcontrolledloop\plusone\c_tabl_ntb_ny\plusone{\tabl_ntb_cell_preset_rows}%
   % check max column
   \advanceby\c_tabl_ntb_current_col\minusone
   \ifnum\c_tabl_ntb_current_col>\c_tabl_ntb_maximum_col\relax
     \c_tabl_ntb_maximum_col\c_tabl_ntb_current_col
   \fi}

\def\tabl_ntb_cell_preset_rows
  {\c_tabl_ntb_current_col\c_tabl_ntb_running_col
   \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_nx
   \ifnum\c_tabl_ntb_nx>\c_tabl_ntb_maximum_row_span\relax
     \c_tabl_ntb_maximum_row_span\c_tabl_ntb_nx
   \fi
   \localcontrolledloop\plusone\c_tabl_ntb_nx\plusone{\tabl_ntb_cell_preset_cells}%
   \advanceby\c_tabl_ntb_current_row\plusone}

\def\tabl_ntb_cell_preset_cells
  {\tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
   \advanceby\c_tabl_ntb_current_col\plusone}

%D The usage of n and m:
%D
%D \startbuffer
%D \bTABLE[width=3em]
%D \bTR\bTD d1 \eTD\bTD[n=2] d2 \eTD\bTD[n=5] d5 \eTD\bTD[n=7] d7 \eTD\eTR
%D \bTR\bTD f1 \eTD\bTD[n=4] f4 \eTD\bTD[n=5] f5 \eTD\bTD[n=7] f7 \eTD\eTR
%D \eTABLE
%D \stopbuffer
%D
%D \typebuffer \getbuffer
%D
%D \startbuffer
%D \bTABLE[width=3em]
%D \bTR\bTD d1 \eTD\bTD[m=2] d2 \eTD\bTD[m=5] d5 \eTD\bTD[m=7] d7 \eTD\eTR
%D \bTR\bTD f1 \eTD\bTD[m=4] f4 \eTD\bTD[m=5] f5 \eTD\bTD[m=7] f7 \eTD\eTR
%D \eTABLE
%D \stopbuffer
%D
%D \typebuffer \getbuffer
%D
%D \startbuffer
%D \bTABLE[frame=on]
%D \bTR \bTH[nc=3] One \eTH \bTH[m=4] Four \eTH\eTR
%D \bTR \bTD a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
%D \eTABLE
%D
%D \bTABLE[frame=on]
%D \bTR \bTH[nr=2] One \eTH \bTH[m=3] Three \eTH\eTR
%D \bTR \bTD[m=3] a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
%D \bTR \bTD[m=3] a \eTD\bTD b \eTD\bTD c \eTD\bTD d \eTD\eTR
%D \eTABLE
%D \stopbuffer
%D
%D \typebuffer \getbuffer

% could be a faster inline: advance and _yes

\tolerant\def\tabl_ntb_th[#S#1]#:#2\eTH
  {\tabl_ntb_td[#1,\c!color=\naturaltablelocalparameter\c!headcolor,\c!style=\naturaltablelocalparameter\c!headstyle,\c!aligncharacter=\v!no]#2\eTD}

\tolerant\def\tabl_ntb_tn[#S#1]#:#2\eTN
  {\tabl_ntb_td[#1]\digits#2\relax\eTD}

%D Vit Zyka needed the option to create a distance between columns, so I added
%D support for individual column distances.
%D
%D \startbuffer
%D % \setupTABLE[c][each][distance=2em]
%D \setupTABLE[c][1][distance=2em]
%D \setupTABLE[c][2][distance=3em]
%D
%D \bTABLE
%D \bTR \bTD test \eTD  \bTD test \eTD  \bTD test \eTD \eTR
%D \bTR \bTD[nx=2] test \eTD  \bTD test \eTD \eTR
%D \bTR \bTD test \eTD  \bTD[nx=2] test \eTD \eTR
%D \eTABLE
%D
%D \bTABLE[option=stretch]
%D \bTR \bTD test \eTD  \bTD test \eTD  \bTD test \eTD \eTR
%D \bTR \bTD[nx=2] test \eTD  \bTD test \eTD \eTR
%D \bTR \bTD test \eTD  \bTD[nx=2] test \eTD \eTR
%D \eTABLE
%D \stopbuffer
%D
%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection
%D
%D and he provided patches for the global left and right margin distances as well as
%D the columndistance (although i changed the names -). Here is his testcase:
%D
%D \startbuffer
%D \framed[offset=overlay]\bgroup
%D     \setupTABLE[column][2][align=left]%
%D     \setupTABLE[column][3][align=right]%
%D     \bTABLE[columndistance=2cm,leftmargindistance=.3cm,rightmargindistance=.5cm]
%D         \bTR \bTH[nc=3] Table head\eTH \eTR
%D         \bTR \bTD[nc=2] AB\eTD \bTD C\eTD \eTR
%D         \bTR \bTD[nc=2,align=left] AB\eTD \bTD C\eTD \eTR
%D         \bTR \bTD[nc=2,align=middle] AB\eTD \bTD C\eTD \eTR
%D         \bTR \bTD A\eTD \bTD B\eTD \bTD C\eTD \eTR
%D         \bTR \bTD Aa\eTD \bTD Bb\eTD \bTD Cccc\eTD \eTR
%D         \bTR \bTD[nc=3,align=middle] ABC\eTD \eTR
%D     \eTABLE
%D \egroup
%D \stopbuffer
%D
%D \typebuffer \startlinecorrection \getbuffer \stoplinecorrection

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

\permanent\protected\lettonothing\eTABLEhead
\permanent\protected\lettonothing\eTABLEnext
\permanent\protected\lettonothing\eTABLEbody
\permanent\protected\lettonothing\eTABLEfoot

\permanent\tolerant\protected\def\bTABLEhead[#1]#:#2\eTABLEhead{\toksapp\t_tabl_ntb_head{\tabl_ntb_section[#1]{#2}}}
\permanent\tolerant\protected\def\bTABLEnext[#1]#:#2\eTABLEnext{\toksapp\t_tabl_ntb_next{\tabl_ntb_section[#1]{#2}}}
\permanent\tolerant\protected\def\bTABLEbody[#1]#:#2\eTABLEbody{\toksapp\t_tabl_ntb_body{\tabl_ntb_section[#1]{#2}}}
\permanent\tolerant\protected\def\bTABLEfoot[#1]#:#2\eTABLEfoot{\toksapp\t_tabl_ntb_foot{\tabl_ntb_section[#1]{#2}}}

\def\tabl_ntb_section[#1]#2% also used in tabl-nte
  {\protected\def\tabl_ntb_setup_section{\setupcurrentnaturaltablelocal[#1]}%
   #2%
   \let\tabl_ntb_setup_section\relax}

\def\tabl_ntb_preset_parameters% each odd|even level / can be sped up but only once per table
  {\begincsname\??naturaltableset\m_tabl_ntb_level:\v!start\v!each\endcsname
   \begincsname\??naturaltableset\m_tabl_ntb_level:\v!start\v!oddeven\m_tabl_ntb_level\endcsname
   \begincsname\??naturaltableset\m_tabl_ntb_level:\v!start\m_tabl_ntb_level\endcsname}

\permanent\tolerant\protected\def\bTABLE[#S#1]%
  {\tabl_ntb_table_push
   % box not here
   \bgroup
   \pushpostponednodedata
   \t_tabl_ntb_head\emptytoks
   \t_tabl_ntb_next\emptytoks
   \t_tabl_ntb_body\emptytoks
   \t_tabl_ntb_foot\emptytoks
   \ifhmode\kern\zeropoint\fi  % blocks \removeunwantedspaces: check this on icare handelingsschema
   \resetcharacteralign % new
   \setupcurrentnaturaltablelocal[\c!align={\v!right,\v!broad,\v!high},#1]%
   %
   \tabl_ntb_anchor_setup
   \tabl_ntb_section_setup
   %
   \d_tabl_ntb_leftmargindistance {\naturaltablelocalparameter\c!leftmargindistance}%
   \d_tabl_ntb_rightmargindistance{\naturaltablelocalparameter\c!rightmargindistance}%
   \d_tabl_ntb_columndistance     {\naturaltablelocalparameter\c!columndistance}%
   \d_tabl_ntb_maxwidth           {\naturaltablelocalparameter\c!maxwidth}%
   %
   \usesetupsparameter\naturaltablelocalparameter
   \hsize
     \ifcstok{\naturaltablelocalparameter\c!textwidth}\v!local
       \availablehsize
     \else
       {\naturaltablelocalparameter\c!textwidth}%
     \fi
   \relax
   \enableTBLbreakfalse
   \multipleTBLheadsfalse
   \forceTBLpageflowfalse
   \autoTBLspreadfalse
   \tightTBLcolspanfalse
   \processaction
     [\naturaltablelocalparameter\c!split]%
     [     \v!yes=>\enableTBLbreaktrue,
        \v!repeat=>\enableTBLbreaktrue\multipleTBLheadstrue,
          \v!page=>\enableTBLbreaktrue\forceTBLpageflowtrue,
          \v!auto=>\ifinsidesplitfloat\enableTBLbreaktrue\fi]%
   \processaction
     [\naturaltablelocalparameter\c!header]%
     [\v!repeat=>\multipleTBLheadstrue]%
   \tabl_ntb_preset_parameters
   \processallactionsinset
     [\naturaltablelocalparameter\c!option]
     [\v!stretch=>\autoTBLspreadtrue,%
        \v!tight=>\tightTBLcolspantrue]%
   \linewidth{\naturaltablelocalparameter\c!rulethickness}% needs to be frozen
   \dontcomplain
   \c_tabl_ntb_running_col     \zerocount
   \c_tabl_ntb_maximum_col     \zerocount
   \c_tabl_ntb_maximum_row     \zerocount
   \c_tabl_ntb_maximum_row_span\plusone
   \let\currentTABLErow   \tabl_ntb_current_row
   \let\currentTABLEcolumn\tabl_ntb_current_column
   \let\nofTABLErows      \tabl_ntb_n_of_rows
   \let\nofTABLEcolumns   \tabl_ntb_n_of_columns
   %
   \enforced\let\bTR\tabl_ntb_bTR
   \enforced\let\bTD\tabl_ntb_bTD
   \enforced\let\bTH\tabl_ntb_bTH
   \enforced\let\bTN\tabl_ntb_bTN}

\def\tabl_ntb_current_row   {\m_tabl_ntb_positive_row}
\def\tabl_ntb_current_column{\m_tabl_ntb_positive_col}
\def\tabl_ntb_n_of_rows     {\the\c_tabl_ntb_maximum_row}
\def\tabl_ntb_n_of_columns  {\the\c_tabl_ntb_maximum_col}

\mutable\let\currentTABLErow   \!!zerocount
\mutable\let\currentTABLEcolumn\!!zerocount
\mutable\let\nofTABLErows      \!!zerocount
\mutable\let\nofTABLEcolumns   \!!zerocount

% there is no gain in a \doifelsenextoptionalcs variant

% todo with tolerant:

\permanent\tolerant\protected\def\tabl_ntb_bTR{\tabl_ntb_tr} % also used in tabl-nte
\permanent\tolerant\protected\def\tabl_ntb_bTD{\tabl_ntb_td} % also used in tabl-nte
\permanent\tolerant\protected\def\tabl_ntb_bTH{\tabl_ntb_th} % also used in tabl-nte
\permanent\tolerant\protected\def\tabl_ntb_bTN{\tabl_ntb_tn} % also used in tabl-nte

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

\permanent\let\bTR\relax \permanent\protected\def\eTR{\ignorespaces} % handy in case we use a macro to generate rows
\permanent\let\bTD\relax \permanent\protected\def\eTD{\ignorespaces}
\permanent\let\bTH\relax \permanent\protected\def\eTH{\ignorespaces}
\permanent\let\bTN\relax \permanent\protected\def\eTN{\ignorespaces}

\newconditional\c_tabl_ntb_reverse % we might need this info more often

\permanent\protected\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode
  {% tricky and dirty order -)
   \c_tabl_ntb_okay\conditionalfalse
   % head
   \c_tabl_ntb_reverse
     \ifcstok{\naturaltablelocalparameter\c!direction}\v!reverse
       \conditionaltrue
     \else
       \conditionalfalse
     \fi
   \ifempty\t_tabl_ntb_head
     \c_tabl_ntb_head\zerocount
     \c_tabl_ntb_n_of_head_lines\zerocount % was 1
     \c_tabl_ntb_n_of_next_lines\zerocount
     \c_tabl_ntb_n_of_hdnx_lines\zerocount
   \else
     \c_tabl_ntb_head{\c_tabl_ntb_maximum_row+\plusone}%
     \expand\t_tabl_ntb_head
     \c_tabl_ntb_n_of_head_lines\c_tabl_ntb_maximum_row\relax
     \ifempty\t_tabl_ntb_next
       \c_tabl_ntb_n_of_next_lines\zerocount % was 1
     \else
       \expand\t_tabl_ntb_next
       \c_tabl_ntb_n_of_next_lines{\c_tabl_ntb_maximum_row-\c_tabl_ntb_n_of_head_lines}%
     \fi
     \c_tabl_ntb_n_of_hdnx_lines\c_tabl_ntb_maximum_row
   \fi
   % body
   \c_tabl_ntb_body{\c_tabl_ntb_maximum_row+\plusone}%
   \expand\t_tabl_ntb_body
   % foot
   \ifempty\t_tabl_ntb_foot
     \c_tabl_ntb_foot\zerocount
   \else
     \c_tabl_ntb_foot{\c_tabl_ntb_maximum_row+\plusone}%
     \expand\t_tabl_ntb_foot
   \fi
   % done
   \removeunwantedspaces % only if hmode
   % finish cells
   \tabl_ntb_loop_one
   % to be sure
   \tabl_ntb_loop_two
   % check and do
   \ifcase\c_tabl_ntb_maximum_col\else
     \startTBLprocessing
       \tabl_ntb_table_start
         \localcontrolledloop\plusone\c_tabl_ntb_maximum_row\plusone
           {\tabl_ntb_row_start
              \c_tabl_ntb_current_row\currentloopiterator\relax
              \ifconditional\c_tabl_ntb_reverse
                \localcontrolledloop\c_tabl_ntb_maximum_col\plusone\minusone
              \else
                \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
              \fi
                {\c_tabl_ntb_current_col\currentloopiterator\relax
                 \expanded{\tabl_ntb_cell{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}}%
            \tabl_ntb_row_stop}%
         \removeunwantedspaces % only if hmode
       \tabl_ntb_table_stop
     \stopTBLprocessing
     % wrong ! ! ! better to have an auto-offset-overlay
     % \ifnum\m_tabl_ntb_level>1
     %   \vskip-\strutdp
     % \fi
   \fi
   \tabl_ntb_section_wrapup
   % tracing
   % \iftrue
   %   \blank \tttf
   %   \localcontrolledloop\plusone\c_tabl_ntb_maximum_row\plusone
   %     {\c_tabl_ntb_current_row\currentloopiterator\relax
   %      \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
   %        {\c_tabl_ntb_current_col\currentloopiterator\relax
   %         [r=\the\c_tabl_ntb_current_row,c=\the\c_tabl_ntb_current_col,h=\the\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col,w=\the\dimexpr\tabl_ntb_get_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col]}%
   %      \par}%
   %   \blank
   % \fi
   \poppostponednodedata
   \egroup
   \tabl_ntb_table_pop}

\def\tabl_ntb_loop_one
  {\localcontrolledloop\plusone\c_tabl_ntb_maximum_row\plusone{\tabl_ntb_loop_one_rows}}

\def\tabl_ntb_loop_one_rows
  {\c_tabl_ntb_current_row\currentloopiterator\relax
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone{\tabl_ntb_loop_one_cells}}

\def\tabl_ntb_loop_one_cells
  {\c_tabl_ntb_current_col\currentloopiterator\relax
   \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
     \tabl_ntb_loop_one_cells_indeed
   \fi}

\def\tabl_ntb_loop_one_cells_indeed
  {\c_tabl_ntb_current_col_two\c_tabl_ntb_current_col
   \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row
   \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
   \localcontrolledloop\plusone\maxcard\plusone
     {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
      \localcontrolledloop\plusone\maxcard\plusone
        {\ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
           \quitloop
         \else
           \advanceby\c_tabl_ntb_current_col_one\plusone
           \ifnum\c_tabl_ntb_current_col_one>\c_tabl_ntb_maximum_col\relax
             \quitloop
           \fi
         \fi}%
      \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\endcsname
        \quitloop
      \else
        \c_tabl_ntb_current_row_two\c_tabl_ntb_current_row_one
        \c_tabl_ntb_current_col_two\c_tabl_ntb_current_col_one
        \advanceby\c_tabl_ntb_current_row_one\plusone
        \ifnum\c_tabl_ntb_current_row_one>\c_tabl_ntb_maximum_row
          \quitloop
        \fi
      \fi}%
   \ifnum\c_tabl_ntb_current_row_two>\c_tabl_ntb_maximum_row\c_tabl_ntb_current_row_two\c_tabl_ntb_maximum_row\fi
   \ifnum\c_tabl_ntb_current_col_two>\c_tabl_ntb_maximum_col\c_tabl_ntb_current_col_two\c_tabl_ntb_maximum_col\fi
   \c_tabl_ntb_current_row_two{\c_tabl_ntb_current_row_two-\c_tabl_ntb_current_row+\plusone}%
   \c_tabl_ntb_current_col_two{\c_tabl_ntb_current_col_two-\c_tabl_ntb_current_col+\plusone}%
   \c_tabl_ntb_current_row_one\c_tabl_ntb_current_row
   \localcontrolledloop\plusone\c_tabl_ntb_current_row_two\plusone
     {\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col
      \tabl_ntb_set_col\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\c_tabl_ntb_current_col_two
      \localcontrolledloop\plusone\c_tabl_ntb_current_col_two\plusone
        {\tabl_ntb_let_tag\c_tabl_ntb_current_row_one\c_tabl_ntb_current_col_one\c_tabl_ntb_none
         \advanceby\c_tabl_ntb_current_col_one\plusone}%
      \advanceby\c_tabl_ntb_current_row_one\plusone}%
   \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_cell
   \tabl_ntb_set_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_current_col_two
   \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_current_row_two%
   \ifautoTBLemptycell
      \expanded
         {\tabl_ntb_set_txt_process\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\c_tabl_ntb_current_row}{\the\c_tabl_ntb_current_col}}%
         {\c!option=\v!tight}{\strut\kern\scaledpoint}% the kern forces the tight
   \fi}

\def\tabl_ntb_loop_two
  {\localcontrolledloop\plusone\c_tabl_ntb_maximum_row\plusone{\tabl_ntb_loop_two_rows}}

\def\tabl_ntb_loop_two_rows
  {\c_tabl_ntb_current_row\currentloopiterator\relax
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone{\tabl_ntb_loop_two_cells}}

\def\tabl_ntb_loop_two_cells
  {\c_tabl_ntb_current_col\currentloopiterator\relax
   \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname
     \scratchcounter{\c_tabl_ntb_maximum_row-\c_tabl_ntb_current_row+\plusone}%
     \ifnum\tabl_ntb_get_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col>\scratchcounter
%        \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col{\the\scratchcounter}%
       \tabl_ntb_set_row\c_tabl_ntb_current_row\c_tabl_ntb_current_col\scratchcounter
     \fi
   \fi
   \tabl_ntb_let_ht\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
   %tabl_ntb_let_wd\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zeropoint
   \ifcsname\tabl_ntb_col_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
     \tabl_ntb_let_col\c_tabl_ntb_current_row\c_tabl_ntb_current_col\zerocount
   \fi
   \ifcsname\tabl_ntb_tag_pattern\c_tabl_ntb_current_row\c_tabl_ntb_current_col\endcsname \else
     \tabl_ntb_let_tag\c_tabl_ntb_current_row\c_tabl_ntb_current_col\c_tabl_ntb_none
   \fi}

\mutable\let\startTBLprocessing\relax % public
\mutable\let\stopTBLprocessing \relax % public

\newinteger\c_tabl_prelocated_rows % \prelocateTBLrows{1000} may speed up large tables

% \def\tabl_ntb_row_start{\t_tabl_ntb_row\emptytoks}
% \def\tabl_ntb_row_stop {\expanded{\t_tabl_ntb{\expand\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\expand\t_tabl_ntb_row\tabl_ntb_row_align_stop}}}

\def\tabl_ntb_row_start
  {\t_tabl_ntb_row\emptytoks}

\def\tabl_ntb_row_stop
  {\ifenableTBLbreak
     \tabl_ntb_row_stop_split
   \else
     \tabl_ntb_row_stop_boxed
   \fi}

\def\tabl_ntb_row_stop_boxed
  {% \noindent % no, else double leftskip in narrower
   \etoksapp\t_tabl_ntb
     {% no need for init
      \tabl_ntb_row_align_start
      \the\t_tabl_ntb_row
      \tabl_ntb_row_align_stop}}

\def\tabl_ntb_row_stop_split
  {\ifcsname\??naturaltableset\m_tabl_ntb_level:\c!y++\the\c_tabl_ntb_current_row\endcsname
     \tabl_ntb_row_stop_split_yes
   \else
     \tabl_ntb_row_stop_split_nop
   \fi}

\def\tabl_ntb_row_stop_split_nop
  {\etoksapp\t_tabl_ntb
     {\tabl_ntb_row_align_reset
      \tabl_ntb_row_align_start
      \the\t_tabl_ntb_row
      \tabl_ntb_row_align_stop}}

\def\tabl_ntb_row_stop_split_yes
  {\begingroup
   \csname\??naturaltableset\m_tabl_ntb_level:\c!y++\the\c_tabl_ntb_current_row\endcsname
   \xdef\m_tabl_ntb_before_split{\naturaltablelocalparameter\c!before}% to be checked
   \xdef\m_tabl_ntb_after_split {\naturaltablelocalparameter\c!after}% to be checked
   \xdef\m_tabl_ntb_same_page   {\naturaltablelocalparameter\c!samepage}%
   \endgroup
   \etoksapp\t_tabl_ntb
     {\tabl_ntb_row_align_set{\m_tabl_ntb_before_split}{\m_tabl_ntb_after_split}{\m_tabl_ntb_same_page}%
      \tabl_ntb_row_align_start
      \the\t_tabl_ntb_row
      \tabl_ntb_row_align_stop}}

\protected\def\tabl_ntb_row_align_set#1#2#3%
  {\xdef\m_tabl_ntb_before_split{#1}%
   \xdef\m_tabl_ntb_after_split {#2}%
   \xdef\m_tabl_ntb_same_page   {#3}}

\protected\def\tabl_ntb_row_align_reset
  {\glettonothing\m_tabl_ntb_before_split
   \glettonothing\m_tabl_ntb_after_split
   \glettonothing\m_tabl_ntb_same_page   }

\def\tabl_ntb_prelocate_error
  {\writestatus\m!TABLE{fatal error: use \string\prelocateTBLrows\space to increase table memory (now: \the\c_tabl_prelocated_rows)}}

% \prelocateTBLrows{1000} % may speed up large tables

\permanent\protected\def\prelocateTBLrows#1% we start at zero so we have one to much, better play safe anyway
  {\localcontrolledloop\c_tabl_prelocated_rows#1\plusone
     {\expandafter\newtoks\csname\??naturaltabletok\the\currentloopiterator\endcsname}%
   \def\tabl_ntb_row_start
     {\ifnum\c_tabl_ntb_row<\c_tabl_prelocated_rows\relax
        \tabl_ntb_prelocate_okay
      \else
        \tabl_ntb_prelocate_error
      \fi}%
   \def\tabl_ntb_row_stop
     {\etoksapp\t_tabl_ntb
        {\tabl_ntb_row_align_start
         \the\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname
         \tabl_ntb_row_align_stop}}%
   \global\c_tabl_prelocated_rows#1\relax}

\def\tabl_ntb_prelocate_okay
  {\expandafter\let\expandafter\t_tabl_ntb_row\csname\??naturaltabletok\the\c_tabl_ntb_row\endcsname\t_tabl_ntb_row\emptytoks}

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

\let\m_tabl_ntb_saved_row\!!zerocount
\let\m_tabl_ntb_saved_col\!!zerocount

\def\tabl_ntb_start_tagged
  {\scratchcounter{\c_tabl_ntb_row+\plusone}%
   \ifnum\scratchcounter=\c_tabl_ntb_head
     \ifconditional\c_tabl_ntb_okay
       \dostoptagged
     \else
       \c_tabl_ntb_okay\conditionaltrue
     \fi
     \dostarttaggednodetail\t!tablehead
   \orelse\ifnum\scratchcounter=\c_tabl_ntb_body
     \ifconditional\c_tabl_ntb_okay
       \dostoptagged
     \else
       \c_tabl_ntb_okay\conditionaltrue
     \fi
     \dostarttaggednodetail\t!tablebody
   \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot
     \ifconditional\c_tabl_ntb_okay
       \dostoptagged
     \else
       \c_tabl_ntb_okay\conditionaltrue
     \fi
     \dostarttaggednodetail\t!tablefoot
   \fi
   \dostarttaggednodetail\t!tablerow}

\def\tabl_ntb_stop_tagged
  {\dostoptagged
   \ifconditional\c_tabl_ntb_okay
     \scratchcounter{\c_tabl_ntb_row+\plustwo}%
     \ifnum\scratchcounter=\c_tabl_ntb_body
       \dostoptagged
       \c_tabl_ntb_okay\conditionalfalse
     \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot
       \dostoptagged
       \c_tabl_ntb_okay\conditionalfalse
     \orelse\ifnum\scratchcounter>\c_tabl_ntb_maximum_row
       \dostoptagged
       \c_tabl_ntb_okay\conditionalfalse
     \fi
   \fi}

\protected\def\tabl_ntb_row_align_start
  {\global\advanceby\c_tabl_ntb_row\plusone
   \global\c_tabl_ntb_col\plusone
   \global\c_tabl_ntb_spn\zerocount
   \tabl_ntb_row_align_start_inject
   \ifconditional\c_strc_tags_enabled
     \tabl_ntb_start_tagged
   \fi
   \tabl_ntb_section_checkup
   \hbox\bgroup
   \kern\d_tabl_ntb_leftmargindistance}

\protected\def\tabl_ntb_row_align_stop
  {\kern{\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance}%
   \egroup
   \ifconditional\c_strc_tags_enabled
     \tabl_ntb_stop_tagged
   \fi
   \tabl_ntb_row_align_stop_inject}

\protected\def\tabl_ntb_before_page
  {\ifx\m_tabl_ntb_same_page\v!before
   % \blank[\v!samepage,\v!strong]%
     \nobreak
   \orelse\ifx\m_tabl_ntb_same_page\v!both
   % \blank[\v!samepage,\v!strong]%
     \nobreak
   \fi}

\protected\def\tabl_ntb_after_page
  {\ifnum\c_tabl_ntb_row>\c_tabl_ntb_n_of_head_lines
     \ifnum\tabl_ntb_get_nob\c_tabl_ntb_row=\zerocount % no \ifzero
       \ifx\m_tabl_ntb_same_page\v!after
       % \blank[\v!samepage,\v!strong]%
         \nobreak
       \orelse\ifx\m_tabl_ntb_same_page\v!both
       % \blank[\v!samepage,\v!strong]%
         \nobreak
       \else
       % \blank[\v!preference,\v!weak]%
         \allowbreak
       \fi
     \fi
   \else
   % \blank[\v!preference,\v!weak]%
     \allowbreak % else no proper head split off
   \fi}

\protected\def\tabl_ntb_inbetween
  {\scratchcounter{\c_tabl_ntb_row+\plusone}%
   \ifnum\scratchcounter>\c_tabl_ntb_n_of_hdnx_lines\relax
     \ifnum\scratchcounter<\c_tabl_ntb_maximum_row\relax
       \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}%
       \ifempty\p_spaceinbetween\else
         \blank[\p_spaceinbetween]%
       \fi
     \fi
   \fi}

\protected\def\tabl_ntb_row_align_start_inject
  {\bgroup % protect local vars
     \m_tabl_ntb_before_split
   \egroup
   \ifenableTBLbreak
     \tabl_ntb_before_page
   \fi}

\protected\def\tabl_ntb_row_align_stop_inject
  {\par
   \nointerlineskip
   \ifenableTBLbreak
     \tabl_ntb_after_page
   \fi
   \bgroup % protect local vars
     \m_tabl_ntb_after_split
   \egroup
   \bgroup % protect local vars
     \tabl_ntb_inbetween
   \egroup}

\def\tabl_ntb_flush_content
  {\expand\everyTABLEpass
   \global\c_tabl_ntb_spn\zerocount
   \global\c_tabl_ntb_col\zerocount
   \global\c_tabl_ntb_row\zerocount
   \global\advanceby\c_tabl_ntb_row\minusone
   \dostarttaggedchained\t!table\empty\empty\??naturaltable
  %\registerparoptions % (*) triggers max hsize
   \expand\t_tabl_ntb
   \dostoptagged}

\protected\def\tabl_ntb_span#1%
  {\hkern\tabl_ntb_get_dis\c_tabl_ntb_col
   \localcontrolledloop\plusone#1\plusone
     {\hkern\tabl_ntb_get_wid\c_tabl_ntb_col\relax
      \global\advanceby\c_tabl_ntb_col\plusone}}

\protected\def\tabl_ntb_skip#1%
  {\global\advanceby\c_tabl_ntb_col#1\relax}

\protected\def\tabl_ntb_plus
  {\global\advanceby\c_tabl_ntb_col\plusone
   \kern\d_tabl_ntb_columndistance}

\defcsname\??naturaltablecell\the\c_tabl_ntb_none\endcsname#1#2%
  {\scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
   \ifnum\scratchcounter>\zerocount
     \etoksapp\t_tabl_ntb_row
       {\tabl_ntb_span{\the\scratchcounter}}%
   \fi}

\defcsname\??naturaltablecell\the\c_tabl_ntb_cell\endcsname#1#2%
  {\toksapp\t_tabl_ntb_row{\tabl_ntb_pass #1 #2 }% space delimited -> less tokens
   \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
   \ifnum\scratchcounter>\zerocount
     \etoksapp\t_tabl_ntb_row
        {\ifnum\scratchcounter=\plusone
           \tabl_ntb_plus
         \else
           \tabl_ntb_skip{\the\scratchcounter}%
         \fi}%
   \fi}

\protected\def\tabl_ntb_cell#1#2%
  {\csname\??naturaltablecell\the\tabl_ntb_get_tag{#1}{#2}\endcsname{#1}{#2}}

\protected\def\tabl_ntb_table_start
  {\global\c_tabl_ntb_spn\zerocount
   \global\c_tabl_ntb_row\zerocount
   \global\c_tabl_ntb_col\zerocount
   \c_tabl_tbl_pass\zerocount
   \t_tabl_ntb\emptytoks}

\def\tabl_ntb_pass_one#1 #2 %
  {\tabl_ntb_get_txt{#1}{#2}}%

\def\tabl_ntb_pass_two#1 #2 % meer in cellD
  {\d_tabl_ntb_width\zeropoint
   \scratchcounter\c_tabl_ntb_col
   \scratchcounterone\tabl_ntb_get_col{#1}{#2}\relax
   \ifcase\scratchcounterone\or
     \advanceby\d_tabl_ntb_width{%
        \tabl_ntb_get_wid\scratchcounter % no real need for expression
     }%
     \advanceby\scratchcounter\plusone
   \else
     \localcontrolledloop\plusone\scratchcounterone\plusone
       {\advanceby\d_tabl_ntb_width{%
          \tabl_ntb_get_wid\scratchcounter
          \ifnum\currentloopiterator<\scratchcounterone
            +\d_tabl_ntb_columndistance
            +\tabl_ntb_get_dis\scratchcounter
          \fi
        }%
        \advanceby\scratchcounter\plusone}%
   \fi
   \setbox\scratchbox\hbox{\tabl_ntb_get_txt{#1}{#2}}%
   \tabl_ntb_set_ht{#1}{#2}\ht\scratchbox
   %tabl_ntb_set_wd{#1}{#2}\wd\scratchbox
   \ifdim\ht\scratchbox>\tabl_ntb_get_hei{#1}\relax
     \tabl_ntb_set_hei{#1}\ht\scratchbox
   \fi}

\def\tabl_ntb_pass_three#1 #2 %
  {% height
   \dostarttaggednodetail\t!tablecell
   \scratchcounterone\tabl_ntb_get_col{#1}{#2}\relax
   \scratchcountertwo\tabl_ntb_get_row{#1}{#2}\relax
   \scratchheight\tabl_ntb_get_ht {#1}{#2}\relax
   \tablecellcolumns\scratchcounterone % used later so don't adapt these
   \tablecellrows   \scratchcountertwo % used later so don't adapt these
   \d_tabl_ntb_height\zeropoint
   \ifnum\scratchcounterone=\c_tabl_ntb_maximum_col\relax
     % case: nc=maxcolumns
   \else
     \scratchcounter#1\relax
     \localcontrolledloop\plusone\scratchcountertwo\plusone
       {\advanceby\d_tabl_ntb_height\tabl_ntb_get_hei\scratchcounter
        \advanceby\scratchcounter\plusone}%
     \ifdim\d_tabl_ntb_height<\scratchheight\relax
       \d_tabl_ntb_height\scratchheight
     \fi
   \fi
   % width
   \d_tabl_ntb_width\zeropoint
   \scratchcounter\c_tabl_ntb_col
   \ifcase\scratchcounterone\or
     \advanceby\d_tabl_ntb_width{%
       \tabl_ntb_get_wid\scratchcounter %no real need for expression
     }%
     \advanceby\scratchcounter\plusone
   \else
     \localcontrolledloop\plusone\scratchcounterone\plusone
       {\advanceby\d_tabl_ntb_width{%
          \tabl_ntb_get_wid\scratchcounter
          \ifnum\currentloopiterator<\scratchcounterone
            +\d_tabl_ntb_columndistance
            +\tabl_ntb_get_dis\scratchcounter
          \fi
        }%
        \advanceby\scratchcounter\plusone}%
   \fi
   % cell
   \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged \bgroup
      \dotagTABLEsignal % maybe we need to add some packaging in this case
      \tabl_ntb_get_txt{#1}{#2}%
   \egroup
   \ifnum\scratchcounterone=\c_tabl_ntb_maximum_col\relax
     % case: nc=maxcolumns
   \else
     \scratchdimen\tabl_ntb_get_hei{#1}%
     \setbox\scratchbox\hpack
       {\lower\ht\scratchbox\hpack{\raise\scratchdimen\box\scratchbox}}%
     \ht\scratchbox\scratchdimen
   \fi
   \dp\scratchbox\zeropoint
   \edef\scratchmacro{\tabl_ntb_get_ref{#1}{#2}}%
   \ifempty\scratchmacro
     \box\scratchbox
   \else
     \expanded{\directgotobox{\box\scratchbox}[\scratchmacro]}% to be checked
   \fi
   \dostoptagged} % right spot

\def\tabl_ntb_cell_finalize
  {\ifx\localwidth\v!fit
      % nothing
   \orelse\ifx\localwidth\v!broad
      % nothing
   \orelse\ifempty\localwidth
      % nothing (safeguard)
   \else
     \tabl_ntb_cell_finalize_indeed
   \fi}

\def\tabl_ntb_cell_finalize_indeed
  {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
   \ifdim\localwidth>\scratchdimen
     \tabl_ntb_set_aut\c_tabl_ntb_col\localwidth\relax
   \fi}

\let\tabl_ntb_preroll\relax

\def\tabl_ntb_table_get_max_width
  {\scratchdimen\wd\scratchbox\relax}

% enabled per 2018-02-22

% \def\tabl_ntb_table_get_max_width_step
%   {\advanceby\scratchdimen\tabl_ntb_get_wid\fastloopindex
%    \advanceby\scratchdimen\tabl_ntb_get_dis\fastloopindex}
%
% \def\tabl_ntb_table_get_max_width
%   {\scratchdimen\zeropoint
%    \dofastloopcs\c_tabl_ntb_maximum_col\tabl_ntb_table_get_max_width_step
%    \ifdim\scratchdimen<\wd\scratchbox\relax
%      \scratchdimen\wd\scratchbox\relax
%    \fi}

\def\tabl_ntb_table_get_max_width
  {\scratchdimen\zeropoint
   \localcontrolledloop\zerocount\c_tabl_ntb_maximum_col\plusone
     {\advanceby\scratchdimen\tabl_ntb_get_wid\currentloopiterator
      \advanceby\scratchdimen\tabl_ntb_get_dis\currentloopiterator}%
   \ifdim\scratchdimen<\wd\scratchbox\relax
     \scratchdimen\wd\scratchbox\relax
   \fi}

\newdimension\d_tabl_ntb_saved_hsize

\let\tabl_ntb_pass\relax

\def\tabl_ntb_table_stop
  {\forgetall % new, here see narrower-004.tex
  %\setbox\scratchbox\hbox
  %  {\letnaturaltablelocalparameter  \c!frame     \v!off
  %   \resetnaturaltablelocalparameter\c!background
  %   \letnaturaltablelocalparameter  \c!align     \v!no
  %   \inheritednaturaltablelocalframed{\strut}}%
  %\edef\minimalcellheight{\the\ht\scratchbox}% not used
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
     {\tabl_ntb_let_aut\currentloopiterator\zeropoint
      % new
      \c_tabl_ntb_current_col_one\currentloopiterator\relax
      \localcontrolledloop\plusone\c_tabl_ntb_maximum_row\plusone
        {%tabl_ntb_let_wd\currentloopiterator\c_tabl_ntb_current_col_one\zeropoint
         \tabl_ntb_let_ht\currentloopiterator\c_tabl_ntb_current_col_one\zeropoint}%
      % till here
      \tabl_ntb_let_tal\currentloopiterator\zerocount
      \tabl_ntb_let_wid\currentloopiterator\zeropoint
      \tabl_ntb_let_dis\currentloopiterator\zeropoint}%
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_row\plusone
     {\tabl_ntb_let_hei\currentloopiterator\maxdimen}%
   \tabl_ntb_let_gal\zerocount
   \tabl_ntb_preroll\relax
   \c_tabl_tbl_pass\plusone
   \let\tabl_ntb_pass\tabl_ntb_pass_one
   \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a
   \expand\t_tabl_ntb_initializers_first\relax
   \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
   \ifcase\tabl_ntb_get_gal\or
      % so \c_tabl_tbl_pass is not really a pass count
    % \c_tabl_tbl_pass\plusone
    % \let\tabl_ntb_pass\tabl_ntb_pass_one
      \let\tabl_ntb_cell_process\tabl_ntb_cell_process_a_extra
      \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
   \fi
   \tabl_ntb_let_dis\c_tabl_ntb_maximum_col\zeropoint
   %
   \tabl_ntb_table_get_max_width % \scratchdimen\scratchbox
   %
   \ifautoTBLspread
     % experimental, stretch non fixed cells to \hsize
     \tabl_ntb_check_widths_one   % trial run
     \tabl_ntb_check_widths_two   % real run
     \tabl_ntb_stretch_widths
     \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
     \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
 % \orelse\ifdim\wd\scratchbox>\hsize
   \orelse\ifdim\scratchdimen>\hsize
     \ifautoTBLhsize
       \tabl_ntb_check_widths_one % trial run
       \tabl_ntb_check_widths_two % real run
       \let\tabl_ntb_cell_process\tabl_ntb_cell_process_b
       \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
     \fi
   \orelse\ifautoTBLrowspan
     \ifnum\c_tabl_ntb_maximum_row_span>\plusone % max ?
       % added jan 2002 because nx=* did no longer work
       \ifnum\c_tabl_ntb_encountered_max<\c_tabl_ntb_maximum_col
         % added jun 2014 because someone had less columns than nx .. sigh / see *nx*
         \writestatus\m!TABLE{missing\space\tointeger{\c_tabl_ntb_maximum_col-\c_tabl_ntb_encountered_max} column(s), guessing widths}%
       \fi
       \d_tabl_ntb_saved_hsize\hsize
     % \hsize\wd\scratchbox\relax % new per 17/04/2006
       \hsize\scratchdimen\relax % new per 17/04/2006
       \tabl_ntb_check_widths_one % trial run
       \tabl_ntb_check_widths_two % real run
       \hsize\d_tabl_ntb_saved_hsize
       \let\tabl_ntb_cell_process\tabl_ntb_cell_process_c
       \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
     \fi
   \fi
   \let\tabl_ntb_cell_process\tabl_ntb_cell_process_d
   \c_tabl_tbl_pass\plustwo
   \let\tabl_ntb_pass\tabl_ntb_pass_two
   \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}%
   \tabl_ntb_check_heights_one
   \tabl_ntb_check_heights_two
   \let\tabl_ntb_cell_process\tabl_ntb_cell_process_e
   \c_tabl_tbl_pass\plusthree
   \let\tabl_ntb_pass\tabl_ntb_pass_three
   \expand\t_tabl_ntb_initializers_second\relax
   \ifnum\m_tabl_ntb_level>\plusone
     \tabl_ntb_split_nop
   \orelse\ifenableTBLbreak
     \tabl_ntb_split_yes
   \else
     \tabl_ntb_split_nop
   \fi}

\def\tabl_ntb_stretch_widths % more variants, e.g. a max to \dimend
  {\ifcase\c_tabl_ntb_maximum_col\else % else division by zero
     \scratchdimenfour\zeropoint
     \scratchdimenfive{%
        \hsize
       -\d_tabl_ntb_leftmargindistance
       -\d_tabl_ntb_rightmargindistance
       +\d_tabl_ntb_columndistance
     }%
     \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
       {\advanceby\scratchdimenfour{%
          \tabl_ntb_get_wid\currentloopiterator % no need for expression
        }
        \advanceby\scratchdimenfive{%
          -\tabl_ntb_get_dis\currentloopiterator
          -\d_tabl_ntb_columndistance
        }}%
     \relax
     % distribute width (stretch)
     \ifdim\scratchdimenfour<\scratchdimenfive
       \advanceby\scratchdimenfour-\scratchdimenfive
       \divideby\scratchdimenfour\c_tabl_ntb_maximum_col
       \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
         {\scratchdimen{\tabl_ntb_get_wid\currentloopiterator-\scratchdimenfour}%
          \tabl_ntb_set_wid\currentloopiterator\scratchdimen}%
     \fi
   \fi}

\def\tabl_ntb_split_nop
  {\setbox\b_tabl_ntb_final\vbox{\tabl_ntb_flush_content}%
   \postprocessTABLEbox\b_tabl_ntb_final
   \tabl_ntb_anchor_process\b_tabl_ntb_final
   \beforeTABLEbox
 % packaging prevents max hsized box
 % \hbox{\registerparoptions\box\b_tabl_ntb_final}% (*) better here
 % better :
   \ifinsidefloat
     % no \dontleavehmode else too wide, otherwise we get a \hsized box
   \else
     \registerparoptions % (*) better here (also does a \dontleavehmode)
     \ifhmode\else\dontleavehmode\fi
   \fi
   \box\b_tabl_ntb_final
   \afterTABLEbox}

\def\tabl_ntb_split_page
  {%\postprocessTABLEbox\b_tabl_ntb_final
   %\tabl_ntb_anchor_process\b_tabl_ntb_final
   \beforeTABLEbox
   \registerparoptions % (*) better here (also does a \dontleavehmode)
   \ifhmode\else\dontleavehmode\fi
   \tabl_ntb_flush_content
   \afterTABLEbox}

\def\tabl_ntb_split_yes
  {\ifinsidesplitfloat
     \donefalse
   \orelse\ifinsidefloat
     \donetrue
   \else
     \donefalse
   \fi
   \ifdone
     \expandafter\tabl_ntb_split_nop
   \orelse\ifforceTBLpageflow
     \expandafter\tabl_ntb_split_page
   \else
     \expandafter\tabl_ntb_split_box
   \fi}

\newbox\TABLEsplitbox % public, don't change

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

\def\tabl_ntb_split_box
  {\resettsplit
   \c_split_minimum_free_lines\plustwo
   \d_split_minimum_free_space{\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset}%
   \t_split_before_result{\beforeTABLEsplitbox}%
   \t_split_after_result{\afterTABLEsplitbox}%
   \t_split_after{\m_tabl_ntb_after_split}%
   \t_split_before{\m_tabl_ntb_before_split}% not used (yet)
   \setbox\b_split_content\vbox{\tabl_ntb_flush_content}%
   \tabl_ntb_section_install % we need content to be set
   \ifmultipleTBLheads
     \localcontrolledloop\plusone\c_tabl_ntb_n_of_head_lines\plusone
       {\setbox\scratchbox\vsplit\b_split_content to \lineheight
        \setbox\b_split_head\vbox{\unvcopy\b_split_head\unvcopy\scratchbox}}% \vpack ?
     \localcontrolledloop\plusone\c_tabl_ntb_n_of_next_lines\plusone
       {\setbox\scratchbox\vsplit\b_split_content to \lineheight
        \setbox\b_split_next\vbox{\unvcopy\b_split_next\unvcopy\scratchbox}}% \vpack ?
   \fi
   \edef\p_spaceinbetween{\naturaltablelocalparameter\c!spaceinbetween}%
   \ifempty\p_spaceinbetween\else
     \blank[\p_spaceinbetween]%
   \fi
   \def\postprocesstsplit{\postprocessTABLEsplitbox{\box\b_split_result}}%
   \handletsplit}

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

\mutable\let\postprocessTABLEsplitbox\gobbleoneargument % maybe just a parameter
\mutable\let\postprocessTABLEbox     \gobbleoneargument % maybe just a parameter

\mutable\let\beforeTABLEsplitbox\relax                  % maybe just a parameter
\mutable\let\afterTABLEsplitbox \relax                  % maybe just a parameter
\mutable\let\beforeTABLEbox     \relax                  % maybe just a parameter
\mutable\let\afterTABLEbox      \relax                  % maybe just a parameter

\def\tabl_ntb_check_widths_one{\tabl_ntb_check_widths_indeed\zerocount} % 0 = trial run
\def\tabl_ntb_check_widths_two{\tabl_ntb_check_widths_indeed\plusone  } % 1 = real run

\def\tabl_ntb_check_widths_indeed#1%
  {\ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths B#1\fi
   \scratchcounterone\zerocount
   \scratchdimenone{%
     \hsize
    -\d_tabl_ntb_leftmargindistance
    -\d_tabl_ntb_rightmargindistance
    -\d_tabl_ntb_columndistance
   }%
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
     {\scratchdimen\tabl_ntb_get_aut\currentloopiterator
      \advanceby\scratchdimenone{%
        -\tabl_ntb_get_dis\currentloopiterator
        -\d_tabl_ntb_columndistance
      }%
      \ifdim\scratchdimen>\zeropoint\relax
        \advanceby\scratchdimenone -\scratchdimen
      \else
        \scratchdimen\tabl_ntb_get_wid\currentloopiterator\relax
        \ifdim\scratchdimen>\d_tabl_ntb_maxwidth\relax
          \ifcase#1\else\tabl_ntb_let_wid\currentloopiterator\zeropoint\fi
          \advanceby\scratchcounterone \plusone
        \orelse\ifdim\scratchdimen>\zeropoint\relax
          \advanceby\scratchdimenone -\scratchdimen
        \orelse\ifnum\c_tabl_ntb_encountered_max=\c_tabl_ntb_maximum_col % *nx* bah
          % eigenlijk moet dit alleen als de kolom wordt overspannen door een
          % vorige, maw extra dubbele loop en status var
            \advanceby\scratchcounterone \plusone % setting maxwidth to a large value also works
        \fi
      \fi}%
   \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths M#1\fi
   \ifcase\scratchcounterone \else \divideby\scratchdimenone \scratchcounterone \fi
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
     {\scratchdimen\tabl_ntb_get_wid\currentloopiterator
      \ifcase#1\relax
        \ifdim\scratchdimen<\scratchdimenone  % take natural width
          \tabl_ntb_set_aut\currentloopiterator\scratchdimen
        \fi
      \else
        \ifzeropt\scratchdimen % auto set width
          \tabl_ntb_set_wid\currentloopiterator\scratchdimenone
        \fi
      \fi}%
   \ifconditional\c_tabl_ntb_trace_widths\tabl_ntb_show_widths E#1\fi}

\def\tabl_ntb_check_heights_one_indeed
  {\scratchcountertwo\tabl_ntb_get_row\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\relax
    % check row span
   \ifnum\scratchcountertwo>\plusone
     % current height in row
     \scratchdimenone\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three
     % find nearest height in row
     \scratchdimentwo\zeropoint
     \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
       {\ifnum\currentloopiterator=\c_tabl_ntb_current_col_three
        \orelse\ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\the\currentloopiterator\endcsname
          \scratchcounterthree\tabl_ntb_get_row\c_tabl_ntb_current_row_three\currentloopiterator\relax
          \ifnum\scratchcounterthree=\plusone
            \scratchdimenthree\tabl_ntb_get_ht\c_tabl_ntb_current_row_three\currentloopiterator\relax
            \ifdim\scratchdimentwo<\scratchdimenthree
              \scratchdimentwo\scratchdimenthree
            \fi
          \fi
        \fi}%
     \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
     % calculate cummulative height
     \scratchdimenthree\scratchdimentwo
     \scratchcounterthree\c_tabl_ntb_current_row_three
     \advanceby\scratchcounterthree\minusone
     \localcontrolledloop\plusone\scratchcountertwo\plusone
       {\ifnum\c_tabl_ntb_current_row_four=\c_tabl_ntb_current_row_three\else
          \advanceby\scratchdimenthree\tabl_ntb_get_hei\c_tabl_ntb_current_row_four
        \fi
        \ifnum\currentloopiterator=\scratchcountertwo\else
          \tabl_ntb_set_nob\scratchcounterthree
          \advanceby\scratchcounterthree\plusone
        \fi
        \advanceby\c_tabl_ntb_current_row_four\plusone}%
     % distribute overshoot equally
     \ifdim\scratchdimentwo>\zeropoint % new: test on natural-003
       \ifdim\scratchdimenthree<\scratchdimenone
         \advanceby\scratchdimenone -\scratchdimenthree
         \divideby\scratchdimenone \scratchcountertwo
         \c_tabl_ntb_current_row_four\c_tabl_ntb_current_row_three
         \tabl_ntb_set_hei\c_tabl_ntb_current_row_three\scratchdimentwo\relax
         \localcontrolledloop\plusone\scratchcountertwo\plusone
           {\localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
              {\ifnum\currentloopiterator=\c_tabl_ntb_current_col_three\else
                 \scratchdimen{\tabl_ntb_get_ht\c_tabl_ntb_current_row_four\currentloopiterator+\scratchdimenone}%
                 \tabl_ntb_set_ht\c_tabl_ntb_current_row_four\currentloopiterator\scratchdimen
                 \ifdim\tabl_ntb_get_hei\c_tabl_ntb_current_row_four<\scratchdimen
                   \tabl_ntb_set_hei\c_tabl_ntb_current_row_four\scratchdimen
                 \fi
               \fi}%
            \advanceby\c_tabl_ntb_current_row_four\plusone}%
       \orelse\ifdim\scratchdimenthree>\scratchdimenone
         \iftightTBLrowspan
           \tabl_ntb_set_hei\c_tabl_ntb_current_row_three\scratchdimentwo\relax
         \fi
       \fi
     \fi
   \fi}

\def\tabl_ntb_check_heights_one
  {\localcontrolledloop\plusone\c_tabl_ntb_maximum_row\plusone
     {\c_tabl_ntb_current_row_three\currentloopiterator\relax
      \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
        {\c_tabl_ntb_current_col_three\currentloopiterator\relax
         \ifcsname\tabl_ntb_row_pattern\c_tabl_ntb_current_row_three\c_tabl_ntb_current_col_three\endcsname
           \tabl_ntb_check_heights_one_indeed
         \fi}}}

\def\tabl_ntb_check_heights_two
  {}

\def\tabl_ntb_show_widths#1#2%
  {\begingroup
   \scratchdimen\zeropoint
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
     {\advanceby\scratchdimen\tabl_ntb_get_wid\currentloopiterator\relax}%
   \writestatus\m!TABLE{#1 \ifcase#2trial\else real\fi: hsize: \the\hsize, total: \the\scratchdimen}%
   \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone
     {\writestatus\m!TABLE{\space\space\the\currentloopiterator: \the\dimexpr\tabl_ntb_get_wid\currentloopiterator}}%
   \endgroup}

\def\tabl_ntb_char_align % called often
  {\ifcstok{\naturaltablelocalparameter\c!aligncharacter}\v!yes
     \ifcase\c_tabl_tbl_pass\or
       \tabl_ntb_let_tal\currentTABLEcolumn\plusone
       \tabl_ntb_let_gal\plusone
     \fi
     \expandafter\tabl_ntb_char_align_indeed
   \else
     \expandafter\gobbletwoarguments
   \fi}

\def\tabl_ntb_char_align_indeed#1#2% row column
  {\ifcase\c_tabl_tbl_pass\or
     \setcharacteralign{#2}{\naturaltablelocalparameter\c!alignmentcharacter}% we could store the character in tal
   \fi
   \typo_charalign_adapt_font
   \signalcharacteralign{#2}{#1}}

\protected\def\tabl_ntb_cell_process_a_extra#1#2%
  {\ifcase\tabl_ntb_get_tal{#2}\relax
     \expandafter\tabl_ntb_cell_process_x
   \else
     \expandafter\tabl_ntb_cell_process_a
   \fi{#1}{#2}}

\protected\def\tabl_ntb_cell_process_x#1#2[#S#3]#4%
  {}

% problem: when span doesn't break we can have a span that is the sum of cells but
% still to small .. chicken egg problem ... for that we should also have a smallest
% width run
%
% nilling the background makes a run upto 25% faster

\def\tabl_ntb_cell_process_a_check_span_one
  {\ifautosqueezeTBLspan
     \edef\p_width{\naturaltablelocalparameter\c!width}%
     \ifcsname\??naturaltablesqueeze\p_width\endcsname\lastnamedcs\else\donefalse\fi
   \else
     \donetrue
   \fi
   \ifdone % brr, 0
     \ifnum\scratchcounter>\plusone
       \tabl_ntb_set_spn\c_tabl_ntb_col
     \fi
   \fi}

\let\tabl_ntb_cell_process_a_check_span_two_yes\relax

\def\tabl_ntb_cell_process_a_check_span_two_nop
  {\ifdim\tabl_ntb_get_wid\c_tabl_ntb_col<\wd\scratchbox
     \tabl_ntb_set_wid\c_tabl_ntb_col\wd\scratchbox
   \fi}

\protected\def\tabl_ntb_cell_process_a#1#2[#S#3]#4% grouping added ! ! !
  {\begingroup
   \resetnaturaltablelocalparameter\c!option\empty
   \tabl_ntb_setup_cell{#1}{#2}%
   \setupcurrentnaturaltablelocal[#3]%
   \resetnaturaltablelocalparameter\c!background
   \letnaturaltablelocalparameter\c!frame\v!off
   \scratchcounter\tabl_ntb_get_col{#1}{#2}\relax
   \setbox\scratchbox\hbox
     {\scratchdimen{\naturaltablelocalparameter\c!distance}%
      \ifdim\scratchdimen>\tabl_ntb_get_dis{#2}\relax
        \tabl_ntb_set_dis{#2}\scratchdimen
      \fi
      \anch_backgrounds_text_level_start
      \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop\tabl_ntb_cell_finalize}%
      \anch_backgrounds_text_level_stop
      \ifcase\c_anch_backgrounds_text_count\else
        \tabl_ntb_let_bck{#1}{#2}\c_anch_backgrounds_text_state
      \fi
     }%
   \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
   \ifdim\wd\scratchbox>\scratchdimen
     \ifsqueezeTBLspan
       \tabl_ntb_cell_process_a_check_span_one
     \fi
    %\tabl_ntb_spn_doifelse\c_tabl_ntb_col
    %  \tabl_ntb_cell_process_a_check_span_two_yes
    %  \tabl_ntb_cell_process_a_check_span_two_nop
     \ifcondition\tabl_ntb_spn_condition\c_tabl_ntb_col
       \tabl_ntb_cell_process_a_check_span_two_yes
     \else
       \tabl_ntb_cell_process_a_check_span_two_nop
     \fi
   \fi
   \scratchcounter{\c_tabl_ntb_row+\plusone}%
   \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
   \ifdim\ht\scratchbox<\scratchdimen
     \tabl_ntb_set_hei\scratchcounter\ht\scratchbox% auto set
   \fi
   \tabl_ntb_set_ht{#1}{#2}\ht\scratchbox
   %tabl_ntb_set_wd{#1}{#2}\wd\scratchbox
   \ifautoTBLcheckwidth
     \ifdim\wd\scratchbox<.75\hsize % fuzzy guess
       \ifdim\ht\scratchbox>2\openlineheight % honor width since this
         \scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax % can be a figure or so
         \ifzeropt\scratchdimen
           % side effect: when width is set to 0pt,
           % we can force a span that fits the sum of spans widths
           \tabl_ntb_set_aut\c_tabl_ntb_col\scratchdimen
         \orelse\ifdim\wd\scratchbox>\scratchdimen
           % unless span
           \tabl_ntb_set_aut\c_tabl_ntb_col\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
   \setbox\scratchboxone\emptyhbox
   \wd\scratchboxone\wd\scratchbox
   \ht\scratchboxone\ht\scratchbox
   \dp\scratchboxone\dp\scratchbox
   \box\scratchboxone
   \endgroup}

\protected\def\tabl_ntb_cell_process_b_c#1#2#3[#S#4]#5%
  {\begingroup
   \setbox\scratchbox\hbox
     {\tabl_ntb_setup_cell{#2}{#3}%
      \setupcurrentnaturaltablelocal[#4,#1]%
      \resetnaturaltablelocalparameter\c!background
      \letnaturaltablelocalparameter\c!frame\v!off
      \inheritednaturaltablelocalframed{\tabl_ntb_cell_start#5\tabl_ntb_cell_stop}}%
   \setbox\scratchboxone\emptyhbox
   \wd\scratchboxone\wd\scratchbox
   \ht\scratchboxone\ht\scratchbox
   \dp\scratchboxone\dp\scratchbox
   \ifautoTBLrowspan
     \scratchcounter{\c_tabl_ntb_row+\plusone}%
     \ifcsname\tabl_ntb_row_pattern\scratchcounter\c_tabl_ntb_col\endcsname
       \scratchdimen\tabl_ntb_get_hei\scratchcounter\relax
       \ifnum\tabl_ntb_get_row\scratchcounter\c_tabl_ntb_col>\plusone
         \ifdim\ht\scratchbox>\scratchdimen
           \ht\scratchboxone{-\scratchdimen-\ht\scratchbox}%
         \fi
       \fi
     \fi
   \fi
   \box\scratchboxone
   \endgroup}

\protected\def\tabl_ntb_cell_process_b#1#2[#S#3]#4%
   {\scratchdimen\tabl_ntb_get_aut\c_tabl_ntb_col\relax
    \ifdim\scratchdimen>\zeropoint\relax
    \else
      \scratchdimen\tabl_ntb_get_wid\c_tabl_ntb_col\relax
      \ifdim\scratchdimen>\zeropoint\relax
        \ifnum\tabl_ntb_get_col{#1}{#2}=\c_tabl_ntb_maximum_col\relax
          \scratchdimen\hsize
        \fi
      \fi
    \fi
    \expanded{\tabl_ntb_cell_process_b_c{\ifdim\scratchdimen>\zeropoint \c!width=\the\scratchdimen\fi}}%
      {#1}{#2}[#3]{\tabl_ntb_char_align{#1}{#2}#4}}

\protected\def\tabl_ntb_cell_process_c
  {\tabl_ntb_cell_process_b_c{}}

\protected\def\tabl_ntb_cell_process_d#1#2[#S#3]#4%
  {\tabl_ntb_setup_cell{#1}{#2}%
   \bgroup
   \setupcurrentnaturaltablelocal[#3]%
   \resetnaturaltablelocalparameter\c!background
   \letnaturaltablelocalparameter  \c!frame     \v!off
   \setnaturaltablelocalparameter  \c!width     {\d_tabl_ntb_width}%
   \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}%
   \egroup}

\protected\def\tabl_ntb_cell_process_e#1#2[#S#3]#4%
  {\begingroup
   \tabl_ntb_setup_cell{#1}{#2}%
   \setupcurrentnaturaltablelocal[#3]% to get the color right, the way we
   \directcolor[\naturaltablelocalparameter\c!color]%
   \resetnaturaltablelocalparameter\c!color
   \setnaturaltablelocalparameter  \c!width{\d_tabl_ntb_width}%
   \ifzeropt\d_tabl_ntb_height % case: nc=maxcolumns
   \else
     \setnaturaltablelocalparameter\c!height{\d_tabl_ntb_height}%
   \fi
   \ifcase\c_anch_backgrounds_text_count\else
     \edef\p_region{\naturaltablelocalparameter\c!region}%
     \ifempty\p_region\ifnum\tabl_ntb_get_bck{#1}{#2}>\zerocount
       \letnaturaltablelocalparameter\c!region\v!yes
     \fi\fi
   \fi
   \tabl_ntb_anchor_start{#1}{#2}%
   \inheritednaturaltablelocalframed{\tabl_ntb_cell_start\tabl_ntb_char_align{#1}{#2}#4\tabl_ntb_cell_stop}%
   \tabl_ntb_anchor_stop
   \hkern\tabl_ntb_get_dis{#2}%
   \endgroup}

\newtoks\everyresetTABLEyes
\newtoks\everyresetTABLEnop

% todo : use \letTABLEparameter\c!width\v!fit ...

\appendtoks
    \setupTABLE [%
        %
        % framed defaults
        %
        \c!width=\v!fit,%
        \c!height=\v!fit,%
        \c!lines=,%
        \c!offset=.25\exheight,%
        \c!empty=\v!no,%
        \c!frame=\v!on,%
        \c!topframe=,%
        \c!bottomframe=,%
        \c!leftframe=,%
        \c!rightframe=,%
        \c!radius=.5\bodyfontsize,%
        \c!rulethickness=\linewidth,%
        \c!corner=\v!rectangular,%
        \c!depth=\zeropoint,%
        \c!foregroundcolor=,%
        \c!foregroundstyle=,%
        \c!background=,%
        \c!backgroundcolor=,%
        \c!backgroundoffset=\v!frame,%
        \c!framecolor=,%
        \c!frameoffset=.5\linewidth,%
      % \c!backgroundcorner=\framedparameter\c!corner,%
      % \c!backgrounddepth=\framedparameter\c!depth,%
      % \c!backgroundradius=\framedparameter\c!radius,%
      % \c!framecorner=\framedparameter\c!corner,%
      % \c!framedepth=\framedparameter\c!depth,%
      % \c!frameradius=\framedparameter\c!radius,%
        \c!component=,%
        \c!region=,%
        \c!align=,%
        \c!bottom=\vss,%
        \c!top=,%
        \c!strut=\v!yes,%
        \c!autostrut=\v!no,%
        \c!location=\v!normal,%
        \c!orientation=,%
        \c!autowidth=\v!yes,%
        \c!setups=,%
        \c!loffset=\zeropoint,%
        \c!roffset=\zeropoint,%
        \c!toffset=\zeropoint,%
        \c!boffset=\zeropoint,%
        %
        % table specific
        %
        \c!aligncharacter=\v!no,%
        \c!alignmentcharacter={,},%
        \c!color=,%
        \c!columndistance=\zeropoint,%       each column (whole table)
        \c!distance=\zeropoint,%             individual column
        \c!headcolor=,%
        \c!header=,%
        \c!headstyle=\v!bold,%
        \c!left=,%
        \c!leftmargindistance=\zeropoint,%   whole table
        \c!maxwidth=8\emwidth,%
        \c!option=,%                         \v!stretch
        \c!right=,%
        \c!rightmargindistance=\zeropoint,%  whole table
        \c!spaceinbetween=,%
        \c!split=\v!auto,%
        \c!splitoffset=\zeropoint,%
        \c!style=,%
        \c!textwidth=\v!local,%              was \hsize
    ]%
\to \everyresetTABLEyes

\appendtoks
    \setupTABLE [%
        \c!width=\v!fit,%
        \c!height=\v!fit%
    ]%
\to \everyresetTABLEnop

\expand\everyresetTABLEyes

% \bgroup
% \setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}]
% \bTABLE
%     \bTR  \bTD  1,2 \eTD  \bTD 2 \eTD \eTR
%     \bTR  \bTD 11,2 \eTD  \bTD
%         {\setupTABLE[column][1][aligncharacter=yes, alignmentcharacter={,}]
%          \bTABLE
%             \bTR  \bTD 1,2 \eTD  \bTD 2 \eTD \eTR
%             \bTR  \bTD  11,22 \eTD  \bTD 2 \eTD \eTR
%             \bTR  \bTD 11,2 \eTD  \bTD 2 \eTD \eTR \eTABLE} \eTD \eTR
%     \bTR  \bTD  11,22 \eTD  \bTD 2 \eTD \eTR
% \eTABLE
% \egroup

\newconditional\resetTABLEmode \resetTABLEmode\conditionaltrue

\def\tabl_ntb_parameters_reset % we can use setters instead
  {\ifnum\m_tabl_ntb_level>\plusone % in ieder geval
     \ifconditional\resetTABLEmode
        \expand\everyresetTABLEyes
     \else
        \expand\everyresetTABLEnop
     \fi
  \fi}

% new (for Olivier Turlier)
%
% \defineTABLEsetup [xx] [foregroundcolor=red]
%
% \bTABLE
%     \bTR      \bTD      oeps \eTD  \bTD oeps \eTD \eTR
%     \bTR      \bTDs[xx] oeps \eTDs \bTD oeps \eTD \eTR
%     \bTRs[xx] \bTD      oeps \eTD  \bTD oeps \eTD \eTRs
% \eTABLE

\installcorenamespace{naturaltablesetup}

\permanent\tolerant\protected\def\defineTABLEsetup[#1]#*[#S#2]%
  {\ifarguments\else\defcsname\??naturaltablesetup#1\endcsname{#2}\fi}

\permanent\let\eTDs\relax
\permanent\let\eTRs\relax

\permanent\protected\def\bTDs[#1]#2\eTDs
  {\expanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD}

\permanent\protected\def\bTRs[#1]#2\eTRs
  {\expanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR}

%D This is new (for Ramkumar, Kb)
%D
%D \starttyping
%D \bTABLE[split=repeat]
%D     \bTABLEhead
%D         \bTR \bTH \darkblue header \eTH \bTH \darkblue done \eTH \eTR
%D     \eTABLEhead
%D     \dorecurse{12}{
%D         \bTABLEbody
%D             \bTABLEsection
%D                 \bTR \bTD \darkred line #1.1 \eTD \bTD \darkred done \eTD \eTR
%D                 \bTR \bTD \darkred line #1.2 \eTD \bTD \darkred done \eTD \eTR
%D             \eTABLEsection
%D             \bTABLEsection[repeat=2]
%D                 \bTR[samepage=after] \bTH \darkorange header #1.1 \eTH \bTH \darkorange done \eTH \eTR
%D                 \bTR[samepage=after] \bTH \darkorange header #1.2 \eTH \bTH \darkorange done \eTH \eTR
%D                 \bTR                 \bTD \darkgreen  hline  #1.3 \eTD \bTD \darkgreen  done \eTD \eTR
%D                 \bTR                 \bTD \darkgreen  hline  #1.4 \eTD \bTD \darkgreen  done \eTD \eTR
%D                 \bTR                 \bTD \darkgreen  hline  #1.5 \eTD \bTD \darkgreen  done \eTD \eTR
%D             \eTABLEsection
%D         \eTABLEbody
%D     }
%D \eTABLE
%D \stoptyping

\definesystemattribute[tablesection][public]

\newinteger\c_tabl_ntb_section
\newinteger\c_tabl_ntb_section_repeat

\def\tabl_ntb_section_mark_indeed
  {\ifcase\c_tabl_ntb_section_repeat
     \tabl_ntb_set_sec\c_tabl_ntb_maximum_row\zerocount\zerocount
   \else
     \tabl_ntb_set_sec\c_tabl_ntb_maximum_row\c_tabl_ntb_section\c_tabl_ntb_section_repeat
   \fi}

\def\tabl_ntb_section_checkup_indeed
  {\scratchcounter\tabl_ntb_get_sec\c_tabl_ntb_row\relax
   \ifcase\scratchcounter
     \c_attr_tablesection\attributeunsetvalue
   \else
     \c_attr_tablesection\scratchcounter
   \fi}

\def\tabl_ntb_section_split_indeed
  {\scratchcounter\clf_ntb_split_section_locate\b_split_content\relax
   \ifcase\scratchcounter\else
     \clf_ntb_split_section_fetch\scratchcounter
   \fi}

\def\tabl_ntb_section_wrapup_indeed
   {\clf_ntb_split_section_reset\b_split_content
    \tabl_ntb_section_setup}

\def\tabl_ntb_section_install_indeed
  {\clf_ntb_split_section_check\b_split_content
   \t_split_section{\tabl_ntb_section_split}}

\def\tabl_ntb_section_disable
  {\glet\tabl_ntb_section_mark   \relax
   \glet\tabl_ntb_section_checkup\relax
   \glet\tabl_ntb_section_split  \relax
   \glet\tabl_ntb_section_install\relax
   \glet\tabl_ntb_section_wrapup \relax}

\def\tabl_ntb_section_enable
  {\let\tabl_ntb_section_enable  \relax
   \glet\tabl_ntb_section_mark   \tabl_ntb_section_mark_indeed
   \glet\tabl_ntb_section_checkup\tabl_ntb_section_checkup_indeed
   \glet\tabl_ntb_section_split  \tabl_ntb_section_split_indeed
   \glet\tabl_ntb_section_install\tabl_ntb_section_install_indeed
   \glet\tabl_ntb_section_wrapup \tabl_ntb_section_wrapup_indeed}

\def\tabl_ntb_section_setup
  {\global\c_tabl_ntb_section_repeat\zerocount
   \c_tabl_ntb_section\zerocount
   \tabl_ntb_section_disable}

\tolerant\permanent\protected\def\bTABLEsection[#S#1]%
  {\ifempty{#1}%
     \global\c_tabl_ntb_section_repeat\zerocount
   \else
     \letdummyparameter\c!repeat\zerocount
     \getdummyparameters[#1]%
     \global\c_tabl_ntb_section_repeat\dummyparameter\c!repeat\relax
   \fi
   \global\advanceby\c_tabl_ntb_section\plusone
   \tabl_ntb_section_enable}

\permanent\protected\def\eTABLEsection
  {\global\c_tabl_ntb_section_repeat\zerocount}

\protect \endinput

% todo: mode: first|next (of niets)