summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/context/base/tabl-xtb.mkvi
diff options
context:
space:
mode:
authorMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
committerMojca Miklavec <mojca.miklavec@gmail.com>2012-05-14 17:38:55 +0000
commit15995e10bfc68edf79970c4ea4fbb6678566c46e (patch)
tree2de7ca2a83f2d37ef043ad7429a5cb945bb79ddb /Master/texmf-dist/tex/context/base/tabl-xtb.mkvi
parentc9a39f716f1e5ec820ed3aab2c9aef25c5a9d730 (diff)
ConTeXt 2012.05.14 16:00
git-svn-id: svn://tug.org/texlive/trunk@26371 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/context/base/tabl-xtb.mkvi')
-rw-r--r--Master/texmf-dist/tex/context/base/tabl-xtb.mkvi689
1 files changed, 689 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/context/base/tabl-xtb.mkvi b/Master/texmf-dist/tex/context/base/tabl-xtb.mkvi
new file mode 100644
index 00000000000..2382cae2190
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/tabl-xtb.mkvi
@@ -0,0 +1,689 @@
+% macros=mkvi
+
+%D \module
+%D [ file=tabl-xtb,
+%D version=2011.10.26,
+%D title=\CONTEXT\ Table Macros,
+%D subtitle=Xtreme,
+%D author=Hans Hagen,
+%D date=\currentdate,
+%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
+%C
+%C This module is part of the \CONTEXT\ macro||package and is
+%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
+%C details.
+
+\writestatus{loading}{ConTeXt Table Macros / Xtreme}
+
+\registerctxluafile{tabl-xtb}{1.001}
+
+% todo:
+%
+% - yes or no: foregroundstyle/color <- style/color
+% - template alignment
+% - maybe split horizontal (a la linetables)
+% - before/after and wrapping (linecorrection)
+% - maybe also some before/after commands
+% - maybe correction when non float usage
+% - tagging needs to be checked
+% - maybe only tag the box
+% - scale to fit
+%
+%D This module started as an afternoon experiment and surprisingly could be
+%D mostly finished the same evening. Of course it builds upon existing
+%D functionality. The main reason for writing it is that we occasionally
+%D run into pretty large tables that take tens of pages and need to be split
+%D into floats. Speed is one issue there, avoiding to use vsplit is another.
+%D
+%D \starttyping
+%D \definextable [tag] | [tag][parent]
+%D \setupxtable [settings] | [tag][settings]
+%D
+%D \startxtable[tag|settings]
+%D \startxtablehead|\startxtablenext|\startxtablebody|\startxtablefoot
+%D \startxrowgroup[tag|settings]
+%D \startxrow[settings]
+%D \startxcellgroup[tag|settings]
+%D \startxcell[settings] ... \stopxcell
+%D \stopxcellgroup
+%D \stopxrow
+%D \startxrowgroup
+%D \stopxtablehead|\stopxtablenext|\stopxtablebody|\stopxtablefoot
+%D \stopxtable
+%D \stoptyping
+%D
+%D See xtables-001.tex etc for some examples.
+
+% We can avoid some checking by using the fastoptionalcheckcs helpers
+% instead of dosingleempty but the speed gain is neglectable.
+
+\unprotect
+
+% \def\v!xtable{xtable}
+
+% option=stretch : equal distribution
+% option={stretch,width} : proportional distribution
+% option={max} : prefer max over forced width/height
+%
+% cells: option=fixed : nils autostretch (not yet complete)
+
+% \setbox\scratchbox\hbox attr \taggedattribute \attribute\taggedattribute {...}
+%
+% \let\tsplitbeforeresult\donothing
+% \let\tsplitafterresult \donothing
+% \let\tsplitinbetween \donothing
+% \let\tsplitbefore \donothing
+% \let\tsplitafter \donothing
+% \let\postprocesstsplit \donothing
+
+\let\dotagxtablecell \relax % names will change
+\let\dotagxtablesignal\relax % names will change
+
+\appendtoks
+ \def\dotagxtablecell {\taggedctxcommand{settagtablecell(\number\tablecellrows,\number\tablecellcolumns,\number\raggedstatus)}}%
+ \def\dotagxtablesignal{\char\zerocount}% not used
+\to \everyenableelements
+
+\newdimen\d_tabl_x_width
+\newdimen\d_tabl_x_height
+\newdimen\d_tabl_x_depth % not used
+\newdimen\d_tabl_x_distance
+\newcount\c_tabl_x_nx
+\newcount\c_tabl_x_ny
+\newcount\c_tabl_x_mode
+\newbox \b_tabl_x
+\newcount\c_tabl_x_state % 0=empty 1=content 3=splitleft
+\newdimen\d_tabl_x_final_width
+\newcount\c_tabl_x_nesting
+\newcount\c_tabl_x_skip_mode % 1 = skip
+
+% \setupxtable[one][parent][a=b,c=d]
+% \setupxtable[one] [a=b,c=d]
+% \setupxtable [a=b,c=d]
+
+\installcorenamespace{xtable}
+\installcorenamespace{xtablecheck}
+
+\installframedautocommandhandler \??xtable {xtable} \??xtable
+
+\appendtoks
+ \checkxtableparent % so we can deal with undefined settings, not that it's efficient
+\to \everysetupxtable
+
+\setupxtable[%
+ \c!nr=1,
+ \c!nc=1,
+ \c!nx=1, % slow
+ \c!ny=1, % slow
+ \c!align=\v!table, % {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE
+ \c!frameoffset=.5\linewidth,
+ \c!backgroundoffset=\v!frame,
+ % \c!framecolor=\s!black,
+ % \c!foregroundstyle=\xtableparameter\c!style, % not clean, better capture elsewhere
+ % \c!foregroundcolor=\xtableparameter\c!color, % not clean, better capture elsewhere
+ % \c!bodyfont=,
+ \c!width=\v!fit,
+ \c!height=\v!fit,
+ \c!maxwidth=8em,
+ \c!autowidth=\v!yes, % controls framed
+ \c!rulethickness=\linewidth,
+ \c!strut=\v!yes,
+ \c!autostrut=\v!no,
+ \c!split=\v!auto, % a number will take that many lines
+ \c!splitoffset=\zeropoint, % extra space taken
+ % \c!aligncharacter=\v!no,
+ % \c!alignmentcharacter={,},
+ % \c!option=, % \v!stretch {\v!stretch,\v!width}
+ % \c!footer=,
+ % \c!header=,
+ \c!spaceinbetween=,
+ \c!textwidth=\hsize,
+ \c!textheight=\vsize,
+ \c!distance=\zeropoint, % individual column
+ \c!columndistance=\zeropoint, % each column (whole table)
+ \c!leftmargindistance=\zeropoint, % whole table
+ \c!rightmargindistance=\zeropoint,% whole table
+]
+
+\unexpanded\def\startxtable
+ {\dosingleempty\tabl_x_start_table}
+
+\let\stopxtable\relax
+
+\def\tabl_x_default_buffer{x_table_\number\c_tabl_x_nesting}
+
+\unexpanded\def\tabl_x_start_table[#settings]% maybe two arguments: [tag][settings] | [tag] | [settings]
+ {\bgroup
+ \tabl_x_prepare{#settings}%
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \buff_pickup{\tabl_x_current_buffer}{startxtable}{stopxtable}\relax\tabl_x_process}
+
+\unexpanded\def\processxtablebuffer
+ {\dosingleempty\tabl_x_process_buffer_directly}
+
+% These direct buffers can be somewhat faster but it's probably neglectable.
+% Anyway, no nesting is supported as we then need to catch (e.g.) rows and
+% keep track of nesting and have a more complex redefinition of nested
+% instanced \unknown\ it's not worth the trouble.
+
+\def\tabl_x_process_buffer_directly[#name]%
+ {\bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{#name}%
+ \tabl_x_get_buffer % pickup settings
+ \tabl_x_process}
+
+\def\tabl_x_start_ignore[#settings]%
+ {}
+
+\def\tabl_x_process_buffer[#settings]%
+ {\tabl_x_prepare{#settings}%
+ \let\tabl_x_start_table\tabl_x_start_ignore
+ \gobbleuntil\stopxtable}
+
+%D A bonus: you can use the following construct inside a macro.
+
+\unexpanded\def\startembeddedxtable
+ {\dosingleempty\tabl_x_embedded_start}
+
+\def\tabl_x_embedded_start[#settings]#content\stopembeddedxtable
+ {\tabl_x_prepare{#settings}%
+ \ctxcommand{assignbuffer("embedded_x_table",\!!bs\detokenize{#content}\!!es)}%
+ \bgroup
+ \let\tabl_x_start_table\tabl_x_process_buffer
+ \edef\tabl_x_current_buffer{embedded_x_table}%
+ \tabl_x_process}
+
+\let\stopembeddedxtable\relax
+
+%D We can also define xtables.
+
+\appendtoks
+ \setuevalue{\e!start\currentxtable}{\tabl_x_start_named{\currentxtable}}%
+ \setuevalue{\e!stop \currentxtable}{\tabl_x_stop_named}%
+\to \everydefinextable
+
+\unexpanded\def\tabl_x_start_named#tag%
+ {\bgroup
+ \edef\currentxtable{#tag}%
+ \dosingleempty\tabl_x_start_named_indeed}
+
+\unexpanded\def\tabl_x_start_named_indeed[#settings]%
+ {\advance\c_tabl_x_nesting\plusone
+ \dostarttagged\t!table\empty
+ \forgetall
+ \iffirstargument
+ \setupcurrentxtable[#settings]%
+ \fi
+ \edef\tabl_x_current_buffer{\tabl_x_default_buffer}%
+ \normalexpanded{\buff_pickup{\tabl_x_current_buffer}{\e!start\currentxtable}{\e!stop\currentxtable}\relax\tabl_x_process}}
+
+\unexpanded\def\tabl_x_stop_named
+ {}
+
+%D Now we come to processing:
+
+\def\tabl_x_prepare#settings% assumes \iffirstargument to be set
+ {\advance\c_tabl_x_nesting\plusone
+ \dostarttagged\t!table\empty
+ \forgetall
+ \iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\def\tabl_x_get_buffer
+ {\ctxcommand{gettexbuffer("\tabl_x_current_buffer")}}
+
+\unexpanded\def\tabl_x_process
+ {\begingroup % *
+ \doifsomething{\xtableparameter\c!bodyfont}
+ {\setupbodyfont[\xtableparameter\c!bodyfont]}%
+ \setbox\scratchbox\vbox
+ {\xtableparameter\c!spaceinbetween}%
+ \ctxcommand{x_table_create {
+ option = "\xtableparameter\c!option",
+ textwidth = \number\dimexpr\xtableparameter\c!textwidth,
+ textheight = \number\dimexpr\xtableparameter\c!textheight,
+ maxwidth = \number\dimexpr\xtableparameter\c!maxwidth,
+ lineheight = \number\openlineheight,
+ columndistance = \number\dimexpr\xtableparameter\c!columndistance,
+ leftmargindistance = \number\dimexpr\xtableparameter\c!leftmargindistance,
+ rightmargindistance = \number\dimexpr\xtableparameter\c!rightmargindistance,
+ rowdistance = \number\ht\scratchbox,
+ header = "\xtableparameter\c!header",
+ footer = "\xtableparameter\c!footer",
+ } }%
+ %
+ \letxtableparameter\c!option\empty
+ % not so nice but needed as we use this in the setup
+ \linewidth\xtableparameter\c!rulethickness\relax
+ % so we freeze it
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_width_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_width_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_reflow_width
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_width_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_width_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_width
+ \settrialtypesetting
+ \tabl_x_get_buffer
+ \ctxcommand{x_table_reflow_width()}\relax
+ \endgroup
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_reflow_height_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_reflow_height_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_reflow_height
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_reflow_height_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_reflow_height_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_reflow_height
+ \settrialtypesetting
+ \tabl_x_get_buffer
+ \ctxcommand{x_table_reflow_height()}\relax
+ \endgroup
+ \begingroup
+ \let\tabl_x_start_row_yes \tabl_x_start_row_construct_yes
+ \let\tabl_x_start_row_nop \tabl_x_start_row_construct_nop
+ \let\tabl_x_stop_row \tabl_x_stop_row_construct
+ \let\tabl_x_start_cell_yes\tabl_x_start_cell_construct_yes
+ \let\tabl_x_start_cell_nop\tabl_x_start_cell_construct_nop
+ \let\tabl_x_stop_cell \tabl_x_stop_cell_construct
+ \tabl_x_get_buffer
+ \ctxcommand{x_table_construct()}\relax
+ \endgroup
+ \endgroup % *
+ \ifinsidesplitfloat
+ \tabl_x_flush_float_split
+ \else\ifinsidefloat
+ \tabl_x_flush_float_normal
+ \else
+ \doifelse{\xtableparameter\c!split}\v!yes
+ \tabl_x_flush_flow_split
+ \tabl_x_flush_flow_normal
+ \fi\fi
+ \ctxcommand{x_table_cleanup()}%
+ \dostoptagged
+ \resetbuffer[\tabl_x_current_buffer]%
+ \egroup}
+
+\let\extratxtablesplitheight\zeropoint % might disappear so don't depend on it
+
+\def\tabl_x_flush_float_normal
+ {\ctxcommand{x_table_flush{ method = "\v!normal" }}}
+
+\def\tabl_x_flush_float_split
+ {\resetdirecttsplit
+ \edef\extrasplitfloatlines {\xtableparameter\c!split}%
+ \edef\tsplitminimumfreespace{\the\dimexpr\extratxtablesplitheight+\xtableparameter\c!splitoffset\relax}%
+ % \edef\tsplitminimumfreelines{2}% not needed here as we're precise enough
+ \let\tsplitdirectsplitter\tabl_x_split_splitter
+ \let\tsplitdirectwidth \d_tabl_x_final_width
+ \handledirecttsplit}
+
+\def\tabl_x_flush_flow_normal
+ {\ctxcommand{x_table_flush{ method = "\v!normal" }}}
+
+\def\tabl_x_flush_flow_split
+ {\ctxcommand{x_table_flush{ method = "\v!split" }}}
+
+\def\tabl_x_split_splitter#vsize%
+ {\setbox\tsplitresult\vbox
+ {\ctxcommand{x_table_flush{ method = "\v!split", vsize = \number\dimexpr#vsize }}}%
+ \ifcase\c_tabl_x_state
+ \global\setfalse\somenextsplitofffloat
+ \else
+ \global\settrue \somenextsplitofffloat
+ \fi}
+
+\unexpanded\def\startxrow
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+\def\tabl_x_start_row_reflow_width_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \ctxcommand{x_table_next_row()}}
+
+\def\tabl_x_start_row_reflow_width_nop
+ {\ctxcommand{x_table_next_row()}}
+
+\def\tabl_x_stop_row_reflow_width
+ {}
+
+\let\tabl_x_start_row_reflow_height_yes\tabl_x_start_row_reflow_width_yes
+\let\tabl_x_start_row_reflow_height_nop\tabl_x_start_row_reflow_width_nop
+\let\tabl_x_stop_row_reflow_height \tabl_x_stop_row_reflow_width
+
+\def\tabl_x_start_row_construct_yes[#settings]%
+ {\setupcurrentxtable[#settings]%
+ \dostarttagged\t!tablerow\empty
+ \ctxcommand{x_table_next_row()}}
+
+\def\tabl_x_start_row_construct_nop
+ {\dostarttagged\t!tablerow\empty
+ \ctxcommand{x_table_next_row()}}
+
+\def\tabl_x_stop_row_construct
+ {\dostoptagged}
+
+\unexpanded\def\stopxrow
+ {\tabl_x_stop_row
+ \endgroup}
+
+\unexpanded\def\startxcell
+ {\doifnextoptionalelse\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\unexpanded\def\stopxcell
+ {\tabl_x_stop_cell}
+
+\def\tabl_x_begin_of_cell
+ {\inhibitblank
+ \everypar{\delayedbegstrut}}
+
+\def\tabl_x_end_of_cell
+ {\ifhmode
+ \delayedendstrut
+ \par
+ \else
+ \par
+ \ifdim\prevdepth<\zeropoint % =-1000pt ?
+ \vskip-\strutdp
+ \else
+ \removebottomthings
+ \fi
+ \fi}
+
+% For historic reasons we support both nx/nc and ny/nr : maybe nx/ny becomes
+% obsolete some day. The let as well as the direct speed things up a bit. We
+% could also consider a \defaultxtableparameter.
+%
+% \c_tabl_x_nx\defaultxtableparameter\c!nc{\defaultxtableparameter\c!nx\plusone}
+% \c_tabl_x_ny\defaultxtableparameter\c!nr{\defaultxtableparameter\c!ny\plusone}
+%
+% Although this becomes kind of messy. It saves already time that we only check
+% for it when we have settings.
+
+\def\tabl_x_set_hsize
+ {\hsize.25\maxdimen} % let's be reasonable
+
+\unexpanded\def\tabl_x_start_cell_reflow_width_yes[#settings]%
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!width \v!fit % overloads given width
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ %
+ \letxtableparameter\c!nx\plusone
+ \letxtableparameter\c!ny\plusone
+ \letxtableparameter\c!nc\plusone
+ \letxtableparameter\c!nr\plusone
+ %
+ \setupcurrentxtable[#settings]%
+ %
+ \c_tabl_x_nx\directxtableparameter\c!nc\relax
+ \c_tabl_x_ny\directxtableparameter\c!nr\relax
+ \ifnum\c_tabl_x_nx=\plusone
+ \c_tabl_x_nx\directxtableparameter\c!nx\relax
+ \fi
+ \ifnum\c_tabl_x_ny=\plusone
+ \c_tabl_x_ny\directxtableparameter\c!ny\relax
+ \fi
+ %
+ \d_tabl_x_distance\xtableparameter\c!distance\relax
+ \ctxcommand{x_table_init_reflow_width("\xtableparameter\c!option")}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\unexpanded\def\tabl_x_start_cell_reflow_width_nop
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!width \v!fit % overloads given width
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \c_tabl_x_nx\plusone
+ \c_tabl_x_ny\plusone
+ \d_tabl_x_distance\xtableparameter\c!distance\relax
+ \ctxcommand{x_table_init_reflow_width()}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \tabl_x_set_hsize}
+
+\unexpanded\def\tabl_x_stop_cell_reflow_width
+ {\tabl_x_end_of_cell
+ \egroup
+ \egroup
+ \ctxcommand{x_table_set_reflow_width()}}
+
+\unexpanded\def\tabl_x_start_cell_reflow_height_yes[#settings]%
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ctxcommand{x_table_init_reflow_height()}%
+ \ifcase\c_tabl_x_skip_mode % can be sped up
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \setupcurrentxtable[#settings]%
+ \relax
+ \letxtableparameter\c!width\d_tabl_x_width % overloads given width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \fi}
+
+\unexpanded\def\tabl_x_start_cell_reflow_height_nop
+ {\setbox\b_tabl_x\hbox\bgroup
+ \ctxcommand{x_table_init_reflow_height()}%
+ \ifcase\c_tabl_x_skip_mode % can be sped up
+ \ifnum\c_tabl_x_nesting>\plusone
+ \letxtableparameter\c!height\v!fit % overloads given height
+ \fi
+ \relax
+ \letxtableparameter\c!width\d_tabl_x_width % overloads given width
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \fi}
+
+\unexpanded\def\tabl_x_stop_cell_reflow_height
+ {\ifcase\c_tabl_x_skip_mode
+ \tabl_x_end_of_cell
+ \egroup
+ \fi
+ \egroup
+ \ctxcommand{x_table_set_reflow_height()}}
+
+\unexpanded\def\tabl_x_start_cell_construct_yes[#settings]%
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hbox\bgroup
+ \setupcurrentxtable[#settings]%
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height
+ \ctxcommand{x_table_init_construct()}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\unexpanded\def\tabl_x_start_cell_construct_nop
+ {\dostarttagged\t!tablecell\empty % can't we just tag the box
+ \setbox\b_tabl_x\hbox\bgroup
+ \letxtableparameter\c!width \d_tabl_x_width % overloads given width
+ \letxtableparameter\c!height\d_tabl_x_height % overloads given height
+ \ctxcommand{x_table_init_construct()}%
+ \inheritedxtableframed\bgroup
+ \tabl_x_begin_of_cell
+ \dotagxtablecell}
+
+\unexpanded\def\tabl_x_stop_cell_construct
+ {\tabl_x_end_of_cell
+ \egroup
+ \dotagxtablesignal % harmless spot
+ \egroup
+ \ctxcommand{x_table_set_construct()}%
+ \dostoptagged}
+
+\unexpanded\def\startxcellgroup
+ {\begingroup
+ \dosingleempty\tabl_x_start_cell_group}
+
+\unexpanded\def\stopxcellgroup
+ {\endgroup}
+
+\unexpanded\def\tabl_x_start_cell_group[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\unexpanded\def\startxrowgroup
+ {\begingroup
+ \dosingleempty\tabl_x_start_row_group}
+
+\unexpanded\def\stopxrowgroup
+ {\dostoptagged
+ \endgroup}
+
+\unexpanded\def\tabl_x_start_row_group[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+% \def\tabl_x_set_checked#settings
+% {\doifassignmentelse{#settings}
+% {\setupcurrentxtable[#settings]}
+% {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
+% \edef\currentxtable{#settings}%
+% \fi}}
+
+\unexpanded\def\tabl_x_set_checked#settings%
+ {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
+ \edef\currentxtable{#settings}%
+ \else
+ \setupcurrentxtable[#settings]%
+ \fi}
+
+\unexpanded\def\startxtablehead{\begingroup\c_tabl_x_mode\plusone \dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablefoot{\begingroup\c_tabl_x_mode\plustwo \dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablenext{\begingroup\c_tabl_x_mode\plusthree\dosingleempty\tabl_x_start_partition}
+\unexpanded\def\startxtablebody{\begingroup\c_tabl_x_mode\plusfour \dosingleempty\tabl_x_start_partition}
+
+\unexpanded\def\tabl_x_start_partition[#settings]%
+ {\iffirstargument
+ \tabl_x_set_checked{#settings}%
+ \fi}
+
+\unexpanded\def\tabl_x_stop_partition
+ {\endgroup}
+
+\let\stopxtablehead\tabl_x_stop_partition
+\let\stopxtablefoot\tabl_x_stop_partition
+\let\stopxtablenext\tabl_x_stop_partition
+\let\stopxtablebody\tabl_x_stop_partition
+
+%D This is an experiment! Beware: you can create loops by using nested
+%D references to already chained settings.
+%D
+%D \startbuffer
+%D \setupxtable[suffix][align=middle,foregroundcolor=red]
+%D \setupxtable[blabla][foregroundstyle=slanted]
+%D \setupxtable[crap] [foregroundcolor=blue]
+%D \setupxtable[bold] [crap][foregroundstyle=bold]
+%D
+%D \startxtable[frame=off]
+%D \startxtablehead
+%D \startxrow[bold]
+%D \startxcell[suffix] a 0 \stopxcell
+%D \startxcell[blabla] a 1 \stopxcell
+%D \startxcell a 2 \stopxcell
+%D \stopxrow
+%D \stopxtablehead
+%D \startxtablebody
+%D \startxrow \startxcell[suffix][ny=2] a 1 \stopxcell \startxcell b 1 \stopxcell \startxcell c 1 \stopxcell \stopxrow
+%D \startxrow \startxcell b 2 \stopxcell \startxcell c 2 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 3 \stopxcell \startxcell b 3 \stopxcell \startxcell c 3 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 4 \stopxcell \startxcell b 4 \stopxcell \startxcell c 4 \stopxcell \stopxrow
+%D \startxrow \startxcell[suffix] a 5 \stopxcell \startxcell b 5 \stopxcell \startxcell c 5 \stopxcell \stopxrow
+%D \stopxtablebody
+%D \stopxtable
+%D \stopbuffer
+%D
+%D \typebuffer \placetable{}{\getbuffer}
+
+\appendtoks
+ \letvalue{\??xtablecheck\currentxtable}\relax % faster than checking parent
+\to \everysetupxtable
+
+% groups
+
+\unexpanded\def\startxgroup
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_group_delayed_one\relax}
+
+\unexpanded\def\stopxgroup
+ {\endgroup}
+
+\def\tabl_x_start_group_delayed_one[#tag]%
+% {\ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+ {\ifcsname\??xtablecheck#tag\endcsname
+ \expandafter\tabl_x_start_group_delayed_two
+ \else
+ \expandafter\setupcurrentxtable
+ \fi[#tag]}
+
+\def\tabl_x_start_group_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifnextoptionalelse\setupcurrentxtable\relax}
+
+\let\startxrowgroup \startxgroup
+\let\stopxrowgroup \stopxgroup
+\let\startxcellgroup\startxgroup
+\let\stopxcellgroup \stopxgroup
+
+% cells (maybe also check for 1 etc but it becomes messy)
+
+\unexpanded\def\startxcell
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_cell_delayed_one\tabl_x_start_cell_nop}
+
+\def\tabl_x_start_cell_delayed_one[#tag]%
+% {\ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+ {\ifcsname\??xtablecheck#tag\endcsname
+ \expandafter\tabl_x_start_cell_delayed_two
+ \else
+ \expandafter\tabl_x_start_cell_yes
+ \fi[#tag]}
+
+\def\tabl_x_start_cell_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifnextoptionalelse\tabl_x_start_cell_yes\tabl_x_start_cell_nop}
+
+\unexpanded\def\stopxcell
+ {\tabl_x_stop_cell
+ \endgroup}
+
+% rows
+
+\unexpanded\def\startxrow
+ {\begingroup
+ \doifnextoptionalelse\tabl_x_start_row_delayed_one\tabl_x_start_row_nop}
+
+\def\tabl_x_start_row_delayed_one[#tag]%
+% {\ifcsname\namedxtablehash{#tag}\s!parent\endcsname
+ {\ifcsname\??xtablecheck#tag\endcsname
+ \expandafter\tabl_x_start_row_delayed_two
+ \else
+ \expandafter\tabl_x_start_row_yes
+ \fi[#tag]}
+
+\def\tabl_x_start_row_delayed_two[#tag]%
+ {\ifx\currentxtable\empty \else
+ \chaintocurrentxtable{#tag}%
+ \fi
+ \edef\currentxtable{#tag}%
+ \doifnextoptionalelse\tabl_x_start_row_yes\tabl_x_start_row_nop}
+
+\unexpanded\def\stopxrow
+ {\tabl_x_stop_row
+ \endgroup}
+
+\protect \endinput