%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} % 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 \the\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 % \the\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 \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_tbl_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_tbl_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} \protected\def\tabl_ntb_next_level {\advanceby\c_tabl_level\plusone \edef\m_tabl_tbl_level{\the\c_tabl_level}} \protected\def\tabl_ntb_prev_level {\advanceby\c_tabl_level\minusone \edef\m_tabl_tbl_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_tbl_level\endcsname} \def\tabl_ntb_get_gal{\csname \??naturaltablegal\m_tabl_tbl_level\endcsname} \def\tabl_ntb_let_tal#1{\gletcsname\??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname} \def\tabl_ntb_get_tal#1{\csname \??naturaltabletal\m_tabl_tbl_level:\number#1\endcsname} \def\tabl_ntb_set_nob#1{\letcsname\??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone} \def\tabl_ntb_get_nob#1{\ifcsname \??naturaltablenob\m_tabl_tbl_level:\number#1\endcsname\plusone\else\zerocount\fi} %def\tabl_ntb_set_tag#1#2{\expandafter\integerdef\csname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_set_col#1#2{\expandafter\integerdef\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_set_row#1#2{\expandafter\integerdef\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_let_tag#1#2{\letcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_let_col#1#2{\letcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_let_row#1#2{\letcsname\??naturaltablerow\m_tabl_tbl_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_tbl_level:\number#1:\number#2\endcsname} % global ! \def\tabl_ntb_set_ht#1#2{\global\expandafter\dimensiondef\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! %def\tabl_ntb_let_wd#1#2{\letcsname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} % global ! \def\tabl_ntb_let_ht#1#2{\letcsname\??naturaltableht\m_tabl_tbl_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_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_get_col#1#2{\csname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_get_row#1#2{\csname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname} %def\tabl_ntb_get_wd#1#2{\csname\??naturaltablewd\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_get_ht#1#2{\csname\??naturaltableht\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_set_wid#1{\global\expandafter\dimensiondef\csname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_set_hei#1{\global\expandafter\dimensiondef\csname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_set_dis#1{\global\expandafter\dimensiondef\csname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_set_aut#1{\global\expandafter\dimensiondef\csname\??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_let_wid#1{\gletcsname\??naturaltablewid\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_let_hei#1{\gletcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_let_dis#1{\gletcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname} % {#2} global ! \def\tabl_ntb_let_aut#1{\gletcsname\??naturaltableaut\m_tabl_tbl_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_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi} \def\tabl_ntb_get_hei#1{\ifcsname\??naturaltablehei\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi} \def\tabl_ntb_get_dis#1{\ifcsname\??naturaltabledis\m_tabl_tbl_level:\number#1\endcsname\lastnamedcs\else\zeropoint\fi} \def\tabl_ntb_get_aut#1{\csname \??naturaltableaut\m_tabl_tbl_level:\number#1\endcsname} \def\tabl_ntb_let_bck#1#2{\global\expandafter\integerdef\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_get_bck#1#2{\csname\??naturaltablebck\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_tag_pattern#1#2{\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2} \def\tabl_ntb_row_pattern#1#2{\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2} \def\tabl_ntb_col_pattern#1#2{\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2} \def\tabl_ntb_tag_doif #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} \def\tabl_ntb_tag_doifnot #1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\gobbleoneargument \else\expandafter\firstofoneargument \fi} \def\tabl_ntb_tag_doifelse#1#2{\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstoftwoarguments\else\expandafter\secondoftwoarguments\fi} \def\tabl_ntb_row_doif #1#2{\ifcsname\??naturaltablerow\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} \def\tabl_ntb_col_doif #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_level:\number#1:\number#2\endcsname\expandafter\firstofoneargument \else\expandafter\gobbleoneargument \fi} \def\tabl_ntb_col_doifnot #1#2{\ifcsname\??naturaltablecol\m_tabl_tbl_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_tbl_level:\number#1:\number#2\endcsname#3% % \fi} % % \def\tabl_ntb_get_tag#1#2% % {\ifcsname\??naturaltabletag\m_tabl_tbl_level:\number#1:\number#2\endcsname % \lastnamedcs % \else % \c_tabl_ntb_none % \fi} \def\tabl_ntb_let_ref #1#2{\gletcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname} \def\tabl_ntb_set_ref #1#2{\xdefcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname} %def\tabl_ntb_get_ref #1#2{\ifcsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\csname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname\fi} \def\tabl_ntb_get_ref #1#2{\begincsname\??naturaltableref\m_tabl_tbl_level:\number#1:\number#2\endcsname} % \def\tabl_ntb_set_spn #1{\letcsname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \!!plusone} % \def\tabl_ntb_spn_doifelse#1{\ifcase0\csname\??naturaltablespn\m_tabl_tbl_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_tbl_level:\number#1\endcsname\plusone} \def\tabl_ntb_spn_doifelse#1{\ifcsname\??naturaltablespn\m_tabl_tbl_level:\number#1\endcsname \expandafter\firstoftwoarguments % a span \else \expandafter\secondoftwoarguments % unset \fi} \protected\def\tabl_ntb_set_txt_process#1#2#3#4#5#6% {\defcsname\??naturaltabletxt\m_tabl_tbl_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_tbl_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} {\settrue \c_tabl_ntb_trace_widths} {\setfalse\c_tabl_ntb_trace_widths} % so far \protected\def\tabl_ntb_cell_process#1#2[#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 \let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal \let\tabl_ntb_setup_step \gobbleoneargument \let\tabl_ntb_setup_step_step\gobbleoneargument \permanent\tolerant\protected\def\setupTABLE[#1]#*[#2]#*[#3]% {\ifarguments \expandafter\gobblethreeoptionals \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} \installcorenamespace{naturaltablesetupthree} \installcorenamespace{naturaltablesetuptwo} \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[#1]{\tabl_ntb_setup_xy [\c!y]} \defcsname\??naturaltablesetupthree \v!column\endcsname[#1]{\tabl_ntb_setup_xy [\c!x]} \defcsname\??naturaltablesetupthree \v!start\endcsname[#1]{\tabl_ntb_setup_xy [\v!start]} \defcsname\??naturaltablesetupthree \v!header\endcsname[#1]{\tabl_ntb_setup_xy [\v!header]} \defcsname\??naturaltablesetuptwo \v!row\endcsname[#1]{\tabl_ntb_setup_each[\c!y]} \defcsname\??naturaltablesetuptwo \v!column\endcsname[#1]{\tabl_ntb_setup_each[\c!x]} \defcsname\??naturaltablesetuptwo \v!start\endcsname[#1]{\tabl_ntb_setup_each[\v!start]} \defcsname\??naturaltablesetuptwo \v!header\endcsname[#1]{\tabl_ntb_setup_each[\v!header]} \letcsname\??naturaltablesetupthree\s!unknown\endcsname\tabl_ntb_setup_un \letcsname\??naturaltablesetuptwo \s!unknown\endcsname\tabl_ntb_setup_ux % \letcsnamecsname\csname\??naturaltablesetupthree r\endcsname\csname\??naturaltablesetupthree \v!row\endcsname % \letcsnamecsname\csname\??naturaltablesetupthree c\endcsname\csname\??naturaltablesetupthree\v!column\endcsname % \letcsnamecsname\csname\??naturaltablesetupthree y\endcsname\csname\??naturaltablesetupthree \v!row\endcsname % \letcsnamecsname\csname\??naturaltablesetupthree x\endcsname\csname\??naturaltablesetupthree\v!column\endcsname % \letcsnamecsname\csname\??naturaltablesetuptwo r\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname % \letcsnamecsname\csname\??naturaltablesetuptwo c\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname % \letcsnamecsname\csname\??naturaltablesetuptwo y\endcsname\csname\??naturaltablesetuptwo \v!row\endcsname % \letcsnamecsname\csname\??naturaltablesetuptwo x\endcsname\csname\??naturaltablesetuptwo \v!column\endcsname \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_tbl_level:#1\endcsname \enforced\def\tabl_ntb_parameters_get[##1]% {\defcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname{\tabl_ntb_parameters_get[##1,#2]}}% \csname\??naturaltableset\m_tabl_tbl_level:#1\endcsname \enforced\let\tabl_ntb_parameters_get\setupcurrentnaturaltablelocal \else \defcsname\??naturaltableset\m_tabl_tbl_level:#1\endcsname{\tabl_ntb_parameters_get[#2]}% \fi \else \defcsname\??naturaltableset\m_tabl_tbl_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 \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{\number#1}% \edef\m_tabl_ntb_positive_col{\number#2}% % \edef\m_tabl_ntb_negative_row{\the\numexpr-\c_tabl_ntb_maximum_row+#1+\minusone\relax}% % \edef\m_tabl_ntb_negative_col{\the\numexpr-\c_tabl_ntb_maximum_col+#2+\minusone\relax}% \edef\m_tabl_ntb_negative_row{\number\numexpr-\c_tabl_ntb_maximum_row+#1+\minusone}% \edef\m_tabl_ntb_negative_col{\number\numexpr-\c_tabl_ntb_maximum_col+#2+\minusone}% % saves tokens (no speed gain) \edef\m_tabl_ntb_prefix{\??naturaltableset\m_tabl_tbl_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[#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\gobbleoneoptional \fi[#1]} \def\tabl_ntb_tr_yes[#1]% {\defcsname\??naturaltableset\m_tabl_tbl_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[#1]% {\advanceby\c_tabl_ntb_encountered_col\plusone \ifparameter#1\or \expandafter\tabl_ntb_td_yes \else \expandafter\tabl_ntb_td_nop \fi[#1]} \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\relax \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax % 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\relax \c_tabl_ntb_ny\naturaltableparameter\c!ny\relax \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 \normalexpanded {\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} \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 \normalexpanded {\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} \def\tabl_ntb_td_pass_n#1% {\scratchcounter\numexpr\m_tabl_ntb_n-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax \ifnum\scratchcounter>\zerocount \normalexpanded{\tabl_ntb_td[\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} \def\tabl_ntb_td_pass_m#1% {\scratchcounter\numexpr\m_tabl_ntb_m-\c_tabl_ntb_running_col+\minusone-\c_tabl_ntb_spn\relax \localcontrolledloop\plusone\scratchcounter\plusone{\normalexpanded{\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 \tolerant\def\tabl_ntb_th[#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[#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 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{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_head} \permanent\tolerant\protected\def\bTABLEnext[#1]#:#2\eTABLEnext{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_next} \permanent\tolerant\protected\def\bTABLEbody[#1]#:#2\eTABLEbody{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_body} \permanent\tolerant\protected\def\bTABLEfoot[#1]#:#2\eTABLEfoot{\appendtoks\tabl_ntb_section[#1]{#2}\to\t_tabl_ntb_foot} \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_tbl_level:\v!start\v!each\endcsname \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\v!oddeven\m_tabl_tbl_level\endcsname \begincsname\??naturaltableset\m_tabl_tbl_level:\v!start\m_tabl_tbl_level\endcsname} \permanent\tolerant\protected\def\bTABLE[#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\relax \d_tabl_ntb_rightmargindistance\naturaltablelocalparameter\c!rightmargindistance\relax \d_tabl_ntb_columndistance \naturaltablelocalparameter\c!columndistance\relax \d_tabl_ntb_maxwidth \naturaltablelocalparameter\c!maxwidth\relax % \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 {\number\c_tabl_ntb_maximum_row} \def\tabl_ntb_n_of_columns {\number\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} \permanent\protected\def\eTABLE % beware, we need to get rid of spurious spaces when in hmode {% tricky and dirty order -) \setfalse\c_tabl_ntb_okay % head \doifelsesometoks\t_tabl_ntb_head % slow, better a flag \iftok {\c_tabl_ntb_head\numexpr\c_tabl_ntb_maximum_row+\plusone\relax \the\t_tabl_ntb_head \c_tabl_ntb_n_of_head_lines\c_tabl_ntb_maximum_row\relax \doifelsesometoks\t_tabl_ntb_next {\the\t_tabl_ntb_next \c_tabl_ntb_n_of_next_lines\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_n_of_head_lines\relax}% {\c_tabl_ntb_n_of_next_lines\zerocount}% was 1 \c_tabl_ntb_n_of_hdnx_lines\c_tabl_ntb_maximum_row} {\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}% % body \c_tabl_ntb_body\numexpr\c_tabl_ntb_maximum_row+\plusone\relax \the\t_tabl_ntb_body % foot \doifelsesometoks\t_tabl_ntb_foot {\c_tabl_ntb_foot\numexpr\c_tabl_ntb_maximum_row+\plusone\relax \the\t_tabl_ntb_foot}% {\c_tabl_ntb_foot\zerocount}% % 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 \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone {\c_tabl_ntb_current_col\currentloopiterator\relax \normalexpanded{\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_tbl_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\numexpr\c_tabl_ntb_current_row_two-\c_tabl_ntb_current_row+\plusone\relax \c_tabl_ntb_current_col_two\numexpr\c_tabl_ntb_current_col_two-\c_tabl_ntb_current_col+\plusone\relax \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 \normalexpanded {\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\numexpr\c_tabl_ntb_maximum_row-\c_tabl_ntb_current_row+\plusone\relax \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 {\normalexpanded{\t_tabl_ntb{\the\t_tabl_ntb\noexpand\tabl_ntb_row_align_start\the\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_tbl_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_tbl_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\numexpr\c_tabl_ntb_row+\plusone\relax \ifnum\scratchcounter=\c_tabl_ntb_head \ifconditional\c_tabl_ntb_okay \dostoptagged \else \settrue\c_tabl_ntb_okay \fi \dostarttagged\t!tablehead\empty \orelse\ifnum\scratchcounter=\c_tabl_ntb_body \ifconditional\c_tabl_ntb_okay \dostoptagged \else \settrue\c_tabl_ntb_okay \fi \dostarttagged\t!tablebody\empty \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot \ifconditional\c_tabl_ntb_okay \dostoptagged \else \settrue\c_tabl_ntb_okay \fi \dostarttagged\t!tablefoot\empty \fi \dostarttagged\t!tablerow\empty} \def\tabl_ntb_stop_tagged {\dostoptagged \ifconditional\c_tabl_ntb_okay \scratchcounter\numexpr\c_tabl_ntb_row+\plustwo\relax \ifnum\scratchcounter=\c_tabl_ntb_body \dostoptagged \setfalse\c_tabl_ntb_okay \orelse\ifnum\scratchcounter=\c_tabl_ntb_foot \dostoptagged \setfalse\c_tabl_ntb_okay \orelse\ifnum\scratchcounter>\c_tabl_ntb_maximum_row \dostoptagged \setfalse\c_tabl_ntb_okay \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\dimexpr\d_tabl_ntb_leftmargindistance\relax} \protected\def\tabl_ntb_row_align_stop {\kern\dimexpr\d_tabl_ntb_rightmargindistance-\d_tabl_ntb_columndistance\relax \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\numexpr\c_tabl_ntb_row+\plusone\relax \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 {\the\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\??naturaltable %\registerparoptions % (*) triggers max hsize \the\t_tabl_ntb \dostoptagged} \protected\def\tabl_ntb_span#1% {\hskip\tabl_ntb_get_dis\c_tabl_ntb_col \localcontrolledloop\plusone#1\plusone {\hskip\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\dimexpr % no need for dimexpr \tabl_ntb_get_wid\scratchcounter \relax \advanceby\scratchcounter\plusone \else \localcontrolledloop\plusone\scratchcounterone\plusone {\advanceby\d_tabl_ntb_width\dimexpr \tabl_ntb_get_wid\scratchcounter \ifnum\currentloopiterator<\scratchcounterone +\d_tabl_ntb_columndistance +\tabl_ntb_get_dis\scratchcounter \fi \relax \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 \dostarttagged\t!tablecell\empty \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\dimexpr \tabl_ntb_get_wid\scratchcounter \relax \advanceby\scratchcounter\plusone \else \localcontrolledloop\plusone\scratchcounterone\plusone {\advanceby\d_tabl_ntb_width\dimexpr \tabl_ntb_get_wid\scratchcounter \ifnum\currentloopiterator<\scratchcounterone +\d_tabl_ntb_columndistance +\tabl_ntb_get_dis\scratchcounter \fi \relax \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 \normalexpanded{\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} \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 \setbox\scratchbox\vbox{\settrialtypesetting \tabl_ntb_flush_content}% \ifcase\tabl_ntb_get_gal\or % \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\number\numexpr\c_tabl_ntb_maximum_col-\c_tabl_ntb_encountered_max\relax\space 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 \ifnum\m_tabl_tbl_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\dimexpr \hsize -\d_tabl_ntb_leftmargindistance -\d_tabl_ntb_rightmargindistance +\d_tabl_ntb_columndistance \relax \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone {\advanceby\scratchdimenfour\dimexpr \tabl_ntb_get_wid\currentloopiterator \relax \advanceby\scratchdimenfive\dimexpr -\tabl_ntb_get_dis\currentloopiterator -\d_tabl_ntb_columndistance \relax}% \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\dimexpr\tabl_ntb_get_wid\currentloopiterator-\scratchdimenfour\relax \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\dimexpr\extratblsplitheight+\naturaltablelocalparameter\c!splitoffset\relax \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\dimexpr \hsize -\d_tabl_ntb_leftmargindistance -\d_tabl_ntb_rightmargindistance -\d_tabl_ntb_columndistance \relax \localcontrolledloop\plusone\c_tabl_ntb_maximum_col\plusone {\scratchdimen\tabl_ntb_get_aut\currentloopiterator \advanceby\scratchdimenone\dimexpr -\tabl_ntb_get_dis\currentloopiterator -\d_tabl_ntb_columndistance \relax \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\dimexpr\tabl_ntb_get_ht\c_tabl_ntb_current_row_four\currentloopiterator+\scratchdimenone\relax \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[#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[#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\relax \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 \fi \scratchcounter\numexpr\c_tabl_ntb_row+\plusone\relax \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[#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\numexpr\c_tabl_ntb_row+\plusone\relax \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\dimexpr-\scratchdimen-\ht\scratchbox\relax \fi \fi \fi \fi \box\scratchboxone \endgroup} \protected\def\tabl_ntb_cell_process_b#1#2[#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 \normalexpanded{\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[#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[#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 \hskip\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 \the\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 \settrue\resetTABLEmode \def\tabl_ntb_parameters_reset % we can use setters instead {\ifnum\m_tabl_tbl_level>\plusone % in ieder geval \ifconditional\resetTABLEmode \the\everyresetTABLEyes \else \the\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]#*[#2]% {\ifarguments\else\defcsname\??naturaltablesetup#1\endcsname{#2}\fi} \permanent\let\eTDs\relax \permanent\let\eTRs\relax \permanent\protected\def\bTDs[#1]#2\eTDs {\normalexpanded{\bTD[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTD} \permanent\protected\def\bTRs[#1]#2\eTRs {\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR} \protect \endinput % todo: mode: first|next (of niets)