tabl-tbl.mkiv /size: 104 Kb    last modification: 2025-02-21 11:03
1%D \module
2%D   [       file=core-tbl,
3%D        version=1998.11.03,
4%D          title=\CONTEXT\ Table Macros,
5%D       subtitle=Text Flow Tabulation,
6%D         author=Hans Hagen,
7%D           date=\currentdate,
8%D      copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9%C
10%C This module is part of the \CONTEXT\ macro||package and is
11%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
12%C details.
13
14\writestatus{loading}{ConTeXt Table Macros / Tabulation}
15
16\unprotect
17
18\registerctxluafile{tabl-tbl}{} % experiment
19
20%D I can probably reimplement this using a \LUATEX\ combination but it does not pay
21%D of in development time. If I need something else I will write it from scratch
22%D anyway. This module looks a bit complex which is a consequence of it dealing with
23%D paragraphs being split over pages and that there are several passes over the data
24%D set. We can probably do some cleanup (combine/split).
25%D
26%D Caching the preamble does not save much (compared to other bits and pieces of
27%D \CONTEXT). There are not that many ways to deal with preambles and this is just
28%D one of them. The keys are somewhat similar to those of the \TABLE\ package.
29
30% |p2|p3| 2:3 -> spanning (maybe)
31%
32% In-text tabbing environment
33%
34% \starttabulate[| separated template] % eg [|l|p|] or [|l|p|p|]
35%   \NC ... \NC ... \NC\NR
36% \stoptabulate
37%
38% with: two pass auto width calculation when no p-width
39% specified, even with multiple p's, see examples.
40%
41%  TaBlE compatible specifications:
42%
43%  l  align column/paragraph left
44%  r  align column/paragraph right
45%  c  align column/paragraph center
46%  p  p(dimen) of automatisch als alleen p
47%  w  column width
48%  f  font#1
49%  A  {alignmentoptions}
50%  B  bold
51%  I  italic
52%  S  slanted
53%  T  type
54%  R  roman
55%  m  math
56%  M  display math
57%  h  hook (inner level or par lines)
58%  b  before (may be command#1)
59%  a  after
60%  i  i<n> skip left of column
61%  j  i<n> skip right of column
62%  k  i<n> skip around column
63%  d  digits (~)
64%
65%  C  [LMRT] {color} % T is text color
66%
67%  |  {color,n}
68%
69%  s  setups
70%
71%  g  g{char} align at char
72%  .  align at .
73%  ,  align at ,
74%
75%  Still to be done
76%
77%  N      math numbers (best hook into existing digits mechanism)
78%  n      numbers (best hook into existing digits mechanism)
79%  Q      math numbers (best hook into existing digits mechanism)
80%  q      numbers (best hook into existing digits mechanism)
81%  ~      \hskip.5em
82%  |      check
83%
84%  nesting
85%
86%  10     evt auto stack; dan wel andere signal dan void nodig
87%
88%  present but not yet 100% ok
89%
90%  \TL [width,color]   bottom hrule
91%  \FL [width,color]   first hrule
92%  \ML [width,color]   mid hrule (with auto split)
93%  \LL [width,color]   bottom hrule
94%  \BL [width,color]   last hrule
95%
96%  \HL [width,color]   top rule
97%  \VL [width,color]
98%
99%  \CC \CL \CM \CR color
100%
101%  \EQ \RQ \HQ     equal  (raw, hook)
102%  \NC \RC \HC     normal (raw, hook)
103%
104%  \NR  checked break
105%  \NB  no break
106%
107%  \HR : rule with lineheight
108%
109%  \autotabulaterule : with lineheight, not first/last
110%  \autotabulateline : spaced, not first/last
111%  \tabulaterule     : with lineheight
112%  \tabulateline     : spaced
113%
114% tricky: align scans ahead, over # and expands ones before
115% while doing
116%
117% new:
118%
119% \starttabulate[|cg{.}|cg{,}|cg{,}|]
120% \NC period     \NC comma      \NC comma   \NC\NR
121% \NG 100.000,00 \NG 100.000,00 \NG 100,00  \NC\NR
122% \NG 10.000,00  \NG 10.000,00  \NG 1000,00 \NC\NR
123% \NG 100,00     \NG 100,00     \NG 10,00   \NC\NR
124% \NG 10         \NG 10         \NG 0,00    \NC\NR
125% \stoptabulate
126%
127% \starttabulate[|c.|c,|c,|]
128% \NC period     \NC comma      \NC comma   \NC\NR
129% \NG 100.000,00 \NG 100.000,00 \NG 100,00  \NC\NR
130% \NG 10.000,00  \NG 10.000,00  \NG 1000,00 \NC\NR
131% \NG 100,00     \NG 100,00     \NG 10,00   \NC\NR
132% \NG 10         \NG 10         \NG 0,00    \NC\NR
133% \stoptabulate
134
135% nice demo (for BG)
136%
137% \starttabulate[|r|b{$\star$}|ra{\percent}|b{=}|r|]
138% \NC 500 \NC \NC 60 \NC \NC 300 \NC \NR
139% \NC 500 \NC \NC 55 \NC \NC 275 \NC \NR
140% \NC 500 \NC \NC 50 \NC \NC 250 \NC \NR
141% \NC 500 \NC \NC 45 \NC \NC 225 \NC \NR
142% \NC 500 \NC \NC 40 \NC \NC 200 \NC \NR
143% \NC 500 \NC \NC 35 \NC \NC 175 \NC \NR
144% \NC 500 \NC \NC 30 \NC \NC 150 \NC \NR
145% \NC 500 \NC \NC 25 \NC \NC 125 \NC \NR
146% \NC 500 \NC \NC 20 \NC \NC 100 \NC \NR
147% \stoptabulate
148
149\newtoks         \t_tabl_tabulate_preamble
150\newtoks         \t_tabl_tabulate_before
151\newtoks         \t_tabl_tabulate_after
152\newtoks         \t_tabl_tabulate_bmath
153\newtoks         \t_tabl_tabulate_emath
154\newtoks         \t_tabl_tabulate_font
155\newtoks         \t_tabl_tabulate_settings
156\newtoks         \t_tabl_tabulate_dummy
157\newtoks         \t_tabl_tabulate_every_row
158\newtoks         \t_tabl_tabulate_every_after_row
159\newtoks         \t_tabl_tabulate_every_real_row
160
161\newtoks         \t_tabl_tabulate_initializers_first
162\newtoks         \t_tabl_tabulate_initializers_second
163
164\newcount        \c_tabl_tabulate_nofauto
165\newcount        \c_tabl_tabulate_columns
166\newcount        \c_tabl_tabulate_column
167\newcount        \c_tabl_tabulate_plines_min
168\newcount        \c_tabl_tabulate_plines_max
169\newcount        \c_tabl_tabulate_max_colorcolumn
170\newcount        \c_tabl_tabulate_max_vrulecolumn
171\newcount        \c_tabl_tabulate_repeathead
172\newcount        \c_tabl_tabulate_noflines
173\newcount        \c_tabl_tabulate_totalnoflines
174\newcount        \c_tabl_tabulate_minusnoflines
175\newcount        \c_tabl_tabulate_align
176\newcount        \c_tabl_tabulate_nofrealrows
177\newcount        \c_tabl_tabulate_autocolor
178
179\newcount        \c_tabl_tabulate_nofcolumns            % set at the lua end by parser
180\newcount        \c_tabl_tabulate_has_rule_spec_first   % set at the lua end by parser (for the moment a count)
181\newcount        \c_tabl_tabulate_has_rule_spec_last    % set at the lua end by parser (for the moment a count)
182
183\newconditional  \c_tabl_tabulate_nopbreak
184\newconditional  \c_tabl_tabulate_firstflushed
185\newconditional  \c_tabl_tabulate_equal
186\newconditional  \c_tabl_tabulate_split             \settrue\c_tabl_tabulate_split
187\newconditional  \c_tabl_tabulate_automode
188\newconditional  \c_tabl_tabulate_handlepbreak      \settrue\c_tabl_tabulate_handlepbreak
189\newconditional  \c_tabl_tabulate_autorulespacing   \settrue\c_tabl_tabulate_autorulespacing
190\newconditional  \c_tabl_tabulate_someamble
191\newconditional  \c_tabl_tabulate_tolerant_break
192\newconditional  \c_tabl_tabulate_splitoff_whitespace
193\newconditional  \c_tabl_tabulate_pwidth_set
194\newconditional  \c_tabl_tabulate_reshape
195
196\newdimen        \d_tabl_tabulate_width_p
197\newdimen        \d_tabl_tabulate_width_w
198\newdimen        \d_tabl_tabulate_width
199\newdimen        \d_tabl_tabulate_unit
200\newdimen        \d_tabl_tabulate_height_p_max
201\newdimen        \d_tabl_tabulate_vrulethickness_default
202\newdimen        \d_tabl_tabulate_hrulethickness_default
203\newdimen        \d_tabl_tabulate_vrulethickness
204\newdimen        \d_tabl_tabulate_hrulethickness          % not used
205\newdimen        \d_tabl_tabulate_vrulethickness_local
206\newdimen        \d_tabl_tabulate_hrulethickness_local
207\newdimen        \d_tabl_tabulate_indent
208\newdimen        \d_tabl_tabulate_splitoff_betweenskip
209\newdimen        \d_tabl_tabulate_margin
210
211\newskip         \s_tabl_tabulate_pre
212\newskip         \s_tabl_tabulate_post
213\newskip         \s_tabl_tabulate_first
214\newskip         \s_tabl_tabulate_last
215\newskip         \s_tabl_tabulate_separator
216
217\newbox          \b_tabl_tabulate
218
219\newconstant     \c_tabl_tabulate_pass
220\newconstant     \c_tabl_tabulate_type
221\newconstant     \c_tabl_tabulate_kind % 1=strong  2=equals
222\newconstant     \c_tabl_tabulate_splitlinemode  \c_tabl_tabulate_splitlinemode\plusone
223\newconstant     \c_tabl_tabulate_colorspan
224\newconstant     \c_tabl_tabulate_localcolorspan
225\newconstant     \c_tabl_tabulate_modus
226
227%newconditional  \c_tabl_pre_is_set
228\newconditional  \c_tabl_post_is_set
229
230\let\tabulatesplitlinemode\c_tabl_tabulate_splitlinemode % temp hack, we need an interface
231
232\let             \m_tabl_tabulate_separator_factor \empty % fraction
233
234\newtoks         \everytabulatepar           % where used ?
235\newtoks         \everytabulate              % public ?
236
237\unexpanded\def\tolerantTABLEbreaktrue   {\settrue \c_tabl_tabulate_tolerant_break} % used in styles !
238\unexpanded\def\handletabulatepbreakfalse{\setfalse\c_tabl_tabulate_handlepbreak  } % depricated
239
240\def\noftabulaterows{\number\c_tabl_tabulate_noflines} % handy for testing if a table is empty
241
242\installcorenamespace{tabulatebox}
243\installcorenamespace{tabulatesetup}
244\installcorenamespace{tabulatehook}
245\installcorenamespace{tabulatesplit}
246\installcorenamespace{tabulateseparator}
247\installcorenamespace{tabulatecolor}
248\installcorenamespace{tabulateheader}
249\installcorenamespace{tabulatealigning}
250\installcorenamespace{tabulatepreamble}
251\installcorenamespace{tabulatevrule}
252
253\installcorenamespace{tabulatehead}
254\installcorenamespace{tabulatefoot}
255\installcorenamespace{tabulatenext}
256
257\prependtoks
258    \global\c_tabl_tabulate_nofrealrows\zerocount
259\to \t_tabl_tabulate_initializers_first
260
261\prependtoks
262    \global\c_tabl_tabulate_nofrealrows\zerocount
263\to \t_tabl_tabulate_initializers_second
264
265\prependtoks
266   \global\advance\c_tabl_tabulate_nofrealrows\plusone
267\to \t_tabl_tabulate_every_real_row
268
269\def\b_tabl_tabulate_current#1%
270  {\csname\??tabulatebox\number#1\endcsname} % beware, a synonym
271
272\def\tabl_tabulate_initialize_boxes#1%
273  {\scratchcounter#1\relax
274   \tabl_tabulate_initialize_boxes_step}
275
276\def\tabl_tabulate_initialize_boxes_step
277  {\ifnum\scratchcounter>\zerocount
278     \tabl_tabulate_initialize_box\scratchcounter
279     \advance\scratchcounter\minusone
280     \expandafter\tabl_tabulate_initialize_boxes_step
281   \fi}
282
283\def\tabl_tabulate_initialize_box#1% also used elsewhere
284  {\ifcsname\??tabulatebox\number#1\endcsname
285     \tabl_tabulate_initialize_box_yes
286   \else
287     \tabl_tabulate_initialize_box_nop#1%
288   \fi}
289
290\def\tabl_tabulate_initialize_box_yes  {\global     \setbox\lastnamedcs\emptybox}
291\def\tabl_tabulate_initialize_box_nop#1{\expandafter\newbox\csname\??tabulatebox\number#1\endcsname}
292
293\tabl_tabulate_initialize_boxes{16} % not really needed
294
295\let\initializetablebox  \tabl_tabulate_initialize_box   % used elsewhere, will change
296\let\initializetableboxes\tabl_tabulate_initialize_boxes % used elsewhere, will change
297\let\tablebox            \b_tabl_tabulate_current
298
299% 0 = NC column next   EQ equal column
300% 1 = RC column raw    RQ equal column raw
301% 2 = HC column hook   HQ equal column hook
302
303% handy helper
304
305\def\tabulatenoalign % public ?
306  {\noalign
307   \bgroup
308   \let\noalign\relax
309   \let\tabulatenoalign\relax
310   \let\next=}
311
312\def\starttabulatenoalign % public ?
313  {\tabulatenoalign\bgroup}
314
315\let\stoptabulatenoalign\egroup
316
317% [|lg{.}|] => \NG 12.34 \NC
318
319\def\tabl_tabulate_nobreak_inject_tracer
320  {\red % maybe use the fast color switcher here
321   \hrule\s!height.5\linewidth\s!depth.5\linewidth
322   \par
323   \kern-\linewidth
324   \tabl_tabulate_break_no}
325
326\installtextracker
327  {tables.tabulate.breaks}
328  {\let\tabl_tabulate_break_no_tracer\tabl_tabulate_nobreak_inject_tracer}
329  {\let\tabl_tabulate_break_no_tracer\donothing}
330
331\let\tabl_tabulate_break_no_tracer\donothing
332
333\def\tabl_tabulate_nobreak_inject_indeed
334  {\tabl_tabulate_break_no
335   \tabl_tabulate_break_no_tracer}
336
337\def\tabl_tabulate_nobreak_inject
338  {\tabulatenoalign{\tabl_tabulate_nobreak_inject_indeed}}
339
340\unexpanded\def\tabl_tabulate_hook_check
341  {\ifnum\c_tabl_tabulate_type<\plustwo
342     \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
343   \else
344     \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
345   \fi}
346
347\unexpanded\def\tabl_tabulate_setups_check
348  {\begincsname\??tabulatesetup\the\c_tabl_tabulate_column\endcsname}
349
350\unexpanded\def\tabl_tabulate_entry_before{\ignorespaces\tabl_tabulate_hook}
351\unexpanded\def\tabl_tabulate_entry_after {\unskip\unskip\ifmmode\else\endgraf\fi}
352
353\unexpanded\def\tabl_tabulate_shaped_par_begin
354  {\dowithnextboxcs\tabl_tabulate_shaped_par_finish\vbox\bgroup}
355
356\def\tabl_tabulate_shaped_par_finish
357  {\clf_doreshapeframedbox\nextbox\relax
358   \ifvmode\unvbox\else\box\fi\nextbox}
359
360\let\tabl_tabulate_shaped_par_end\egroup
361
362\ifdefined\dotagtabulatecell   \else \let\dotagtabulatecell  \relax \fi
363\ifdefined\dotagtabulatesignal \else \let\dotagtabulatesignal\relax \fi
364
365\unexpanded\def\tabl_tabulate_check_local_color_first#1#2%
366  {\relax}
367
368\unexpanded\def\tabl_tabulate_check_local_color_second#1#2%
369  {\relax
370   \ifx\m_tabl_tabulate_color_local\empty
371     \xdef\m_tabl_tabulate_color{#1}%
372   \else
373     \glet\m_tabl_tabulate_color\m_tabl_tabulate_color_local
374     \glet\m_tabl_tabulate_color_local\empty
375   \fi
376   \ifcase\c_tabl_tabulate_localcolorspan
377     \global\c_tabl_tabulate_colorspan#2\relax
378   \else
379     \global\c_tabl_tabulate_colorspan\c_tabl_tabulate_localcolorspan
380     \global\c_tabl_tabulate_localcolorspan\zerocount
381   \fi}
382
383\unexpanded\def\tabl_tabulate_check_local_vrule_thickness#1%
384  {\relax
385   \ifcase\d_tabl_tabulate_vrulethickness_local
386     \global\d_tabl_tabulate_vrulethickness#1\relax
387   \else
388     \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_local
389     \global\d_tabl_tabulate_vrulethickness_local\zeropoint
390   \fi}
391
392\unexpanded\def\tabl_tabulate_check_local_vrule_color_first#1%
393  {\relax}
394
395\unexpanded\def\tabl_tabulate_check_local_vrule_color_second#1%
396  {\relax
397   \ifx\m_tabl_tabulate_vrule_color_local\empty
398     \xdef\m_tabl_tabulate_vrule_color{#1}%
399   \else
400     \glet\m_tabl_tabulate_vrule_color\m_tabl_tabulate_vrule_color_local
401     \glet\m_tabl_tabulate_vrule_color_local\empty
402   \fi}
403
404\let\tabl_tabulate_check_local_color      \gobbletwoarguments
405\let\tabl_tabulate_check_local_vrule_color\gobbleoneargument
406
407\appendtoks
408    \let\tabl_tabulate_check_local_color      \tabl_tabulate_check_local_color_first
409    \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_first
410\to \t_tabl_tabulate_initializers_first
411
412\appendtoks
413    \let\tabl_tabulate_check_local_color      \tabl_tabulate_check_local_color_second
414    \let\tabl_tabulate_check_local_vrule_color\tabl_tabulate_check_local_vrule_color_second
415\to \t_tabl_tabulate_initializers_second
416
417% \unexpanded % we can expand this one
418\def\tabl_tabulate_inject_pre_skip#1%
419  {\ifdim#1>\zeropoint
420     \kern#1\relax % was \hskip
421   \else\ifnum\c_tabl_tabulate_column=\zerocount
422     \ifconditional\c_tabl_tabulate_autorulespacing
423       \ifcase\c_tabl_tabulate_has_rule_spec_first\else
424         \kern\s_tabl_tabulate_first\relax % was \hskip
425       \fi
426     \fi
427   \fi\fi}
428
429% \unexpanded % we can expand this one
430\def\tabl_tabulate_inject_post_skip#1#2%
431  {\ifdim#1>\zeropoint
432     \kern\ifnum\c_tabl_tabulate_columns=\c_tabl_tabulate_nofcolumns#2\else#1\fi\relax
433   \else\ifnum\c_tabl_tabulate_columns=\c_tabl_tabulate_nofcolumns
434     \ifconditional\c_tabl_tabulate_autorulespacing
435       \ifcase\c_tabl_tabulate_has_rule_spec_last\else
436         \kern\s_tabl_tabulate_last\relax % was \hskip
437       \fi
438     \fi
439   \fi\fi}
440
441\let\tabl_tabulate_hook_b\donothing
442\let\tabl_tabulate_hook_e\donothing
443
444\let\tabl_tabulate_hook_g\donothing
445
446\def\tabl_tabulate_set_preamble_step#1#2% only makes sense for many tabulates
447  {\etoksapp\t_tabl_tabulate_preamble{%
448        \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
449        \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
450        \tabl_tabulate_check_local_color\constantemptyargument\m_tabl_tabulate_color\constantnumberargument\c_tabl_tabulate_colorspan
451        \tabl_tabulate_color_side_right
452        \aligntab
453        \tabl_tabulate_column_vrule_inject
454        \tabl_tabulate_color_side_left
455        \tabl_tabulate_inject_pre_skip{\the\dimexpr\s_tabl_tabulate_pre}% get rid of plus
456        \alignmark\alignmark
457        \aligntab
458        \tabl_tabulate_color_side_both
459        \global\c_tabl_tabulate_colorspan\zerocount
460        \global\c_tabl_tabulate_column\constantnumber\c_tabl_tabulate_columns
461        \tabl_tabulate_hook_g
462        \tabl_tabulate_setups_check % unexpandable
463        \tabl_tabulate_hook_check   % unexpandable
464        \ifzeropt\d_tabl_tabulate_width
465            \ifcase\c_tabl_tabulate_modus\else
466               \settrue\c_tabl_tabulate_automode
467            \fi
468        \else
469            \ifcase\c_tabl_tabulate_modus
470                \hbox to
471            \else
472                \hsize
473            \fi
474            \the\d_tabl_tabulate_width
475        \fi
476        \bgroup
477            \tabl_tabulate_bbskip
478            \bgroup % we cannot combine the if because a cell may have only one ##
479                \tabl_tabulate_hook_b
480                \c_tabl_tabulate_align\constantnumber\c_tabl_tabulate_align % needed in tag passing
481                \ifx\m_tabl_tabulate_alignment\empty \else
482                    \spac_align_use_now{\m_tabl_tabulate_alignment}%
483                \fi
484                \noexpand\dostarttagged\noexpand\t!tabulatecell\noexpand\empty
485                \noexpand\dotagtabulatecell
486                \noexpand#1%
487                \ifconditional\c_tabl_tabulate_reshape
488                    \tabl_tabulate_shaped_par_begin
489                \fi
490                \dotagtabulatesignal  % empty cells .. todo (can be removed as soon as build)
491                \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
492                    \the\t_tabl_tabulate_bmath % maybe later? can interfere with char 0
493                    \the\t_tabl_tabulate_font
494                    \the\t_tabl_tabulate_settings
495                    \the\t_tabl_tabulate_before
496                    \ifx\m_tabl_tabulate_text_color\empty
497                        \expandafter\gobbleoneargument
498                    \else
499                        \expandafter\dofastcoloractivation
500                    \fi\m_tabl_tabulate_text_color
501                \noexpand\fi
502                % grouping needs to be outside macros (or expandable), nice test
503                % example \NC \string \aligntab \NC which will fail otherwise (mk)
504                \bgroup
505                \tabl_tabulate_entry_before
506                \alignmark\alignmark
507                \tabl_tabulate_entry_after
508                \egroup
509                \noexpand\ifnum\noexpand\c_tabl_tabulate_type=\plusone\noexpand\else
510                    \the\t_tabl_tabulate_after
511                    \the\t_tabl_tabulate_emath
512                \noexpand\fi
513                \ifconditional\c_tabl_tabulate_reshape
514                    \tabl_tabulate_shaped_par_end
515                \fi
516                \noexpand#2%
517                \tabl_tabulate_hook_e
518            \egroup
519        \egroup
520        \aligntab
521        \noexpand\dostoptagged
522        \tabl_tabulate_inject_post_skip
523          {\the\ifconditional\c_tabl_post_is_set\s_tabl_tabulate_post\else\s_tabl_tabulate_last\fi}%
524          {\the\s_tabl_tabulate_post}%
525        \alignmark\alignmark
526   }%
527   \toksapp\t_tabl_tabulate_dummy{\NC}%
528   \s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\relax
529   \ifnum\c_tabl_tabulate_columns<\numexpr\c_tabl_tabulate_nofcolumns-\plusone\relax
530     \s_tabl_tabulate_post\s_tabl_tabulate_pre
531   \else
532     \s_tabl_tabulate_post\zeropoint
533   \fi
534  %\let\gettabulateexit\dogettabulateexit % still needed ?
535   \d_tabl_tabulate_width\zeropoint
536   %setfalse\c_tabl_pre_is_set
537   \setfalse\c_tabl_post_is_set}
538
539\unexpanded\def\installtabulatepreambleoption#1#2%
540  {\setvalue{\??tabulatepreamble\string#1}{#2}}%
541
542\installtabulatepreambleoption{x}{\c_tabl_tabulate_align\zerocount
543                                  \tabl_tabulate_set_preamble} % internal
544\installtabulatepreambleoption{l}{\c_tabl_tabulate_align\plusone
545                                  \tabl_tabulate_set_preamble}
546\installtabulatepreambleoption{r}{\c_tabl_tabulate_align\plustwo
547                                  \tabl_tabulate_set_preamble}
548\installtabulatepreambleoption{c}{\c_tabl_tabulate_align\plusthree
549                                  \tabl_tabulate_set_preamble}
550\installtabulatepreambleoption{p}{\tabl_tabulate_set_paragraph}
551\installtabulatepreambleoption{s}{\tabl_tabulate_set_setups}
552\installtabulatepreambleoption{w}{\tabl_tabulate_set_width}
553\installtabulatepreambleoption{f}{\tabl_tabulate_set_font}
554\installtabulatepreambleoption{B}{\t_tabl_tabulate_font{\bf}%
555                                  \tabl_tabulate_set_preamble}
556\installtabulatepreambleoption{I}{\t_tabl_tabulate_font{\it}%
557                                  \tabl_tabulate_set_preamble}
558\installtabulatepreambleoption{S}{\t_tabl_tabulate_font{\sl}%
559                                  \tabl_tabulate_set_preamble}
560\installtabulatepreambleoption{T}{\t_tabl_tabulate_font{\tt}%
561                                  \tabl_tabulate_set_preamble}
562\installtabulatepreambleoption{R}{\t_tabl_tabulate_font{\rm}%
563                                  \tabl_tabulate_set_preamble}
564\installtabulatepreambleoption{m}{\t_tabl_tabulate_bmath{\normalstartimath}%
565                                  \t_tabl_tabulate_emath{\normalstopimath}%
566                                  \tabl_tabulate_set_preamble}
567\installtabulatepreambleoption{M}{\t_tabl_tabulate_bmath{\normalstartimath\displaystyle}%
568                                  \t_tabl_tabulate_emath{\normalstopimath}%
569                                  \tabl_tabulate_set_preamble}
570\installtabulatepreambleoption{h}{\tabl_tabulate_set_hook}
571\installtabulatepreambleoption{b}{\tabl_tabulate_set_before}
572\installtabulatepreambleoption{a}{\tabl_tabulate_set_after}
573\installtabulatepreambleoption{i}{\tabl_tabulate_set_preskip}
574\installtabulatepreambleoption{j}{\tabl_tabulate_set_posskip}
575\installtabulatepreambleoption{k}{\tabl_tabulate_set_preposskip}
576\installtabulatepreambleoption{e}{\toksapp\t_tabl_tabulate_settings{\global\settrue\c_tabl_tabulate_equal}%
577                                  \tabl_tabulate_set_preamble}
578\installtabulatepreambleoption{g}{\tabl_tabulate_set_align}
579\installtabulatepreambleoption{.}{\tabl_tabulate_set_align.}
580\installtabulatepreambleoption{,}{\tabl_tabulate_set_align,}
581\installtabulatepreambleoption{C}{\tabl_tabulate_set_color_span}
582\installtabulatepreambleoption{d}{\toksapp\t_tabl_tabulate_settings{\fixedspaces}%
583                                  \tabl_tabulate_set_preamble}
584\installtabulatepreambleoption{ }{\tabl_tabulate_set_preamble}
585\installtabulatepreambleoption{A}{\tabl_tabulate_set_alignment}
586
587%D We no longer deal with \type {~} here but map it onto \type {d} instead. Of
588%D course we could prefix a key with \type {\meaning} instead, which works ok (and
589%D is needed in order to pseudo expand \type {\next}, but is ugly at the same time.
590%D The type {d} stands for digitspace.
591
592%D \starttyping
593%D \installtabulatepreambleoption{~}{...} % see 'd'
594%D \stoptyping
595%D
596%D Also, as there is always a key, we no longer do some after assigment or future
597%D let but just pick up the key.
598
599% \installtabulatepreambleoption \s!unknown %
600%   {\writestatus{tabulate}{unknown preamble key [\normalmeaning\next]}%
601%    \tabl_tabulate_set_preamble}
602%
603% \def\tabl_tabulate_set_preamble
604%   {\afterassignment\dosettabulatepreamble\let\next=}
605%
606% \def\dosettabulatepreamble
607%   {\ifx\next\relax \else
608%      \csname\??tabulatepreamble
609%        \ifcsname\??tabulatepreamble\next\endcsname\next\else\s!unknown\fi
610%      \expandafter\endcsname
611%    \fi}
612
613\installtabulatepreambleoption\relax
614  {} % finished
615
616\def\tabl_tabulate_set_preamble#1%
617  {\ifcsname\??tabulatepreamble\string#1\endcsname
618    %\expandafter\tabl_tabulate_set_preamble_yes
619     \expandafter\expandafter\expandafter\lastnamedcs\expandafter\gobbleoneargument
620   \else
621     \expandafter\tabl_tabulate_set_preamble_nop
622   \fi{#1}}
623
624\def\tabl_tabulate_set_preamble_yes#1%
625  {\csname\??tabulatepreamble\string#1\expandafter\endcsname}
626
627\def\tabl_tabulate_set_preamble_nop#1%
628  {\writestatus{tabulate}{unknown preamble key: #1}%
629   \tabl_tabulate_set_preamble}
630
631\def\tabl_tabulate_set_preskip#1%
632  {%settrue\c_tabl_pre_is_set
633   \doifelsenumber{#1}%
634     {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble  }%
635     {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
636
637\def\tabl_tabulate_set_posskip#1%
638  {\settrue\c_tabl_post_is_set
639   \doifelsenumber{#1}%
640     {\s_tabl_tabulate_post#1\d_tabl_tabulate_unit\tabl_tabulate_set_preamble  }%
641     {\s_tabl_tabulate_post.5\d_tabl_tabulate_unit\tabl_tabulate_set_preamble#1}}
642
643\def\tabl_tabulate_set_preposskip#1%
644  {%settrue\c_tabl_pre_is_set
645   \settrue\c_tabl_post_is_set
646   \doifelsenumber{#1}%
647     {\s_tabl_tabulate_pre#1\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble  }%
648     {\s_tabl_tabulate_pre.5\d_tabl_tabulate_unit\s_tabl_tabulate_post\s_tabl_tabulate_pre\tabl_tabulate_set_preamble#1}}
649
650\def\tabl_tabulate_set_setups#1%
651  {\setvalue{\??tabulatesetup\the\c_tabl_tabulate_columns}{\setups[#1]}%
652   \tabl_tabulate_set_preamble}
653
654\def\tabl_tabulate_set_hook#1%
655  {\setvalue{\??tabulatehook\the\c_tabl_tabulate_columns}{#1}%
656   \tabl_tabulate_set_preamble}
657
658% begin of character align plugin
659
660\newconditional\c_tabl_auto_align_mode % reset later
661
662\def\tabl_tabulate_hook_g % partly expanded
663  {\ifconditional\c_tabl_auto_align_mode
664     \signalcharacteralign\c_tabl_tabulate_column{\c_tabl_tabulate_noflines+\plusone}%
665     \typo_charalign_adapt_font
666   \fi}
667
668\def\tabl_tabulate_set_align#1%
669  {\global\settrue\c_tabl_auto_align_mode
670   \setcharacteralign\c_tabl_tabulate_columns{#1}%
671   \tabl_tabulate_set_preamble}
672
673% end of character align plugin
674
675\def\tabl_tabulate_set_before#1%
676  {\t_tabl_tabulate_before{#1}%
677   \tabl_tabulate_set_preamble}
678
679\def\tabl_tabulate_set_after#1%
680  {\t_tabl_tabulate_after{#1}%
681   \tabl_tabulate_set_preamble}
682
683\def\tabl_tabulate_set_font#1%
684  {\t_tabl_tabulate_font{#1}%
685   \tabl_tabulate_set_preamble}
686
687\def\tabl_tabulate_pickup_width
688  {\doifelsenextparenthesis\tabl_tabulate_set_width_indeed\tabl_tabulate_set_preamble}
689
690\def\tabl_tabulate_set_width
691  {\setfalse\c_tabl_tabulate_pwidth_set
692   \c_tabl_tabulate_modus\zerocount
693   \tabl_tabulate_pickup_width}
694
695\def\tabl_tabulate_set_alignment#1%
696  {\edef\m_tabl_tabulate_alignment{#1}%
697   \spac_align_use_later\m_tabl_tabulate_alignment
698   \tabl_tabulate_set_preamble}
699
700\def\tabl_tabulate_set_paragraph
701  {\doifelsenextparenthesis
702     {\c_tabl_tabulate_modus\plusone
703      \settrue\c_tabl_tabulate_pwidth_set
704      \tabl_tabulate_pickup_width}
705     {\c_tabl_tabulate_modus\plustwo
706      \setfalse\c_tabl_tabulate_pwidth_set
707      \tabl_tabulate_set_preamble}}
708
709% \startbuffer
710%   \toplinebox{\framed[width=3cm,height=2cm]{tufte}}
711% \stopbuffer
712% \starttabulate[|p(fixed)|p|]
713%   \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
714% \stoptabulate
715% \starttabulate[|p(fit)|p|]
716%   \dorecurse{100}{\NC \getbuffer \NC test \par test \par \NC \NR}
717% \stoptabulate
718
719\def\tabl_tabulate_set_width_indeed(#1)%
720  {\processallactionsinset % can be made faster
721     [#1]%
722     [   \v!fit=>\c_tabl_tabulate_modus\plusthree,
723       \v!fixed=>\c_tabl_tabulate_modus\plusthree
724                 \settrue\c_tabl_tabulate_nopbreak,
725        \v!auto=>\c_tabl_tabulate_modus\plusthree
726                 \settrue\c_tabl_tabulate_reshape,
727     \s!unknown=>\d_tabl_tabulate_width#1\relax]%
728   \ifconditional\c_tabl_tabulate_pwidth_set
729     \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth
730   \fi
731   \tabl_tabulate_set_preamble}
732
733% faster but seldom used
734%
735% \installcorenamespace{tabulatewidth}
736%
737% \setvalue{\??tabulatewidth\v!fit  }{\c_tabl_tabulate_modus\plusthree}
738% \setvalue{\??tabulatewidth\v!fixed}{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_nopbreak}
739% \setvalue{\??tabulatewidth\v!auto }{\c_tabl_tabulate_modus\plusthree\settrue\c_tabl_tabulate_reshape}
740%
741% \def\tabl_tabulate_set_width_step#1%
742%   {\ifcsname\??tabulatewidth#1\endcsname
743%      \lastnamedcs
744%    \else
745%      \d_tabl_tabulate_width#1\relax
746%    \fi}
747%
748% \def\tabl_tabulate_set_width_indeed(#1)%
749%   {\rawprocesscommacommand[#1]\tabl_tabulate_set_width_step
750%    \ifconditional\c_tabl_tabulate_pwidth_set
751%      \global\advance\d_tabl_tabulate_width_p\d_tabl_tabulate_width % accumulated parwidth
752%    \fi
753%    \tabl_tabulate_set_preamble}
754%
755\def\tabl_tabulate_set_raggedright {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedright \fi}
756\def\tabl_tabulate_set_raggedcenter{\ifnum\c_tabl_tabulate_type=\plusone \else\raggedcenter\fi}
757\def\tabl_tabulate_set_raggedleft  {\ifnum\c_tabl_tabulate_type=\plusone \else\raggedleft  \fi}
758\def\tabl_tabulate_set_notragged   {\ifnum\c_tabl_tabulate_type=\plusone \else\notragged   \fi}
759\def\tabl_tabulate_set_hss         {\ifnum\c_tabl_tabulate_type=\plusone \else\hss         \fi} % never change this to a fill
760
761\def\tabl_tabulate_bskip_raggedright {\tabl_tabulate_bskip\tabl_tabulate_set_raggedright }
762\def\tabl_tabulate_bskip_raggedleft  {\tabl_tabulate_bskip\tabl_tabulate_set_raggedleft  }
763\def\tabl_tabulate_bskip_raggedcenter{\tabl_tabulate_bskip\tabl_tabulate_set_raggedcenter}
764
765\def\tabl_tabulate_set_width_normal
766  {\ifcase\c_tabl_tabulate_align\relax
767     \tabl_tabulate_set_preamble_step\empty                \tabl_tabulate_set_hss \or
768     \tabl_tabulate_set_preamble_step\empty                \tabl_tabulate_set_hss \or
769     \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\empty                 \or
770     \tabl_tabulate_set_preamble_step\tabl_tabulate_set_hss\tabl_tabulate_set_hss \fi}
771
772\def\tabl_tabulate_set_width_fixed
773  {\ifcase\c_tabl_tabulate_align\relax
774     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip             \tabl_tabulate_eskip \or
775     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
776     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft  \tabl_tabulate_eskip \or
777     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
778
779\def\tabl_tabulate_set_width_auto
780  {\global\advance\c_tabl_tabulate_nofauto\plusone
781   \ifcase\c_tabl_tabulate_align\relax
782     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip             \tabl_tabulate_eskip \or
783     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedright \tabl_tabulate_eskip \or
784     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedleft  \tabl_tabulate_eskip \or
785     \tabl_tabulate_set_preamble_step\tabl_tabulate_bskip_raggedcenter\tabl_tabulate_eskip \fi}
786
787\def\tabl_tabulate_set_width_simple
788  {\tabl_tabulate_set_preamble_step\tabl_tabulate_xbskip\tabl_tabulate_xeskip}
789
790% \def\tabl_tabulate_set_color_span#1#2%
791%   {\xdef\m_tabl_tabulate_color{#2}%
792%    \global\c_tabl_tabulate_colorspan\if#1L\plusone\else\if#1M\plustwo\else\if#1R\plusthree\else\zerocount\fi\fi\fi\relax
793%    \tabl_tabulate_set_preamble}
794
795\installcorenamespace{tabulatecolorspec}
796
797\setvalue{\??tabulatecolorspec C}#1{\xdef\m_tabl_tabulate_color     {#1}\global\c_tabl_tabulate_colorspan\zerocount}
798\setvalue{\??tabulatecolorspec L}#1{\xdef\m_tabl_tabulate_color     {#1}\global\c_tabl_tabulate_colorspan\plusone  }
799\setvalue{\??tabulatecolorspec M}#1{\xdef\m_tabl_tabulate_color     {#1}\global\c_tabl_tabulate_colorspan\plustwo  }
800\setvalue{\??tabulatecolorspec R}#1{\xdef\m_tabl_tabulate_color     {#1}\global\c_tabl_tabulate_colorspan\plusthree}
801\setvalue{\??tabulatecolorspec T}#1{\xdef\m_tabl_tabulate_text_color{#1}}
802
803\def\tabl_tabulate_set_color_span#1#2%
804  {\csname\??tabulatecolorspec#1\endcsname{#2}%
805   \tabl_tabulate_set_preamble}
806
807\def\tabl_tabulate_set_vrule_command#1%
808  {\doifelsenumber{#1}
809     {\global\d_tabl_tabulate_vrulethickness#1\d_tabl_tabulate_vrulethickness_default}
810     {\xdef\m_tabl_tabulate_vrule_color{#1}}}
811
812\def\tabl_tabulate_set_entry#1#2% rulespec template
813  {\c_tabl_tabulate_align\v_tabl_tabulate_align
814   \c_tabl_tabulate_modus\zerocount
815   \setfalse\c_tabl_tabulate_pwidth_set
816   \setfalse\c_tabl_tabulate_reshape
817   %setfalse\c_tabl_pre_is_set
818   \setfalse\c_tabl_post_is_set
819   \t_tabl_tabulate_before\emptytoks
820   \t_tabl_tabulate_after\emptytoks
821   \t_tabl_tabulate_bmath\emptytoks
822   \t_tabl_tabulate_emath\emptytoks
823   \t_tabl_tabulate_font\emptytoks
824   \t_tabl_tabulate_settings\emptytoks
825   \glet\m_tabl_tabulate_alignment\empty
826   \glet\m_tabl_tabulate_color\empty
827   \glet\m_tabl_tabulate_text_color\empty
828   \glet\m_tabl_tabulate_vrule_color\empty
829   \global\c_tabl_tabulate_colorspan\zerocount
830   \global\setfalse\c_tabl_auto_align_mode
831   \global\advance\c_tabl_tabulate_columns\plusone
832   \expandafter\let\csname\??tabulatesetup\the\c_tabl_tabulate_columns\endcsname\donothing % here ?
833   \edef\currenttabulationtrulespec{#1}%
834   \ifx\currenttabulationtrulespec\empty
835     \global\d_tabl_tabulate_vrulethickness\zeropoint
836   \else
837     \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
838     \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
839   \fi
840     \tabl_tabulate_set_preamble#2\relax\relax % permits i without n
841   \ifcase\c_tabl_tabulate_modus\relax
842     \tabl_tabulate_set_width_normal
843   \or % fixed width
844     \tabl_tabulate_set_width_fixed
845   \or % auto width
846     \tabl_tabulate_set_width_auto
847   \or % simple
848     \tabl_tabulate_set_width_simple
849   \fi}
850
851\def\tabl_tabulate_set_last_entry#1% rulespec
852  {\glet\m_tabl_tabulate_color\empty
853   \glet\m_tabl_tabulate_vrule_color\empty
854   \edef\currenttabulationtrulespec{#1}%
855   \ifx\currenttabulationtrulespec\empty
856     \global\d_tabl_tabulate_vrulethickness\zeropoint
857   \else
858     \global\d_tabl_tabulate_vrulethickness\d_tabl_tabulate_vrulethickness_default
859     \rawprocesscommalist[#1]\tabl_tabulate_set_vrule_command
860   \fi
861   \etoksapp\t_tabl_tabulate_preamble{%
862     \tabl_tabulate_check_local_vrule_thickness\constantdimenargument\d_tabl_tabulate_vrulethickness
863     \tabl_tabulate_check_local_vrule_color\constantemptyargument\m_tabl_tabulate_vrule_color
864     \tabl_tabulate_column_vrule_inject}}
865
866\let\settabulateentry    \tabl_tabulate_set_entry      % used at the lua end
867\let\settabulatelastentry\tabl_tabulate_set_last_entry % used at the lua end
868
869\def\tabl_tabulate_normalize_splitline
870  {\ifcase\c_tabl_tabulate_splitlinemode
871     % nothing
872   \or
873     \ht\b_tabl_tabulate\strutht
874     \dp\b_tabl_tabulate\strutdp
875   \or
876     \ifdim\ht\b_tabl_tabulate<\strutht
877       \ht\b_tabl_tabulate\strutht
878     \fi
879     \ifdim\dp\b_tabl_tabulate<\strutdp
880       \dp\b_tabl_tabulate\strutdp
881     \fi
882   \fi}
883
884\def\tabl_tabulate_whitespace
885  {\ifdim\d_tabl_tabulate_splitoff_betweenskip>\zeropoint
886     \vskip\d_tabl_tabulate_splitoff_betweenskip
887     \global\d_tabl_tabulate_splitoff_betweenskip\zeropoint
888   \fi}
889
890\def\tabl_tabulate_check_whitespace
891  {\setbox\scratchbox\vpack
892     {\splitdiscards
893      \unskip
894      \ifdim\lastskip>\d_tabl_tabulate_splitoff_betweenskip
895        \global\d_tabl_tabulate_splitoff_betweenskip\lastskip
896      \fi}}
897
898\installtexdirective
899  {tabulate.linenumbers}
900  {\def\tabl_tabulate_check_linenumbers{\page_postprocessors_linenumbers_deepbox\b_tabl_tabulate}}
901  {\let\tabl_tabulate_check_linenumbers\relax}
902
903\let\tabl_tabulate_check_linenumbers\relax
904
905\def\tabl_tabulate_splitoff_box
906  {\dontcomplain
907   \global\setbox\b_tabl_tabulate\vsplit\b_tabl_tabulate_current\c_tabl_tabulate_column to \lineheight % % % global ? % % %
908   \setbox\b_tabl_tabulate\vbox
909     {\unvbox\b_tabl_tabulate}%
910   \ifconditional\c_tabl_tabulate_splitoff_whitespace
911     \tabl_tabulate_check_whitespace
912   \fi
913   \tabl_tabulate_color_repeat % needs to end up in a cell
914   \setbox\b_tabl_tabulate\hpack to \wd\b_tabl_tabulate
915     {\hss\tabl_tabulate_hook_yes{\box\b_tabl_tabulate}\hss}%
916   \tabl_tabulate_normalize_splitline
917   \tabl_tabulate_check_linenumbers
918   \box\b_tabl_tabulate}
919
920\unexpanded\def\tabl_tabulate_hook_nop
921  {}
922
923\let\tabl_tabulate_hook\tabl_tabulate_hook_nop
924
925\def\tabl_tabulate_hook_yes{\begincsname\??tabulatehook\the\c_tabl_tabulate_column\endcsname}
926
927\def\tabl_tabulate_pheight_reset
928  {\global\c_tabl_tabulate_plines_min\plusone
929   \ifdim\d_tabl_tabulate_height_p_max>\zeropoint
930     \getnoflines\d_tabl_tabulate_height_p_max
931     \global\c_tabl_tabulate_plines_max\noflines
932   \else
933     \global\c_tabl_tabulate_plines_max\zerocount
934   \fi
935   \global\d_tabl_tabulate_height_p_max\zeropoint}
936
937\def\tabl_tabulate_pheight_set
938  {\scratchdimen\ht\b_tabl_tabulate_current\c_tabl_tabulate_column\relax
939   \ifdim\scratchdimen>\d_tabl_tabulate_height_p_max
940     \global\d_tabl_tabulate_height_p_max\scratchdimen
941   \fi}
942
943\def\tabl_tabulate_pbreak_inject
944  {\ifconditional\c_tabl_tabulate_handlepbreak
945     \ifconditional\c_tabl_tabulate_nopbreak
946       \tabl_tabulate_nobreak_inject
947     \else\ifnum\c_tabl_tabulate_plines_max>\plusone
948       \ifnum\c_tabl_tabulate_plines_min=\plusone
949         \tabl_tabulate_nobreak_inject
950       \fi
951       \global\advance\c_tabl_tabulate_plines_min\plusone
952       \ifnum\c_tabl_tabulate_plines_min=\c_tabl_tabulate_plines_max\relax
953         \tabl_tabulate_nobreak_inject
954       \fi
955     \fi \fi
956   \fi}
957
958\def\tabl_tabulate_pbreak_check
959  {\starttabulatenoalign
960     \tabl_tabulate_pbreak_inject
961     \ifconditional\c_tabl_tabulate_splitoff_whitespace
962       \tabl_tabulate_whitespace
963     \fi
964   \stoptabulatenoalign}
965
966%D \startbuffer
967%D \starttabulate[|c|p|p|]
968%D \NC \bf Alpha \NC \bf Beta        \NC \bf Gamma          \NC\NR
969%D \NC 1         \NC right indeed    \NC definitely wrong   \NC\NR
970%D \NC 2         \NC \thinrules[n=3] \NC \thinrules[n=3]    \NC\NR
971%D \NC 3         \NC oh yes          \NC simply no          \NC\NR
972%D \NC 4         \NC very true       \NC as false as can be \NC\NR
973%D \NC 5         \NC \thinrules[n=5] \NC \thinrules[n=5]    \NC\NR
974%D \NC 6         \NC \thinrules[n=3] \NC \thinrules[n=4]    \NC\NR
975%D \stoptabulate
976%D \stopbuffer
977%D
978%D \typebuffer {\tracetabulatetrue\getbuffer}
979%D
980%D \startbuffer
981%D \starttabulate[|c|p|p|]
982%D \NC \bf Alpha \NC \bf Beta        \NC \bf Gamma          \NC\NR
983%D \NC 1         \NC right indeed    \NC definitely wrong   \NC\NR
984%D \NC 2         \NC oh yes          \NC simply no          \NC\NR
985%D \NC 3         \NC very true       \NC as false as can be \NC\NR
986%D \NC 4         \NC the whole truth \NC but the truth      \NC\NR
987%D \stoptabulate
988%D \stopbuffer
989%D
990%D \typebuffer {\tracetabulatetrue\getbuffer}
991
992%D Because we want to be compatible we use an indirect way to implement the
993%D definers. The next examples demonstrate the difference:
994%D
995%D \starttyping
996%D \definetabulate[test][|l|c|r|]
997%D \definetabulate[test][two][|r|c|l|]
998%D
999%D \definetabulation[more][format={|l|c|r|}]
1000%D \definetabulation[more:two][format={|r|c|l|}]
1001%D
1002%D \starttest
1003%D \NC t \NC t \NC t \NC \NR
1004%D \NC te \NC te \NC te \NC \NR
1005%D \NC tes \NC tes \NC tes \NC \NR
1006%D \NC test \NC test \NC test \NC \NR
1007%D \stoptest
1008%D
1009%D \starttest[two]
1010%D \NC t \NC t \NC t \NC \NR
1011%D \NC te \NC te \NC te \NC \NR
1012%D \NC tes \NC tes \NC tes \NC \NR
1013%D \NC test \NC test \NC test \NC \NR
1014%D \stoptest
1015%D \startmore
1016%D \NC t \NC t \NC t \NC \NR
1017%D \NC te \NC te \NC te \NC \NR
1018%D \NC tes \NC tes \NC tes \NC \NR
1019%D \NC test \NC test \NC test \NC \NR
1020%D \stopmore
1021%D
1022%D \startmore[two]
1023%D \NC t \NC t \NC t \NC \NR
1024%D \NC te \NC te \NC te \NC \NR
1025%D \NC tes \NC tes \NC tes \NC \NR
1026%D \NC test \NC test \NC test \NC \NR
1027%D \stopmore
1028%D \stoptyping
1029
1030\installcorenamespace {tabulation}
1031
1032\installcommandhandler \??tabulation {tabulation} \??tabulation
1033
1034\setuptabulation
1035  [\c!unit=1em,
1036   EQ={:},
1037   \c!format={|l|p|},
1038   \c!frame=\v!off,
1039  %\c!bodyfont=,
1040   \c!rule=\v!normal,
1041  %\c!rulecolor=,
1042   \c!rulethickness=\linewidth,
1043  %\c!inner=,
1044   \c!before=\blank,
1045   \c!after=\blank,
1046   \c!distance={\v!depth,\v!medium},
1047   \c!align=\v!normal,
1048   \c!margin=\!!zeropoint,
1049   \c!split=\v!auto,
1050   \c!header=\v!yes,
1051  %\c!title=,
1052   \c!indenting=\v!no]
1053
1054\unexpanded\def\definetabulate
1055  {\dotripleempty\tabl_tabulate_define}
1056
1057\def\tabl_tabulate_define[#1][#2][#3]%
1058  {\ifthirdargument
1059     % [tag] [sub] [template]
1060     \ifcsname\namedtabulationhash{#1}\s!check\endcsname \else
1061       \definetabulation[#1][\c!format={#3},\s!check=]%
1062     \fi
1063     \definetabulation[#1:#2][#1][\c!format={#3},\s!check=]%
1064   \else\ifsecondargument
1065     % [tag] [template]
1066     \definetabulation[#1][\c!format={#2},\s!check=]%
1067   \else
1068     % [tag]
1069     \definetabulation[#1][\c!format={|l|p|},\s!check=]%
1070   \fi\fi}
1071
1072\unexpanded\def\setuptabulate
1073  {\dotripleempty\tabl_tabulate_setup}
1074
1075\def\tabl_tabulate_setup[#1][#2][#3]%
1076  {\ifthirdargument
1077     % [tag] [sub] [settings]
1078     \setuptabulation[#1:#2][#3]%
1079   \else\ifsecondargument
1080     % [tag] [settings]
1081     \setuptabulation[#1][#2]%
1082   \else
1083     % [tag]
1084     \setuptabulation[#1]%
1085   \fi\fi}
1086
1087\appendtoks
1088     \setuevalue{\e!start\currenttabulation}{\tabl_start_defined[\currenttabulation]}%
1089     \letvalue{\e!stop\currenttabulation}\relax
1090     \letvalue{\??tabulatehead\currenttabulation}\empty
1091     \letvalue{\??tabulatefoot\currenttabulation}\empty
1092\to \everydefinetabulation
1093
1094\let\tabulateparameter\tabulationparameter % will stay for a while
1095\def\currenttabulate  {\currenttabulation} % will stay for a while
1096
1097% Here begins the implementation.
1098
1099\let\tabl_tabulate_insert_head\empty
1100\let\tabl_tabulate_insert_body\empty
1101\let\tabl_tabulate_insert_foot\empty
1102
1103\def\tabl_tabulate_insert_head_content
1104  {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
1105   \begincsname\??tabulatehead\currenttabulation\endcsname
1106   \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
1107
1108\def\tabl_tabulate_insert_foot_content
1109  {\tabulatenoalign{\global\settrue\c_tabl_tabulate_someamble}%
1110   \begincsname\??tabulatefoot\currenttabulation\endcsname
1111   \tabulatenoalign{\global\setfalse\c_tabl_tabulate_someamble}}%
1112
1113\def\tabl_tabulate_check_full_content % - needed, else confusion with \c!header
1114  {\ifcsname\??tabulatehead\currenttabulation\endcsname
1115    %\expandafter\ifx\csname\??tabulatehead\currenttabulation\endcsname\empty
1116     \expandafter\ifx\lastnamedcs\empty
1117       \let\tabl_tabulate_insert_head\empty
1118     \else
1119       \let\tabl_tabulate_insert_head\tabl_tabulate_insert_head_content
1120     \fi
1121   \else
1122     \let\tabl_tabulate_insert_head\empty
1123   \fi
1124   \ifcsname\??tabulatefoot\currenttabulation\endcsname
1125    %\expandafter\ifx\csname\??tabulatefoot\currenttabulation\endcsname\empty
1126     \expandafter\ifx\lastnamedcs\empty
1127       \let\tabl_tabulate_insert_foot\empty
1128     \else
1129       \let\tabl_tabulate_insert_foot\tabl_tabulate_insert_foot_content
1130     \fi
1131   \else
1132     \let\tabl_tabulate_insert_foot\empty
1133   \fi}
1134
1135\def\tabl_tabulate_insert_content
1136  {\tabl_tabulate_insert_head
1137   \ifcase\c_tabl_tabulate_repeathead \else
1138     \tabulatenoalign{\penalty\zerocount}% added 7/5/2014 WS mail
1139   \fi
1140   \tabl_tabulate_insert_body
1141   \tabl_tabulate_insert_foot
1142   \tabl_tabulate_remove_funny_line}
1143
1144\def\tabl_tabulate_remove_funny_line
1145  {\ifhmode
1146     \strut\crcr
1147     \tabulatenoalign{\kern-\lineheight}%
1148   \fi}
1149
1150% todo: make footer synonym to tail
1151
1152\setuvalue{\e!start\v!tabulatehead}{\doifelsenextoptionalcs\tabl_tabulate_start_head_yes\tabl_tabulate_start_head_nop}
1153\setuvalue{\e!start\v!tabulatetail}{\doifelsenextoptionalcs\tabl_tabulate_start_foot_yes\tabl_tabulate_start_foot_nop}
1154
1155\let\m_tabl_tabulate_data\empty
1156
1157\def\tabl_tabulate_start_head_yes[#1]%
1158  {\processcontent{\e!stop\v!tabulatehead}\m_tabl_tabulate_data{\letvalue{\??tabulatehead#1}\m_tabl_tabulate_data}}
1159
1160\def\tabl_tabulate_start_foot_yes[#1]%
1161  {\processcontent{\e!stop\v!tabulatetail}\m_tabl_tabulate_data{\letvalue{\??tabulatefoot#1}\m_tabl_tabulate_data}}
1162
1163\def\tabl_tabulate_start_head_nop{\tabl_tabulate_start_head_yes[\v!tabulate]}
1164\def\tabl_tabulate_start_foot_nop{\tabl_tabulate_start_foot_yes[\v!tabulate]}
1165
1166\unexpanded\def\tabl_start_defined[#1]%
1167  {\bgroup
1168   \edef\currenttabulationparent{#1}%
1169   \let\currenttabulation\currenttabulationparent
1170   \edef\p_format{\tabulationparameter\c!format}%
1171   \ifx\p_format\v!none
1172     % this is special case: we need to define the generic english
1173     % \starttabulate in other interfaces as well
1174     \expandafter\dodoubleempty   \expandafter\tabl_start_regular
1175   \else
1176     \expandafter\dodoubleargument\expandafter\tabl_start_defined_indeed
1177   \fi}
1178
1179\def\tabl_start_defined_indeed
1180  {\iffirstargument
1181     \ifsecondargument
1182       \doubleexpandafter\tabl_start_defined_two
1183     \else
1184       \doubleexpandafter\tabl_start_defined_one
1185     \fi
1186   \else
1187      \singleexpandafter\tabl_start_defined_zero
1188   \fi}
1189
1190\def\tabl_start_defined_one[#1][#2]%
1191  {\ifcondition\validassignment{#1}%
1192     \setuptabulation[\currenttabulation][#1]%
1193   \else
1194     \edef\currenttabulation{\currenttabulation:#1}%
1195   \fi
1196   \tabl_tabulate_start_building}
1197
1198\def\tabl_start_defined_two[#1][#2]%
1199  {\edef\currenttabulation{\currenttabulation:#1}%
1200   \setuptabulation[\currenttabulation][#2]%
1201   \tabl_tabulate_start_building}
1202
1203\def\tabl_start_defined_zero[#1][#2]%
1204  {\tabl_tabulate_start_building}
1205
1206% \definetabulate[\v!tabulate][|l|p|] % we need to get rid of this one
1207
1208\unexpanded\setuvalue{\e!start\v!tabulate}%
1209  {\bgroup % whole thing
1210   \let\currenttabulationparent\empty
1211   \dodoubleempty\tabl_start_regular}
1212
1213\def\tabl_start_regular
1214  {\let\currenttabulation\currenttabulationparent
1215   \ifsecondargument
1216     \expandafter\tabl_start_regular_two
1217   \else
1218     \expandafter\tabl_start_regular_one
1219   \fi}
1220
1221\def\tabl_default_format{|l|p|}
1222
1223\def\tabl_start_regular_one[#1][#2]%
1224  {\ifcondition\validassignment{#1}%
1225     \lettabulationparameter\c!format\tabl_default_format
1226     \setupcurrenttabulation[#1]%
1227   \else
1228     \def\p_format{#1}%
1229     \ifx\p_format\empty
1230       \def\p_format{|l|p|}%
1231     \fi
1232     \lettabulationparameter\c!format\p_format
1233   \fi
1234   \tabl_tabulate_start_building}
1235
1236\def\tabl_start_regular_two[#1][#2]%
1237  {\def\p_format{#1}%
1238   \ifx\p_format\empty
1239     \let\p_format\tabl_default_format
1240   \fi
1241   \lettabulationparameter\c!format\p_format
1242   \setupcurrenttabulation[#2]%
1243   \tabl_tabulate_start_building}
1244
1245\letvalue{\e!stop\v!tabulate    }\relax
1246\letvalue{\e!stop\v!tabulatehead}\relax
1247\letvalue{\e!stop\v!tabulatetail}\relax
1248
1249\unexpanded\def\tabl_tabulate_start_ignore
1250  {\em Nested tabulate is not (yet) supported.\relax
1251   \expandafter\gobbleuntil\csname\ifconditional\c_tabl_generic stoptabulate\else\e!stop\v!tabulate\fi\endcsname}
1252
1253\appendtoks
1254    \letvalue{\e!start\v!tabulate}\tabl_tabulate_start_ignore % only the main one
1255\to \everytabulate
1256
1257\setvalue{\??tabulatesplit\v!yes   }{\settrue\c_tabl_tabulate_split}
1258\setvalue{\??tabulatesplit\v!repeat}{\settrue\c_tabl_tabulate_split}
1259\setvalue{\??tabulatesplit\v!no    }{\setfalse\c_tabl_tabulate_split}
1260\setvalue{\??tabulatesplit\v!auto  }{\ifinsidefloat\ifinsidesplitfloat\else\setfalse\c_tabl_tabulate_split\fi\fi}
1261
1262% todo: spacing around tabulate when bodyfont is set
1263
1264% \let\tabl_tabulate_inside_before   \relax
1265% \let\tabl_tabulate_inside_after    \relax
1266% \let\tabl_tabulate_inside_inbetween\relax
1267%
1268% \def\tabl_tabulate_outside_before
1269%   {\whitespace
1270%    \tabulationparameter\c!before}
1271%
1272% \def\tabl_tabulate_outside_after
1273%   {\tabulationparameter\c!after}
1274
1275% \showboxes
1276%
1277% \startcombination
1278%     {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
1279%     {\insidefloattrue \starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
1280% \stopcombination
1281%
1282% \startcombination
1283%     {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {}
1284%     {\vbox{\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate}} {}
1285% \stopcombination
1286%
1287% \startcombination
1288%     {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
1289%     {\starttabulate[|||] \NC test \NC test \NC \NR \stoptabulate} {}
1290% \stopcombination
1291
1292\let\tabl_tabulate_inside_after     \relax
1293\let\tabl_tabulate_outside_after    \relax
1294\let\tabl_tabulate_inside_inbetween \relax
1295\let\tabl_tabulate_outside_inbetween\relax
1296
1297\unexpanded\def\tabl_tabulate_inside_before
1298  {\ifhmode\par\fi
1299   \ifhmode
1300     \ifinsidesplitfloat
1301       \let\tabl_tabulate_inside_after\relax
1302     \else
1303       \vbox\bgroup
1304       \let\tabl_tabulate_inside_after\egroup
1305     \fi
1306   \else
1307     \let\tabl_tabulate_inside_after\relax
1308   \fi}
1309
1310\unexpanded\def\tabl_tabulate_outside_before
1311  {\ifhmode\par\fi
1312   \ifhmode
1313     \vbox\bgroup
1314     \let\tabl_tabulate_outside_after    \egroup
1315     \let\tabl_tabulate_outside_inbetween\relax
1316   \else\ifinner
1317     \let\tabl_tabulate_outside_after    \relax
1318     \let\tabl_tabulate_outside_inbetween\relax
1319   \else
1320     \whitespace
1321     \tabulationparameter\c!before
1322     \relax
1323     \let\tabl_tabulate_outside_after    \tabl_tabulate_outside_after_indeed
1324     \let\tabl_tabulate_outside_inbetween\tabl_tabulate_outside_inbetween_indeed
1325   \fi\fi}
1326
1327\def\tabl_tabulate_outside_after_indeed
1328  {\tabulationparameter\c!after}
1329
1330\def\tabl_tabulate_outside_inbetween_indeed
1331  {\doifempty{\tabulationparameter\c!after}
1332     {\vskip\strutdp
1333      \verticalstrut
1334      \vskip-\struttotal}}
1335
1336\def\tabl_tabulate_inside_inbetween % needs checking
1337  {\doifempty{\tabulationparameter\c!after}
1338     {\vskip\strutdp
1339      \verticalstrut
1340      \vskip-\struttotal}}
1341
1342\unexpanded\def\tabl_tabulate_start_building
1343  {\ifinsidefloat
1344     \tabl_tabulate_inside_before
1345   \else
1346     \tabl_tabulate_outside_before
1347   \fi
1348   \bgroup % settings
1349   %
1350   \t_tabl_tabulate_preamble\emptytoks
1351   \t_tabl_tabulate_dummy   \emptytoks
1352   %
1353   \resetcharacteralign
1354   %
1355   \edef\p_distance     {\tabulationparameter\c!distance}%
1356   \edef\p_align        {\tabulationparameter\c!align}%
1357   \edef\p_line         {\tabulationparameter\c!rule}%
1358   \edef\p_rulecolor    {\tabulationparameter\c!rulecolor}%
1359   \edef\p_rulethickness{\tabulationparameter\c!rulethickness}%
1360   \edef\p_bodyfont     {\tabulationparameter\c!bodyfont}
1361   \edef\p_indenting    {\tabulationparameter\c!indenting}%
1362   \edef\p_keeptogether {\tabulationparameter\c!keeptogether}%
1363   \edef\p_blank        {\tabulationparameter\c!blank}%
1364   %
1365   \ifx\p_keeptogether\v!no
1366     \settrue \c_tabl_tabulate_tolerant_break
1367    %\setfalse\c_tabl_tabulate_handlepbreak
1368   \else
1369     \setfalse\c_tabl_tabulate_tolerant_break
1370    %\settrue \c_tabl_tabulate_handlepbreak
1371   \fi
1372   %
1373   \settrue\c_tabl_tabulate_split
1374   \begincsname\??tabulatesplit\tabulationparameter\c!split\endcsname
1375   %
1376   \let\m_tabl_tabulate_blank_default\p_blank
1377   %
1378   \d_tabl_tabulate_unit\tabulationparameter\c!unit
1379   \d_tabl_tabulate_margin\tabulationparameter\c!margin
1380   \let\m_tabl_tabulate_vrule_color_default\p_rulecolor
1381   \let\m_tabl_tabulate_hrule_color_default\p_rulecolor
1382   \d_tabl_tabulate_vrulethickness_default\p_rulethickness
1383   \d_tabl_tabulate_hrulethickness_default\p_rulethickness
1384   \ifx\p_bodyfont\empty\else
1385     \switchtobodyfont[\p_bodyfont]%
1386   \fi
1387   \postponenotes % new, to be tested / will be configurable
1388   \widowpenalty\zerocount % otherwise lines are not broken
1389   \clubpenalty \zerocount % but overlap in funny ways
1390   \the\everytabulate
1391   \tabulationparameter\c!inner
1392   \d_tabl_tabulate_indent\dimexpr\leftskip+\hangindent\ifx\p_indenting\v!yes+\parindent\fi\relax
1393   \global\c_tabl_tabulate_column\zerocount
1394   \processcontent
1395     {\ifconditional\c_tabl_generic stoptabulate\else\e!stop\ifx\currenttabulationparent\empty\v!tabulate\else\currenttabulationparent\fi\fi}
1396     \tabl_tabulate_insert_body
1397     \tabl_tabulate_process}
1398
1399\def\tabulateEQ
1400  {\ifconditional\c_tabl_tabulate_firstflushed\else
1401     \dostarttaggedchained\t!ignore\empty\empty
1402     \dostarttagged\t!ignore\empty
1403     \tabulationparameter{EQ}%
1404     \dostoptagged
1405     \dostoptagged
1406   \fi
1407   \global\setfalse\c_tabl_tabulate_equal}
1408
1409% The next ones will be token registers
1410
1411\let\tabulatenormalpos\relax % hooks, todo
1412\let\tabulateequalpos \relax % hooks, todo
1413
1414% color columns
1415
1416\let\m_tabl_tabulate_color_previous     \empty
1417\let\m_tabl_tabulate_color              \empty
1418\let\m_tabl_tabulate_text_color         \empty
1419\let\m_tabl_tabulate_color_local        \empty
1420\let\m_tabl_tabulate_vrule_color        \empty
1421\let\m_tabl_tabulate_vrule_color_local  \empty
1422\let\m_tabl_tabulate_vrule_color_default\empty % used local
1423\let\m_tabl_tabulate_hrule_color_default\empty % used local
1424\let\m_tabl_tabulate_blank_default      \empty
1425
1426\appendtoks
1427    \glet\m_tabl_tabulate_color_previous      \empty
1428    \glet\m_tabl_tabulate_color               \empty
1429    \glet\m_tabl_tabulate_text_color          \empty
1430    \glet\m_tabl_tabulate_color_local         \empty
1431    \glet\m_tabl_tabulate_vrule_color         \empty
1432    \glet\m_tabl_tabulate_vrule_color_local   \empty
1433    \global    \d_tabl_tabulate_vrulethickness_local\zeropoint
1434\to \t_tabl_tabulate_every_row
1435
1436\unexpanded\def\tabl_tabulate_color_side_right_second
1437  {\ifx\m_tabl_tabulate_color_previous\empty \else
1438     \tabl_tabulate_color_set\m_tabl_tabulate_color_previous
1439     \glet\m_tabl_tabulate_color_previous\empty
1440   \fi}
1441
1442\unexpanded\def\tabl_tabulate_color_side_left_second
1443  {\ifx\m_tabl_tabulate_color\empty \else
1444     \ifcase\c_tabl_tabulate_colorspan
1445     \or
1446       \tabl_tabulate_color_set\m_tabl_tabulate_color
1447     \or
1448       \tabl_tabulate_color_set\m_tabl_tabulate_color
1449     \fi
1450   \fi}
1451
1452\unexpanded\def\tabl_tabulate_color_side_both_second
1453  {\ifx\m_tabl_tabulate_color\empty \else
1454     \tabl_tabulate_color_set\m_tabl_tabulate_color
1455     \ifcase\c_tabl_tabulate_colorspan
1456       %\glet\m_tabl_tabulate_color_previous\empty
1457     \or
1458       \glet\m_tabl_tabulate_color_previous\empty
1459     \or
1460       \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
1461     \or
1462       \glet\m_tabl_tabulate_color_previous\m_tabl_tabulate_color
1463     \fi
1464   \fi}
1465
1466\let\tabl_tabulate_color_side_right \relax
1467\let\tabl_tabulate_color_side_left  \relax
1468\let\tabl_tabulate_color_side_both  \relax
1469
1470\appendtoks
1471    \let\tabl_tabulate_color_side_right\tabl_tabulate_color_side_right_second
1472    \let\tabl_tabulate_color_side_left \tabl_tabulate_color_side_left_second
1473    \let\tabl_tabulate_color_side_both \tabl_tabulate_color_side_both_second
1474\to \t_tabl_tabulate_initializers_second
1475
1476\def\tabl_tabulate_set_color_column#1% overloaded
1477  {\unskip
1478   \doifelsefastoptionalcheck{\tabl_tabulate_set_color_column_yes#1}{\tabl_tabulate_set_color_column_nop#1}}
1479
1480\def\tabl_tabulate_set_color_column_nop
1481  {\tabl_tabulate_column_normal\zerocount}
1482
1483\def\tabl_tabulate_set_color_column_yes#1[#2]%
1484  {\xdef\m_tabl_tabulate_color_local{#2}%
1485   \tabl_tabulate_column_normal\zerocount#1}
1486
1487% normal columns:
1488
1489\def\tabl_tabulate_column_normal#1#2%
1490  {\unskip
1491   \aligntab
1492   \ifconditional\c_tabl_tabulate_equal\tabulateequalpos\else\tabulatenormalpos\fi
1493   \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn\else
1494     \tabl_tabulate_column_vrule_setup
1495   \fi
1496   \aligntab
1497   \global\c_tabl_tabulate_kind#1%
1498   \global\c_tabl_tabulate_type#2%
1499   \aligntab}
1500
1501% equal columns
1502
1503\def\tabl_tabulate_column_equal#1#2%
1504  {\unskip
1505   \aligntab
1506   \tabulateequalpos
1507   \aligntab
1508   \global\c_tabl_tabulate_kind#1%
1509   \global\c_tabl_tabulate_type#2%
1510   \aligntab}
1511
1512% ruled columns
1513
1514\def\tabl_tabulate_column_vruled_preset
1515  {\glet\m_tabl_tabulate_vrule_color_local\m_tabl_tabulate_vrule_color_default
1516   \global\d_tabl_tabulate_vrulethickness_local\d_tabl_tabulate_vrulethickness_default}
1517
1518\def\tabl_tabulate_column_vruled#1#2%
1519  {\unskip % 0-n
1520  %\ifnum\c_tabl_tabulate_column=\plusone
1521  %  \global\c_tabl_tabulate_has_rule_spec_first\plusone
1522  %\else\ifnum\c_tabl_tabulate_column=\c_tabl_tabulate_nofcolumns
1523  %  \global\c_tabl_tabulate_has_rule_spec_last\plusone
1524  %\fi\fi
1525   \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_vrulecolumn
1526     \global\c_tabl_tabulate_max_vrulecolumn\c_tabl_tabulate_column
1527   \fi
1528   \doifelsefastoptionalcheck{\tabl_tabulate_column_vruled_yes#1#2}{\tabl_tabulate_column_vruled_nop#1#2}}
1529
1530\def\tabl_tabulate_column_vrule_setup
1531  {\begincsname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname}
1532
1533\def\tabl_tabulate_column_vruled_nop
1534  {\expandafter\glet\csname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname\tabl_tabulate_column_vruled_preset
1535   \tabl_tabulate_column_normal}
1536
1537\def\tabl_tabulate_column_vruled_step#1%
1538  {\doifelsenumber{#1}
1539     {\global\d_tabl_tabulate_vrulethickness_local#1\d_tabl_tabulate_vrulethickness_default}
1540     {\xdef\m_tabl_tabulate_vrule_color_local{#1}}}
1541
1542\def\tabl_tabulate_column_vruled_yes#1#2[#3]%
1543  {\expandafter\gdef\csname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname
1544     {\tabl_tabulate_column_vruled_preset
1545      \rawprocesscommalist[#3]\tabl_tabulate_column_vruled_step}%
1546   \tabl_tabulate_column_normal#1#2}
1547
1548\def\tabl_tabulate_vrule_reset
1549  {\ifcase\c_tabl_tabulate_max_vrulecolumn\else
1550     \tabl_tabulate_vrule_reset_indeed
1551   \fi}
1552
1553\def\tabl_tabulate_vrule_reset_indeed
1554  {\gletcsname\??tabulatevrule0\endcsname\undefined
1555   \dofastloopcs\c_tabl_tabulate_max_vrulecolumn\tabl_tabulate_vrule_reset_step
1556   \global\c_tabl_tabulate_max_vrulecolumn\zerocount}
1557
1558\def\tabl_tabulate_vrule_reset_step % undefined or relax
1559  {\expandafter\glet\csname\??tabulatevrule\the\fastloopindex\endcsname\undefined}
1560
1561\appendtoks
1562    \tabl_tabulate_vrule_reset
1563\to \t_tabl_tabulate_every_after_row
1564
1565% sometimes more efficient:
1566%
1567% \def\tabl_tabulate_column_vruled_yes#1#2[#3]%
1568%   {\rawprocesscommalist[#3]\tabl_tabulate_column_vruled_step
1569%    \expandafter\xdef\csname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname
1570%      {\global\d_tabl_tabulate_vrulethickness_local\the\d_tabl_tabulate_vrulethickness_default
1571%       \noexpand\xdef\noexpand\m_tabl_tabulate_vrule_color_local{\m_tabl_tabulate_vrule_color_local}}%
1572%    \tabl_tabulate_column_normal#1#2}
1573
1574\def\tabl_tabulate_column_vruled_normal
1575  {\vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
1576
1577\def\tabl_tabulate_column_vruled_colored
1578  {\dousecolorparameter\m_tabl_tabulate_vrule_color
1579   \vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
1580
1581\unexpanded\def\tabl_tabulate_column_vrule_inject_first
1582  {\ifcase\d_tabl_tabulate_vrulethickness\else
1583     \tabl_tabulate_column_vruled_normal % could be a skip instead
1584   \fi
1585   \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
1586
1587\unexpanded\def\tabl_tabulate_column_vrule_inject_second
1588  {\ifcase\d_tabl_tabulate_vrulethickness\else
1589     \ifx\m_tabl_tabulate_vrule_color\empty
1590       \tabl_tabulate_column_vruled_normal
1591     \else
1592       \tabl_tabulate_column_vruled_colored
1593     \fi
1594   \fi
1595   \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
1596
1597\let\tabl_tabulate_column_vrule_inject\relax
1598
1599\appendtoks
1600    \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_first
1601\to \t_tabl_tabulate_initializers_first
1602
1603\appendtoks
1604    \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_second
1605\to \t_tabl_tabulate_initializers_second
1606
1607% auto columns
1608
1609\def\tabl_tabulate_column_inject_auto
1610  {\tabl_tabulate_column_normal\zerocount\zerocount
1611   \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_columns\relax
1612     \expandafter\NR
1613   \else
1614     \expandafter\ignorespaces % interferes with the more tricky hooks
1615   \fi}
1616
1617\unexpanded\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
1618  {\let#1\tabl_tabulate_column_inject_auto
1619   \let\\\tabl_tabulate_column_inject_auto} % brrr, will go
1620
1621\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount}
1622\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp}
1623\setvalue{\??tabulateseparator\v!small }{\def\m_tabl_tabulate_separator_factor{.25}}
1624\setvalue{\??tabulateseparator\v!medium}{\def\m_tabl_tabulate_separator_factor{.5}}
1625\setvalue{\??tabulateseparator\v!big   }{}
1626\setvalue{\??tabulateseparator\v!none  }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
1627\setvalue{\??tabulateseparator\v!grid  }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
1628
1629\def\tabl_tabulate_column_rule_separator_step#1%
1630  {\ifcsname\??tabulateseparator#1\endcsname
1631     \lastnamedcs
1632   \else
1633     \s_tabl_tabulate_separator#1\relax
1634   \fi}
1635
1636\def\tabl_tabulate_column_rule_separator_inject % can be sped up (will do when used frequently)
1637  {\bgroup
1638   \s_tabl_tabulate_separator\strutdp
1639   \ifx\p_distance\empty\else
1640     \let\m_tabl_tabulate_separator_factor\plusone
1641     \processcommacommand[\p_distance]\tabl_tabulate_column_rule_separator_step
1642     \s_tabl_tabulate_separator\m_tabl_tabulate_separator_factor\s_tabl_tabulate_separator
1643   \fi
1644   % someamble: footer or header: unfortunately a skip can trigger a page break (weird
1645   % as we have lots of nobreaks)
1646 % \ifconditional\c_tabl_tabulate_someamble\kern\else\vskip\fi\s_tabl_tabulate_separator % new
1647 % \directvspacing{\the\s_tabl_tabulate_separator}% new
1648   \directvskip\s_tabl_tabulate_separator
1649   \egroup}
1650
1651\def\tabl_tabulate_hrule_spec_ignore#1%
1652  {%\glet\currenttabulationlocalhrulecolor\empty
1653   %\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
1654   \doifelsefastoptionalcheck#1#1}
1655
1656\def\tabl_tabulate_hrule_spec_pickup#1%
1657  {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
1658   \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
1659   \doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1}
1660
1661\def\tabl_tabulate_hrule_preset_step#1%
1662  {\doifelsenumber{#1}
1663     {\global\d_tabl_tabulate_hrulethickness_local#1\d_tabl_tabulate_hrulethickness_default}
1664     {\xdef\currenttabulationlocalhrulecolor{#1}}}
1665
1666\def\tabl_tabulate_hrule_preset#1[#2]%
1667  {\rawprocesscommalist[#2]\tabl_tabulate_hrule_preset_step
1668   #1}
1669
1670\def\tabl_tabulate_hrule_inject_normal
1671  {\autorule
1672     \s!height.5\d_tabl_tabulate_hrulethickness_local
1673     \s!depth .5\d_tabl_tabulate_hrulethickness_local
1674     \s!left    \d_tabl_tabulate_indent
1675   \relax}
1676
1677\def\tabl_tabulate_hrule_inject_colored
1678  {\dousecolorparameter\currenttabulationlocalhrulecolor
1679   \tabl_tabulate_hrule_inject_normal}
1680
1681\unexpanded\def\tabl_tabulate_hrule_inject_first
1682  {\ifcase\d_tabl_tabulate_hrulethickness_local\else
1683     \tabl_tabulate_hrule_inject_normal
1684   \fi}
1685
1686\unexpanded\def\tabl_tabulate_hrule_inject_second
1687  {\ifcase\d_tabl_tabulate_hrulethickness_local\else
1688     \ifx\currenttabulationlocalhrulecolor\empty
1689       \tabl_tabulate_hrule_inject_normal
1690     \else
1691       \tabl_tabulate_hrule_inject_colored
1692     \fi
1693   \fi}
1694
1695\let\tabl_tabulate_hrule_inject\relax
1696
1697\appendtoks
1698    \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_first
1699\to \t_tabl_tabulate_initializers_first
1700
1701\appendtoks
1702    \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_second
1703\to \t_tabl_tabulate_initializers_second
1704
1705%D Color:
1706
1707% \starttabulate[||p||]
1708% \NC test \NC test \NC test \NC \NR
1709% \NC test \CC[green] \input tufte  \CC[yellow] test \NC \NR
1710% \NC test \NC test \NC test \NC \NR
1711% \NC test \NC test \NC test \NC \NR
1712% \NC test \NC test \NC test \NC \NR
1713% \NC test \NC test \NC test \NC \NR
1714% \CC[blue] test \CC[red] test \NC test \NC \NR
1715% \NC test \NC test \NC test \NC \NR
1716% \NC test \NC test \NC test \NC \NR
1717% \NC test \NC test \NC test \NC \NR
1718% \NC test \NC test \CC[gray] test \NC \NR
1719% \NC test \NC test \NC test \NC \NR
1720% \NC test \NC test \NC test \NC \NR
1721% \CC[blue] test \NC test \NC test \NC \NR
1722% \NC test \NC test \NC test \NC \NR
1723% \NC test \NC test \CC[magenta] test \NC \NR
1724% \NC test \NC test \NC test \NC \NR
1725% \NC test \CC[cyan] \dorecurse{10}{\input ward }\NC test \NC \NR
1726% \NC test \NC test \NC test \NC \NR
1727% \NC test \CC[yellow] test \NC test \NC \NR
1728% \stoptabulate
1729
1730\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
1731  {\begingroup
1732   \clf_enablebackgroundalign % was \node_backgrounds_align_initialize
1733   \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second
1734   \global\settrue\c_tabl_tabulate_has_colors
1735   \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_colorcolumn
1736     \global\c_tabl_tabulate_max_colorcolumn\c_tabl_tabulate_column
1737   \fi
1738   \expandafter\xdef\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}%
1739   \hpack \thealignbackgroundcolorattr{#1}{}% pack ?
1740   \endgroup}
1741
1742\def\tabl_tabulate_color_repeat_second % for split off lines
1743  {\begingroup
1744   \scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly !
1745   \ifcsname\??tabulatecolor\the\scratchcounter\endcsname
1746   % \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ?
1747     \hpack \expandafter\thealignbackgroundcolorattr\expandafter{\lastnamedcs}{}% pack ?
1748   \fi
1749   \endgroup}
1750
1751\let\tabl_tabulate_color_repeat\relax
1752
1753\appendtoks
1754    \let\tabl_tabulate_color_repeat\relax
1755\to \everytabulate
1756
1757\def\tabl_tabulate_color_reset
1758  {\ifcase\c_tabl_tabulate_max_colorcolumn\else
1759     \tabl_tabulate_color_reset_indeed
1760   \fi}
1761
1762% \def\tabl_tabulate_color_reset_indeed
1763%   {\dorecurse\c_tabl_tabulate_max_colorcolumn{\letgvalue{\??tabulatecolor\recurselevel}\undefined}} % slow
1764
1765\def\tabl_tabulate_color_reset_indeed
1766  {\dofastloopcs\c_tabl_tabulate_max_colorcolumn\tabl_tabulate_color_reset_step}
1767
1768\def\tabl_tabulate_color_reset_step % undefined or empty?
1769  {\expandafter\glet\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined}
1770
1771\appendtoks
1772    \tabl_tabulate_color_reset
1773\to \t_tabl_tabulate_every_after_row
1774
1775% \def\tabl_tabulate_register_par_options_indeed
1776%   {\iftrialtypesetting \else
1777%      \registerparoptions
1778%      \ifinsidefloat
1779%        % that is, an unbreakable one
1780%        \glet\tabl_tabulate_register_par_options\empty
1781%      \else
1782%        % unsafe in crossing pages, at each b...
1783%        % \glet\tabl_tabulate_register_par_options\empty
1784%      \fi
1785%    \fi}
1786%
1787% \appendtoks
1788%     \glet\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_indeed
1789% \to \everytabulate
1790
1791\def\tabl_tabulate_register_par_options_first % maybe track here if needed
1792  {}
1793
1794\def\tabl_tabulate_register_par_options_second
1795  {\registerparoptions
1796   \ifinsidefloat
1797     % that is, an unbreakable one
1798     \glet\tabl_tabulate_register_par_options\empty
1799   \else
1800     % unsafe in crossing pages, at each b...
1801     % \glet\tabl_tabulate_register_par_options\empty
1802   \fi}
1803
1804\let\tabl_tabulate_register_par_options\relax
1805
1806\appendtoks
1807    \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_first
1808\to \t_tabl_tabulate_initializers_first
1809
1810\appendtoks
1811    \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_second
1812\to \t_tabl_tabulate_initializers_second
1813
1814\appendtoks
1815    \tabl_tabulate_register_par_options
1816\to \t_tabl_tabulate_every_row
1817
1818\def\tabl_tabulate_flush_indent_indeed
1819  {\hbox to \d_tabl_tabulate_indent % pack ?
1820     {% we now have a local hsize, and since we want to
1821      % register positional info (i.e. real hsizes) we
1822      % need to reconstitute the original hsize
1823      \advance\hsize\d_tabl_tabulate_indent
1824      % this is indeed rather messy and took a few hours
1825      % to dis/uncover
1826      \the\t_tabl_tabulate_every_row
1827      \hss}}
1828
1829\def\tabl_tabulate_flush_indent
1830  {\ifnum\c_tabl_tabulate_column=\zerocount
1831     \tabl_tabulate_flush_indent_indeed
1832   \fi}
1833
1834\def\tabl_tabulate_digits{\digits}
1835
1836%D Beware, we cannot use \type {\unexpanded} on \type {\HL} cum suis, since \TEX's
1837%D hard coded noalign lookahead fails on it! I mistakenly added this for a while.
1838
1839\setvalue{\??tabulatealigning\v!normal}{0}
1840\setvalue{\??tabulatealigning\v!right }{1}
1841\setvalue{\??tabulatealigning\v!left  }{2}
1842\setvalue{\??tabulatealigning\v!middle}{3}
1843
1844\setvalue{\??tabulateheader\v!repeat}{\plusone}
1845\setvalue{\??tabulateheader\v!text  }{\plustwo}
1846
1847\unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
1848\unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
1849\unexpanded\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
1850\unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
1851
1852\let\tabl_tabulate_bbskip\relax
1853\let\tabl_tabulate_eeskip\relax
1854\let\tabl_tabulate_bskip \relax
1855\let\tabl_tabulate_eskip \relax
1856\let\tabl_tabulate_xbskip\relax
1857\let\tabl_tabulate_xeskip\relax
1858
1859\appendtoks
1860   \let\tabl_tabulate_bbskip\relax
1861  %\let\tabl_tabulate_eeskip\relax % adapted by bskip
1862   \let\tabl_tabulate_bskip \tabl_tabulate_bskip_first
1863   \let\tabl_tabulate_eskip \tabl_tabulate_eskip_first
1864   \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_first
1865   \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_first
1866\to \t_tabl_tabulate_initializers_first
1867
1868\def\tabl_tabulate_baselinecorrection % keep an eye on this one
1869  {\def\dobaselinecorrection{\vskip\dimexpr-\prevdepth+\strutdp+\strutdp\relax}% todo: mkiv
1870   \baselinecorrection}
1871
1872% some hack to prevent an allowbreak ... actually we could set up a system then
1873% that is dealt with atthe lua end in the skip handler: turn penalties with attributes
1874% values into other penalties that get removed
1875
1876\installcorenamespace{tabulatenobreak}
1877
1878\def\tabl_tabulate_break_allow{\directvpenalty\zerocount}
1879\def\tabl_tabulate_break_maybe{\directvpenalty\zerocount}
1880\def\tabl_tabulate_break_no   {\directvpenalty\plustenthousand} % ,order:2}}
1881
1882\let\tabl_tabulate_break_state_set       \relax
1883\let\tabl_tabulate_break_state_reset     \relax
1884\let\tabl_tabulate_break_state_allowbreak\tabl_tabulate_break_maybe
1885
1886% so far
1887
1888\unexpanded\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount}
1889\unexpanded\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount}
1890\unexpanded\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone}
1891\unexpanded\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo}
1892\unexpanded\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo  \zerocount}
1893\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone}
1894\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo}
1895
1896\unexpanded\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount}
1897\unexpanded\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first
1898\unexpanded\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake
1899
1900\unexpanded\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row
1901\unexpanded\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break
1902
1903\unexpanded\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row
1904\unexpanded\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break
1905
1906\unexpanded\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount}
1907\unexpanded\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone  \tabl_tabulate_set_color_column\zerocount}
1908\unexpanded\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo  \tabl_tabulate_set_color_column\zerocount}
1909\unexpanded\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount}
1910
1911%D Sort of special:
1912%D
1913%D \startbuffer
1914%D \startitemize[n]
1915%D \starttabulate[|||||]
1916%D \NC p \NC \itemtag \NC q \NC r \NC \NR
1917%D \NC p \NC \itemtag \NC q \NC r \NC \NR
1918%D \NC p \NC \itemtag \NC q \NC r \NC \NR
1919%D \NC p \NC \itemtag \NC q \NC r \NC \NR
1920%D \stoptabulate
1921%D \stopitemize
1922%D
1923%D \startitemize[n]
1924%D \starttabulate[|||||]
1925%D \NI b \NC c \NC d \NC \NR
1926%D \NC a \NI c \NC d \NC \NR
1927%D \NC a \NC b \NI d \NC \NR
1928%D \NC a \NC b \NC c \NI \NR
1929%D \stoptabulate
1930%D \stopitemize
1931%D \stopbuffer
1932%D
1933%D \typebuffer \getbuffer
1934
1935\unexpanded\def\tabl_tabulate_NI_first{\doifelsefastoptionalcheck\tabl_tbl_NI_yes\tabl_tbl_NI_nop}
1936
1937\def\tabl_tbl_NI_yes[#1]{\NC \itemtag[#1]\NC}
1938\def\tabl_tbl_NI_nop    {\NC \itemtag    \NC}
1939
1940%D The following shortcut is handy for tables where one needs bold headers:
1941
1942\unexpanded\def\tabl_tabulate_BC_first
1943  {\tabl_tabulate_column_normal\plusone\zerocount
1944   \let\fontstyle\globalfontstyle
1945   \bf}
1946
1947\appendtoks
1948    \let\VL\tabl_tabulate_VL_first
1949    \let\NC\tabl_tabulate_NC_first
1950    \let\BC\tabl_tabulate_BC_first
1951    \let\RC\tabl_tabulate_RC_first
1952    \let\HC\tabl_tabulate_HC_first
1953    \let\EQ\tabl_tabulate_EQ_first
1954    \let\RQ\tabl_tabulate_RQ_first
1955    \let\HQ\tabl_tabulate_HQ_first
1956    \let\NG\tabl_tabulate_NG_first
1957    \let\NN\tabl_tabulate_NN_first
1958    \let\ND\tabl_tabulate_ND_first
1959    \let\NR\tabl_tabulate_NR_first
1960    \let\NB\tabl_tabulate_NB_first
1961    \let\CC\tabl_tabulate_CC_first
1962    \let\CL\tabl_tabulate_CL_first
1963    \let\CM\tabl_tabulate_CM_first
1964    \let\CR\tabl_tabulate_CR_first
1965    \let\NI\tabl_tabulate_NI_first
1966\to \t_tabl_tabulate_initializers_first
1967
1968\appendtoks
1969    \let\NR\tabl_tabulate_NR_second
1970    \let\NB\tabl_tabulate_NB_second
1971\to \t_tabl_tabulate_initializers_second
1972
1973\appendtoks
1974    \let\SR\NR
1975    \let\FR\NR
1976    \let\MR\NR
1977    \let\LR\NR
1978    \let\AR\NR
1979\to \t_tabl_tabulate_initializers_first
1980
1981\unexpanded\def\tabl_tabulate_NR_common#1#2%
1982  {\global\advance\c_tabl_tabulate_noflines\plusone
1983   \global\setfalse\c_tabl_tabulate_firstflushed
1984   \global\setfalse\c_tabl_tabulate_equal
1985   \global\c_tabl_tabulate_column\zerocount
1986   \ifconditional#1\relax
1987     \tabl_tabulate_break_state_reset
1988   \fi
1989   \tabl_tabulate_pheight_reset
1990   \unskip\unskip\crcr\tabl_tabulate_flush_collected
1991   % can we omit the next one in the first run? probably
1992   \starttabulatenoalign
1993     \the\t_tabl_tabulate_every_after_row
1994     #2%
1995   \stoptabulatenoalign}
1996
1997\def\tabl_tabulate_check_penalties
1998  {\ifconditional\c_tabl_tabulate_tolerant_break\else
1999     \ifnum\c_tabl_tabulate_totalnoflines=\plusone
2000     %  \tabl_tabulate_break_allow
2001     \else
2002       \ifconditional\c_tabl_tabulate_someamble \ifcase\c_tabl_tabulate_repeathead \else
2003         \tabl_tabulate_break_allow
2004       \fi \fi
2005       \ifnum\c_tabl_tabulate_noflines=\plusone
2006         \tabl_tabulate_nobreak_inject
2007       \else \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_minusnoflines
2008         \ifnum\c_tabl_tabulate_plines_max<\plustwo
2009           \tabl_tabulate_nobreak_inject
2010         \else
2011           \tabl_tabulate_break_allow % needed with pbreak prevention
2012         \fi
2013       \else
2014         \tabl_tabulate_break_state_allowbreak
2015       \fi \fi
2016     \fi
2017   \fi
2018   \global\setfalse\c_tabl_tabulate_firstflushed}
2019
2020\unexpanded\def\tabl_tabulate_bbskip_second_split_yes
2021  {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
2022     \ifx\tabl_tabulate_flush_collected_indeed\empty\else
2023% like in mkxl
2024%        \dostarttagged\t!tabulatecell\empty
2025%        \dotagtabulatesignal
2026%        \dostoptagged
2027       \setbox0\hbox
2028     \fi
2029  \fi}
2030
2031\unexpanded\def\tabl_tabulate_eskip_second
2032  {\par\egroup
2033   \tabl_tabulate_pheight_set
2034   \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2035   \tabl_tabulate_splitoff_box}
2036
2037\unexpanded\def\tabl_tabulate_bskip_second_split_yes
2038  {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
2039     % first line
2040     \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox
2041     \bgroup
2042     \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
2043     \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
2044     % \begstrut % interferes with pre-\pars
2045     % evt: \appendtoks\begstrut\to\everypar
2046     \ignorespaces
2047     \let\tabl_tabulate_eskip\tabl_tabulate_eskip_second
2048   \else
2049     % successive lines
2050     \let\tabl_tabulate_eskip\empty
2051     \dontcomplain
2052     \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2053     \expandafter\tabl_tabulate_splitoff_box
2054   \fi}
2055
2056\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
2057\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
2058
2059\unexpanded\def\tabl_tabulate_flush_second_indeed
2060  {\glet\tabl_tabulate_flush_collected_indeed\empty
2061   \global\c_tabl_tabulate_column\zerocount
2062   \tabl_tabulate_pbreak_check
2063   \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step
2064   \global\settrue\c_tabl_tabulate_firstflushed}
2065
2066\unexpanded\def\tabl_tabulate_flush_second_step
2067  {\ifvoid\b_tabl_tabulate_current\fastloopindex\else
2068     \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}%
2069   \fi}
2070
2071\def\tabl_tabulate_flush_second
2072  {\tabulatenoalign{\tabl_tabulate_flush_second_indeed}%
2073   \tabl_tabulate_flush_collected_indeed}
2074
2075\unexpanded\def\tabl_tabulate_bskip_second_split_nop
2076  {\vtop\bgroup
2077     \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
2078     % \begstrut % interferes with pre-\pars
2079     % evt: \appendtoks\begstrut\to\everypar
2080     \ignorespaces}
2081
2082\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
2083  {\par\verticalstrut
2084   \vskip-\struttotal
2085   \egroup}
2086
2087% \let\tabl_tabulate_eskip \relax % adapted by bskip
2088% \let\tabl_tabulate_eeskip\relax % adapted by bskip
2089
2090\appendtoks
2091   \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_second
2092   \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_second
2093   \ifconditional\c_tabl_tabulate_split
2094     \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_yes
2095     \let\tabl_tabulate_bbskip\tabl_tabulate_bbskip_second_split_yes
2096   \else
2097     \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_nop
2098     \let\tabl_tabulate_eskip \tabl_tabulate_eskip_second_split_nop
2099   \fi
2100\to \t_tabl_tabulate_initializers_second
2101
2102% see ***
2103%
2104% \enabletrackers[nodes.page_vspacing]
2105% \starttext
2106%     \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate
2107% \stoptext
2108
2109\def\tabl_tabulate_XX_none
2110  {\starttabulatenoalign
2111     \tabl_tabulate_break_state_set
2112     \tabl_tabulate_hrule_spec_ignore
2113   \stoptabulatenoalign}
2114
2115\def\tabl_tabulate_FL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_FL_second_indeed}
2116\def\tabl_tabulate_ML_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_ML_second_indeed}
2117\def\tabl_tabulate_LL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_LL_second_indeed}
2118\def\tabl_tabulate_TL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_TL_second_indeed}
2119\def\tabl_tabulate_BL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_BL_second_indeed}
2120
2121\unexpanded\def\tabl_tabulate_FL_second_indeed
2122  {\ifinsidefloat\else
2123     \doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion
2124   \fi
2125   \tabl_tabulate_hrule_inject
2126   \tabl_tabulate_nobreak_inject
2127   \tabl_tabulate_column_rule_separator_inject
2128   \prevdepth\strutdp
2129   \tabl_tabulate_nobreak_inject
2130   \stoptabulatenoalign}
2131
2132\def\spac_vspacing_no_topskip % use grouped
2133  {\c_attr_skipcategory\plusten}
2134
2135\unexpanded\def\tabl_tabulate_ML_second_indeed
2136  {\tabl_tabulate_break_no
2137   \tabl_tabulate_column_rule_separator_inject
2138   \tabl_tabulate_break_no
2139   \tabl_tabulate_hrule_inject
2140   \vskip-\p_rulethickness\relax
2141   \begingroup
2142   \spac_vspacing_no_topskip
2143   \tabl_tabulate_hrule_inject
2144   \endgroup
2145   \tabl_tabulate_break_no
2146   \tabl_tabulate_column_rule_separator_inject
2147   \stoptabulatenoalign}
2148
2149\unexpanded\def\tabl_tabulate_LL_second_indeed
2150  {\tabl_tabulate_nobreak_inject
2151   \tabl_tabulate_column_rule_separator_inject
2152   \tabl_tabulate_nobreak_inject
2153   \tabl_tabulate_hrule_inject
2154   \ifinsidefloat
2155     \tabl_tabulate_inside_inbetween
2156   \else
2157     \tabl_tabulate_outside_inbetween
2158   \fi
2159   \stoptabulatenoalign}
2160
2161\unexpanded\def\tabl_tabulate_TL_second_indeed
2162  {\tabl_tabulate_nobreak_inject
2163   \tabl_tabulate_column_rule_separator_inject
2164   \tabl_tabulate_nobreak_inject
2165   \tabl_tabulate_hrule_inject
2166   \tabl_tabulate_nobreak_inject
2167   \tabl_tabulate_column_rule_separator_inject
2168  %\prevdepth\strutdp % todo, might differ between TL and BL
2169   \tabl_tabulate_nobreak_inject
2170   \stoptabulatenoalign}
2171
2172\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed
2173
2174\def\tabl_tabulate_HL_second
2175  {\csname
2176     \ifnum\c_tabl_tabulate_noflines=\zerocount                     F\else
2177     \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else
2178                                                                    M\fi\fi
2179   L\endcsname}
2180
2181\appendtoks
2182    \let\FL\tabl_tabulate_XX_none
2183    \let\ML\tabl_tabulate_XX_none
2184    \let\LL\tabl_tabulate_XX_none
2185    \let\TL\tabl_tabulate_XX_none
2186    \let\BL\tabl_tabulate_XX_none
2187    \let\HL\tabl_tabulate_XX_none
2188    \let\HR\tabl_tabulate_XX_none
2189\to \t_tabl_tabulate_initializers_first
2190
2191\appendtoks
2192    \let\FL\tabl_tabulate_FL_second
2193    \let\ML\tabl_tabulate_ML_second
2194    \let\LL\tabl_tabulate_LL_second
2195    \let\TL\tabl_tabulate_TL_second
2196    \let\BL\tabl_tabulate_BL_second
2197    \let\HL\tabl_tabulate_HL_second
2198    \let\HR\tabl_tabulate_HL_second
2199\to \t_tabl_tabulate_initializers_second
2200
2201% \def\tabulatedoHRfive % horizontal rule line (break untested)
2202%   {\starttabulatenoalign
2203%      \glet\dotabulateautoline\dotabulatelinerule
2204%     %\ifcase#1\or % todo: check what this does
2205%        \ifnum\noftabulatelines=\zerocount
2206%          \glet\dotabulateautoline\donothing
2207%        \else\ifnum\noftabulatelines=\totalnoftabulatelines
2208%          \glet\dotabulateautoline\donothing
2209%        \fi\fi
2210%     %\fi
2211%      \dotabulatenobreak
2212%    \stoptabulatenoalign
2213%    \dotabulateautoline
2214%    \starttabulatenoalign
2215%      \tabl_tabulate_break_no
2216%      \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
2217%      \ifnum\noftabulatelines=\totalnoftabulatelines
2218%        \expandafter\dotabulatenobreak
2219%      \else
2220%        \expandafter\tabl_tabulate_break_allow
2221%      \fi
2222%    \stoptabulatenoalign
2223%    \dotabulateautoline
2224%    \starttabulatenoalign
2225%      \dotabulatenobreak
2226%    \stoptabulatenoalign}
2227
2228% \dorecurse{10}{
2229%     \starttabulate[|l|]
2230%     \FL
2231%     \NC first line, bound to next rule    \NC \NR
2232%     \TL
2233%     \NC bound to previous rule            \NC \NR
2234%     \NC some line                         \NC \NR
2235%     \NC some line                         \NC \NR
2236%     \NC some line                         \NC \NR
2237%     \NC bound to next rule                \NC \NR
2238%     \ML
2239%     \NC bound to previous rule            \NC \NR
2240%     \NC bound to next rule                \NC \NR
2241%     \BL
2242%     \NC last line, bound to previous rule \NC \NR
2243%     \LL
2244%     \stoptabulate
2245% }
2246
2247% This needs checking:
2248
2249\def\tabulaterule    {\HR} % a rule with lineheight
2250\def\tabulateline    {\HL} % just a spaced rule
2251\def\tabulateautorule{\HR}%
2252\def\tabulateautoline{\HL} % no longer different (to be looked into)
2253
2254%D When support for vertical rules we needed a way to pick up the specification for
2255%D the final rule and a \type {|{}} interface was chosen. As a result parsing had to
2256%D become more complex and I was not in the mood for messing up the code too much.
2257%D Therefore from now on the preamble is split by \LUA. There are definitely more
2258%D places where we can use \LUA\ code (for instance in alignment of numbers. The
2259%D repeat parser is replace at the \LUA\ end as well.
2260
2261\let\tabl_tabulate_flush_collected       \empty
2262\let\tabl_tabulate_flush_collected_indeed\empty
2263
2264\let\v_tabl_tabulate_align\!!zerocount
2265
2266\def\tabl_tabulate_check_side_float % new per 29-07-2016
2267  {\ifdefined\page_sides_check_floats_indeed
2268     \page_sides_check_floats_indeed
2269     \ifdim\hangindent>\zeropoint
2270       \advance\d_tabl_tabulate_indent\hangindent
2271     \fi
2272   \fi}
2273
2274\def\tabl_tabulate_set_local_hsize
2275  {\setlocalhsize
2276   \hsize\localhsize}
2277
2278\def\tabl_tabulate_process
2279  {\c_tabl_tabulate_pass\plusone
2280   \tabl_tabulate_check_full_content
2281   \edef\v_tabl_tabulate_align{\ifcsname\??tabulatealigning\p_align\endcsname\lastnamedcs\else0\fi}%
2282   \s_tabl_tabulate_first.5\d_tabl_tabulate_unit
2283   \s_tabl_tabulate_last\s_tabl_tabulate_first
2284   \s_tabl_tabulate_pre\zeropoint
2285   \s_tabl_tabulate_post\zeropoint
2286   \global\c_tabl_tabulate_columns\zerocount
2287   \global\c_tabl_tabulate_nofauto\zerocount
2288   \global\c_tabl_tabulate_noflines\zerocount
2289   \c_tabl_tabulate_totalnoflines\zerocount
2290   \c_tabl_tabulate_minusnoflines\zerocount
2291   \global\d_tabl_tabulate_width_p\zeropoint
2292   \global\d_tabl_tabulate_width_w\zeropoint
2293   \global\setfalse\c_tabl_tabulate_equal
2294   \tabl_tabulate_pheight_reset
2295   \tabskip\zeropoint
2296   \ifinsidesplitfloat
2297     \donetrue
2298   \else\ifinsidefloat
2299     \donefalse
2300   \else
2301     \donetrue
2302   \fi\fi
2303   \global\c_tabl_tabulate_repeathead
2304     \ifdone
2305       \ifcsname\??tabulateheader\tabulationparameter\c!header\endcsname
2306         \lastnamedcs
2307       \else
2308         \zerocount
2309       \fi
2310     \else
2311       \zerocount
2312     \fi
2313   %
2314   \the\t_tabl_tabulate_initializers_first % collect more here
2315   %
2316   \glet\tabl_tabulate_flush_collected\empty
2317   \ifdim\d_tabl_tabulate_margin>\zeropoint
2318     \t_tabl_tabulate_preamble
2319       {\aligntab
2320        \tabl_tabulate_flush_indent
2321        \strut
2322        \alignmark\alignmark
2323        \tabskip\d_tabl_tabulate_margin
2324        \strut
2325        \aligntab
2326        \alignmark\alignmark
2327        \tabskip\zeropoint}%
2328   \else
2329     \t_tabl_tabulate_preamble
2330       {\aligntab
2331        \tabl_tabulate_flush_indent
2332        \strut
2333        \alignmark\alignmark
2334        \aligntab
2335        \alignmark\alignmark
2336        \tabskip\zeropoint}%
2337   \fi
2338   \d_tabl_tabulate_width\zeropoint
2339   % these counters are set at the lua end
2340   \c_tabl_tabulate_nofcolumns         \zerocount
2341   \c_tabl_tabulate_has_rule_spec_first\zerocount
2342   \c_tabl_tabulate_has_rule_spec_last \zerocount
2343   \clf_presettabulate{\detokenizedtabulationparameter\c!format}%
2344   %
2345   \d_tabl_tabulate_width\zeropoint
2346   \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
2347   \toksapp\t_tabl_tabulate_preamble{%
2348     \aligntab\alignmark\alignmark
2349     \global\advance\c_tabl_tabulate_column\plusone % maybe just set it already
2350   }%
2351   \toksapp\t_tabl_tabulate_dummy{%
2352     \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
2353   }%
2354   \global\c_tabl_tabulate_column\zerocount
2355   \tabl_tabulate_pheight_reset
2356   \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2357   \ifx\p_indenting\v!no
2358     \forgetparindent
2359   \fi
2360   \ifinsidefloat
2361     \d_tabl_tabulate_indent\zeropoint
2362   \else
2363     \tabl_tabulate_check_side_float
2364     \tabl_tabulate_set_local_hsize
2365   \fi
2366   \dontcomplain
2367   \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved
2368   \everypar\everytabulatepar
2369   \setbox\scratchbox\vbox % outside \if because of line counting
2370     {\notesenabledfalse
2371      \d_tabl_tabulate_indent\zeropoint
2372      \settrialtypesetting % very important
2373      \anch_backgrounds_text_level_start
2374      \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}%
2375      \anch_backgrounds_text_level_stop
2376      \ifcase\c_anch_backgrounds_text_state\else
2377        \global\settrue\tablehaspositions
2378      \fi
2379   \ifnum\c_tabl_tabulate_nofauto>\zerocount
2380     % so, even if the natural size is larger, in the final run, we force the calculated width
2381     \d_tabl_tabulate_width\dimexpr\hsize-\wd\scratchbox-\d_tabl_tabulate_width_p-\d_tabl_tabulate_width_w\relax
2382     \ifnum\c_tabl_tabulate_nofauto>\zerocount
2383       \divide\d_tabl_tabulate_width \c_tabl_tabulate_nofauto\relax
2384     \fi
2385   \fi
2386   \setbox\scratchbox\emptybox % free memory
2387   \ifconditional\c_tabl_tabulate_split
2388     \splittopskip\strutht
2389     \glet\tabl_tabulate_flush_collected_indeed\empty
2390     \glet\tabl_tabulate_flush_collected\tabl_tabulate_flush_second
2391   \fi
2392   \c_tabl_tabulate_totalnoflines\c_tabl_tabulate_noflines
2393   \c_tabl_tabulate_minusnoflines\numexpr\c_tabl_tabulate_noflines+\minusone\relax
2394   \global\c_tabl_tabulate_noflines\zerocount
2395   %
2396   \c_tabl_tabulate_pass\plustwo % final pass
2397   \the\t_tabl_tabulate_initializers_second % collect more here
2398   %
2399   \ifx\p_line\v!line
2400     \let\HL\HR
2401     \let\tabulateautoline\tabulateautorule
2402     \let\tabulateline\tabulaterule
2403   \fi
2404   %
2405   \ifcase\c_tabl_tabulate_repeathead
2406     \ifinsidesplitfloat
2407        \global\setbox\b_tabl_tabulate\vbox \bgroup
2408      \else
2409        \startframedcontent[\tabulationparameter\c!frame]%
2410      \fi
2411   \else
2412     \global\setbox\b_tabl_tabulate\vbox \bgroup
2413   \fi
2414   %
2415   \dostarttaggedchained\t!tabulate\empty\??tabulation
2416   \dostarttagged\t!tabulaterow\empty
2417   \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
2418   \toksapp\everycr{%
2419     \noalign{\the\t_tabl_tabulate_every_real_row}%
2420     \dostoptagged
2421     \dostarttagged\t!tabulaterow\empty
2422   }%
2423    % we are in sync but just to be sure:
2424   \synchronizedisplaydirection
2425   \synchronizeinlinedirection
2426   \halign
2427     \usedirectionparameterreverse\tabulateparameter
2428     \expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
2429   \dostoptagged
2430   \dostoptagged
2431   \ifhmode\par\prevdepth\strutdp\fi % temporary hack
2432   \ifx\p_distance\v!grid
2433     \vskip-\strutdp % experimental tm-prikkels
2434   \fi
2435   %
2436   \ifcase\c_tabl_tabulate_repeathead
2437     \ifinsidesplitfloat
2438       \egroup % box
2439       \egroup % settings
2440       \tabl_split_box\b_tabl_tabulate
2441     \else
2442       \stopframedcontent
2443       \egroup
2444     \fi
2445   \else
2446     \egroup % box
2447     \egroup % settings
2448     \tabl_split_box\b_tabl_tabulate
2449   \fi
2450   %
2451   \ifinsidefloat
2452     \tabl_tabulate_inside_after
2453   \else
2454     \tabl_tabulate_outside_after
2455   \fi
2456   \egroup} % whole thing
2457
2458% \egroup
2459
2460% \setuptabulate[split=yes,header=text,title=Vervolg van Tabel]
2461%
2462% % \starttabulatehead
2463% % \NC test \NC hans\NC \NR
2464% % \stoptabulatehead
2465%
2466% \starttabulate
2467% \NC test \NC \input tufte \relax \NC \NR
2468% \NC test \NC \input knuth \relax \NC \NR
2469% \NC test \NC \input knuth \relax \NC \NR
2470% \NC test \NC \input tufte \relax \NC \NR
2471% \NC test \NC \input tufte \relax \NC \NR
2472% \NC test \NC \input tufte \relax \NC \NR
2473% \stoptabulate
2474
2475\def\tabl_split_box#1% #1 <> 0/2 / derived from the one in core-ntb.tex
2476  {\ifinsidesplitfloat
2477     \tabl_split_box_indeed#1%
2478   \else\ifinsidefloat
2479     \unvbox#1%
2480   \else
2481     \tabl_split_box_indeed#1%
2482   \fi\fi}
2483
2484\def\tabl_split_box_indeed#1%
2485  {\resettsplit
2486   \def\tsplitminimumfreelines{2}%
2487   \def\tsplitminimumfreespace{0pt}%
2488   \setbox\tsplitcontent\box#1%
2489   \ifcase\c_tabl_tabulate_repeathead\or
2490     \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
2491     \setbox\tsplithead\vbox{\unvbox\tsplithead}%
2492   \or
2493     \setbox\tsplithead\vbox{\hbox{\strut\tabulationparameter\c!title}}%
2494   \fi
2495   \handletsplit}
2496
2497%D \starttyping
2498%D \setuptabulate[split=no,rule=line]
2499%D
2500%D \starttabulate
2501%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2502%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2503%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2504%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2505%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2506%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2507%D \stoptabulate
2508%D \stoptyping
2509
2510%D Spacing:
2511%
2512% \starttabulate
2513% \NC text \NC text \NC \NR
2514% \TB[small]
2515% \NC text \NC text \NC \NR
2516% \TB[4*big]
2517% \NC text \NC text \NC \NR
2518% \stoptabulate
2519
2520\def\tabl_tabulate_TB
2521  {\starttabulatenoalign
2522   \dosingleempty\tabl_tabulate_TB_indeed}
2523
2524\def\tabl_tabulate_TB_indeed[#1]%
2525  {\iffirstargument
2526     \blank[#1]
2527   \else\ifx\m_tabl_tabulate_blank_default\empty
2528     \blank
2529   \else
2530     \blank[\m_tabl_tabulate_blank_default]%
2531   \fi\fi
2532   \stoptabulatenoalign}
2533
2534% to be tested:
2535%
2536% \def\tabl_tabulate_TB
2537%   {\starttabulatenoalign
2538%    \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop}
2539%
2540% \def\tabl_tabulate_TB_yes[#1]%
2541%   {\blank[#1]
2542%    \stoptabulatenoalign}
2543%
2544% \def\tabl_tabulate_TB_nop[#1]%
2545%   {\blank
2546%    \stoptabulatenoalign}
2547
2548\appendtoks
2549    \let\TB\tabl_tabulate_TB
2550\to \everytabulate
2551
2552% %D Between alignment lines certain rules apply, and even a simple test can mess
2553% %D up a table, which is why we have a special test facilityL
2554% %D
2555% %D \startbuffer
2556% %D \starttabulate[|l|p|]
2557% %D \NC 1test \NC test \NC \NR
2558% %D \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
2559% %D \stoptabulate
2560% %D \stopbuffer
2561% %D
2562% %D \typebuffer \getbuffer
2563%
2564% \def\tableifelse#1% should be tabulatenoalign then
2565%   {\tablenoalign
2566%      {#1%
2567%        {\aftergroup \firstoftwoarguments}%
2568%        {\aftergroup\secondoftwoarguments}}}
2569%
2570% \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
2571
2572%D Some new trickery:
2573%D
2574%D \startbuffer
2575%D \settrue\c_tabl_tabulate_splitoff_whitespace
2576%D
2577%D \starttabulate[|p(2cm)|p(2cm)|p(2cm)|]
2578%D     \NC test 1a \NC test 2a \NC test 3a
2579%D                                 \par
2580%D                                 test 3b          \NC \NR
2581%D     \NC test 1a \NC test 2a \NC test 3a
2582%D                                 \blank[line]
2583%D                                 test 3b          \NC \NR
2584%D     \NC test 1a \NC test 2a \NC test 3a
2585%D                                 \blank[halfline]
2586%D                                 test 3b
2587%D                                 \blank[halfline]
2588%D                                 test 3c          \NC \NR
2589%D     \NC \blank  \NC \blank  \NC \blank           \NC \NR
2590%D     \NC test 1a \NC test 2a \NC test 3a
2591%D                                 \blank[halfline]
2592%D                                 test 3b
2593%D                                 \blank[halfline]
2594%D                                 test 3c          \NC \NR
2595%D     \NC \blank  \NC \blank  \NC                  \NC \NR
2596%D     \NC test 1a
2597%D         \par
2598%D         test 1b
2599%D         \par
2600%D         test 1b \NC test 2a
2601%D                     \par
2602%D                     test 2b
2603%D                     \par
2604%D                     test 2b \NC test 3a          \NC \NR
2605%D     \NC test 1a
2606%D         \blank
2607%D         test 1b
2608%D         \par
2609%D         test 1b \NC test 2a
2610%D                     \par
2611%D                     test 2b
2612%D                     \blank
2613%D                     test 2b \NC test 3a          \NC \NR
2614%D \stoptabulate
2615%D \stopbuffer
2616%D
2617%D \typebuffer \start \getbuffer \stop
2618
2619% \starttabulatie[|mc|]
2620% \NC \digits{100.000,00} \NC\NR
2621% \NC \digits{@10.000,00} \NC\NR
2622% \NC \digits{@@@.100,00} \NC\NR
2623% \NC \digits{@@@.@10,@@} \NC\NR
2624% \NC \digits{@@@.@@1,@@} \NC\NR
2625% \stoptabulatie
2626%
2627% \starttabulatie[|mc|]
2628% \ND 100.000,00 \NC\NR
2629% \ND @10.000,00 \NC\NR
2630% \ND @@@.100,00 \NC\NR
2631% \ND @@@.@10,@@ \NC\NR
2632% \ND @@@.@@1,@@ \NC\NR
2633% \stoptabulatie
2634%
2635% \starttabulatie[|c|]
2636% \ND $100.000,00$ \NC\NR
2637% \ND $@10.000,00$ \NC\NR
2638% \ND $@@@.100,00$ \NC\NR
2639% \ND $@@@.@10,@@$ \NC\NR
2640% \ND $@@@.@@1,@@$ \NC\NR
2641% \stoptabulatie
2642%
2643% \starttabulatie[|c|]
2644% \NC $\digits 100.000,00 $ \NC\NR
2645% \NC $\digits @10.000,00 $ \NC\NR
2646% \NC $\digits @@@.100,00 $ \NC\NR
2647% \NC $\digits @@@.@10,@@ $ \NC\NR
2648% \NC $\digits @@@.@@1,@@ $ \NC\NR
2649% \stoptabulatie
2650%
2651% \starttabulatie[|c|]
2652% \NC \digits $100.000,00$ \NC\NR
2653% \NC \digits $@10.000,00$ \NC\NR
2654% \NC \digits $@@@.100,00$ \NC\NR
2655% \NC \digits $@@@.@10,@@$ \NC\NR
2656% \NC \digits $@@@.@@1,@@$ \NC\NR
2657% \stoptabulatie
2658
2659%D Predefined categories (moved from core-mis):
2660
2661\definetabulate
2662  [\v!legend]
2663  [|emj1|i1|mR|]
2664
2665\setuptabulate
2666  [\v!legend]
2667  [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}]
2668
2669\definetabulate
2670  [\v!legend][\v!two]
2671  [|emj1|emk1|i1|mR|]
2672
2673\definetabulate
2674  [\v!fact]
2675  [|R|ecmj1|i1mR|]
2676
2677\setuptabulate
2678  [\v!fact]
2679  [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}]
2680
2681%D Another example:
2682%D
2683%D \starttyping
2684%D \definetabulate
2685%D   [whatever]
2686%D   [|l|r|]
2687%D
2688%D \definetabulate
2689%D   [whatever][else]
2690%D   [|l|c|r|]
2691%D
2692%D \startwhatever
2693%D \NC l    \NC r     \NC \NR
2694%D \NC left \NC right \NC \NR
2695%D \stopwhatever
2696%D
2697%D \startwhatever[else]
2698%D \NC l    \NC m      \NC r     \NC \NR
2699%D \NC left \NC middle \NC right \NC \NR
2700%D \stopwhatever
2701%D
2702%D \startwhatever[else][format={|c|c|c|c|}]
2703%D \NC l    \NC m      \NC m      \NC r     \NC \NR
2704%D \NC left \NC middle \NC middle \NC right \NC \NR
2705%D \stopwhatever
2706%D \stoptyping
2707
2708%D This is needed because we sometimes use the english command in tracing macros. In
2709%D fact, most detailed tracing macros that are done with \LUA\ only work in the
2710%D english interface anyway.
2711
2712% \definetabulate[tabulate] \setuptabulate[tabulate][\c!format=\v!none] % so no \v! here
2713
2714\newconditional\c_tabl_generic
2715
2716\unexpanded\setuvalue{starttabulate}%
2717  {\bgroup % whole thing
2718   \settrue\c_tabl_generic
2719   \let\currenttabulationparent\empty
2720   \dodoubleempty\tabl_start_regular}
2721
2722\letvalue{stoptabulate}\relax
2723
2724%D The following helpers are just there because we also have them at the \LUA\ end:
2725%D
2726%D \startbuffer
2727%D \starttabulate[|l|c|r|]
2728%D     \tabulaterow    {a,b,c}
2729%D     \tabulaterowbold{aa,bb,cc}
2730%D     \tabulaterowtype{aaa,bbb,ccc}
2731%D     \tabulaterowtyp {aaaa,bbbb,cccc}
2732%D \stoptabulate
2733%D \stopbuffer
2734%D
2735%D \typebuffer \getbuffer
2736
2737\def\tabl_tabulate_compact_row#1#2%
2738  {\NC\tabl_tabulate_compact_step#1#2,\end,}
2739
2740\def\tabl_tabulate_compact_step#1#2#3,%
2741  {\ifx#2\end
2742     \NR
2743     \expandafter\gobbleoneargument
2744   \else
2745     #1{#2#3}\NC
2746     \expandafter\tabl_tabulate_compact_step
2747   \fi#1}
2748
2749\unexpanded\def\tabulaterow    {\tabl_tabulate_compact_row\relax}
2750\unexpanded\def\tabulaterowbold{\tabl_tabulate_compact_row\bold}
2751\unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type}
2752\unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ}
2753
2754%D Here we plug in a row background feature. As we only have support for
2755%D \type {frame=name} we can use these variables.
2756%D
2757%D \starttyping
2758%D \startuseMPgraphic{foo}
2759%D     fill unitsquare
2760%D         xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8)
2761%D         randomized ExHeight
2762%D         shifted  (-ExHeight/8,ExHeight/16)
2763%D         withcolor RuleColor ;
2764%D \stopuseMPgraphic
2765%D
2766%D \setuptabulate % wel only have frame=name so we can use these:
2767%D   [background=foo,
2768%D    backgroundcolor=darkred,
2769%D    foregroundcolor=white]
2770%D
2771%D \definelinefiller[foo][mp=foo,color=darkgreen]
2772%D \definelinefiller[bar][mp=foo,color=darkred]
2773%D
2774%D \starttabulate[|||]
2775%D     \DB foo \BC bar \BC \NR
2776%D     \NC foo \NC bar \NC \NR
2777%D     \NC foo \NC bar \NC \NR
2778%D     \NC foo \NC bar \NC \NR
2779%D     \NC foo \NC bar \NC \NR
2780%D \stoptabulate
2781%D
2782%D \starttabulate[|||]
2783%D     \PB foo \BC bar \BC \NR
2784%D     \NC foo \NC bar \NC \NR
2785%D     \NC foo \NC bar \NC \NR
2786%D     \NC foo \NC bar \NC \NR
2787%D     \NC foo \NC bar \NC \NR
2788%D \stoptabulate
2789%D
2790%D \starttabulate[|||]
2791%D     \FB[bar] foo \BC bar \BC \NR
2792%D     \NC      foo \NC bar \NC \NR
2793%D     \NC      foo \NC bar \NC \NR
2794%D     \NC      foo \NC bar \NC \NR
2795%D     \NC      foo \NC bar \NC \NR
2796%D \stoptabulate
2797%D
2798%D \startnarrower
2799%D     \starttabulate[|||]
2800%D         \DB foo \DB bar \BC \NR
2801%D         \NC foo \NC bar \NC \NR
2802%D         \NC foo \NC bar \NC \NR
2803%D         \NC foo \NC bar \NC \NR
2804%D         \NC foo \NC bar \NC \NR
2805%D     \stoptabulate
2806%D \stopnarrower
2807%D
2808%D \starttabulate[|||]
2809%D     \BC          foo \BC bar \BC \NR
2810%D     \NL[magenta] foo \NC bar \NC \NR
2811%D     \NL[yellow]  foo \NC bar \NC \NR
2812%D     \NL[cyan]    foo \NC bar \NC \NR
2813%D     \NL[gray]    foo \NC bar \NC \NR
2814%D \stoptabulate
2815%D
2816%D \starttabulate
2817%D     \NL[red]     foo \NC bar \NC \NR
2818%D     \NL[green]   foo \NL[red] bar \NC \NR
2819%D     \NC          foo \NC bar \NC \NR
2820%D     \NL[blue]    foo \NC \input tufte  \NC \NR
2821%D     \NL[gray]    foo \NC bar \NC \NR
2822%D     \NL[yellow]  foo \NC bar \NC \NR
2823%D \stoptabulate
2824%D \stoptyping
2825
2826% \setuptabulate
2827%   [\c!background=,
2828%    \c!backgroundcolor=,
2829%    \c!foregroundcolor=,
2830%    \c!foregroundstyle=]
2831
2832\let\m_table_current_row_background              \empty
2833\let\m_table_current_row_background_default      \empty
2834\let\m_table_current_row_background_filler       \empty
2835\let\m_table_current_row_background_defaultfiller\empty
2836\let\m_table_current_row_background_auto         \empty
2837
2838\unexpanded\def\tabl_register_row_background#1%
2839  {\xdef\m_table_current_row_background{#1}}
2840
2841\unexpanded\def\tabl_register_row_background_filler#1%
2842  {\xdef\m_table_current_row_background_filler{#1}}
2843
2844\unexpanded\def\tabl_synchronize_row_background
2845  {\iftrialtypesetting\else
2846     \ifx\m_table_current_row_background_filler\empty
2847       \ifx\m_table_current_row_background\empty
2848         % nothing
2849         \tabl_synchronize_row_background_dummy
2850       \else
2851         \tabl_synchronize_row_background_indeed\m_table_current_row_background
2852       \fi
2853     \else
2854       \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler
2855     \fi
2856   \fi}
2857
2858\unexpanded\def\tabl_synchronize_row_background_dummy
2859  {\iftrialtypesetting\else
2860     \begingroup
2861    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint
2862     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint
2863     \endgroup
2864   \fi}
2865
2866\unexpanded\def\tabl_synchronize_row_background_indeed#1%
2867  {\iftrialtypesetting\else
2868     \begingroup
2869     \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
2870     \dousecolorparameter{#1}%
2871     \setbox\scratchbox\hpack{}%
2872    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
2873     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
2874     \endgroup
2875   \fi}
2876
2877\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1%
2878  {\iftrialtypesetting\else
2879     \begingroup
2880     \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
2881     \node_linefiller_set{#1}%
2882     \setbox\scratchbox\hpack{}%
2883    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
2884     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
2885     \endgroup
2886   \fi}
2887
2888\appendtoks
2889    \glet\m_table_current_row_background\empty
2890    \glet\m_table_current_row_background_filler\empty
2891    \global\c_tabl_tabulate_nofrealrows\zerocount
2892    \global\c_tabl_tabulate_autocolor\zerocount
2893    \clf_resetbackgroundrowdata
2894\to \t_tabl_tabulate_initializers_first
2895
2896\appendtoks
2897    \glet\m_table_current_row_background\empty
2898    \glet\m_table_current_row_background_filler\empty
2899    \global\c_tabl_tabulate_nofrealrows\zerocount
2900    \global\c_tabl_tabulate_autocolor\zerocount
2901    \clf_resetbackgroundrowdata
2902\to \t_tabl_tabulate_initializers_second
2903
2904\appendtoks
2905    \tabl_synchronize_row_background
2906\to \t_tabl_tabulate_every_real_row
2907
2908\appendtoks
2909    \glet\m_table_current_row_background\empty
2910    \glet\m_table_current_row_background_filler\empty
2911\to \t_tabl_tabulate_every_after_row
2912
2913\unexpanded\def\tabl_tabulate_NL_first[#1]%
2914  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2915   \ifcase\c_tabl_tabulate_column\or
2916     \tabl_register_row_background{#1}%
2917   \fi
2918   \ignorespaces}
2919
2920\unexpanded\def\tabl_tabulate_ND_first
2921  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2922   \ifcase\c_tabl_tabulate_column\or
2923     \tabl_register_row_background\m_table_current_row_background_default
2924   \fi
2925   \ignorespaces}
2926
2927\unexpanded\def\tabl_tabulate_LB_first[#1]%
2928  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2929   \ifcase\c_tabl_tabulate_column\or
2930     \tabl_register_row_background{#1}%
2931   \fi
2932   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2933   \ignorespaces}
2934
2935\unexpanded\def\tabl_tabulate_DB_first
2936  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2937   \ifcase\c_tabl_tabulate_column\or
2938     \tabl_register_row_background\m_table_current_row_background_default
2939   \fi
2940   \let\fontstyle\globalfontstyle
2941   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2942   \ignorespaces}
2943
2944\unexpanded\def\tabl_tabulate_NF_first[#1]%
2945  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2946   \ifcase\c_tabl_tabulate_column\or
2947     \tabl_register_row_background_filler{#1}%
2948   \fi
2949   \ignorespaces}
2950
2951\unexpanded\def\tabl_tabulate_NP_first
2952  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2953   \ifcase\c_tabl_tabulate_column\or
2954     \tabl_register_row_background_filler\m_table_current_row_background_default_filler
2955   \fi
2956   \ignorespaces}
2957
2958\unexpanded\def\tabl_tabulate_FB_first[#1]%
2959  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2960   \ifcase\c_tabl_tabulate_column\or
2961     \tabl_register_row_background_filler{#1}%
2962   \fi
2963   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2964   \ignorespaces}
2965
2966\unexpanded\def\tabl_tabulate_PB_first
2967  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2968   \ifcase\c_tabl_tabulate_column\or
2969     \tabl_register_row_background_filler\m_table_current_row_background_default_filler
2970   \fi
2971   \let\fontstyle\globalfontstyle
2972   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2973   \ignorespaces}
2974
2975\unexpanded\def\tabl_tabulate_BC_first % overloaded
2976  {\tabl_tabulate_column_normal\plusone\zerocount
2977   \let\fontstyle\globalfontstyle
2978   \ifx\m_table_current_row_background\empty
2979     \ifx\m_table_current_row_background_filler\empty
2980       \usetabulationstyleandcolor\c!headstyle\c!headcolor
2981     \else
2982       \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2983     \fi
2984   \else
2985     \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2986   \fi}
2987
2988\unexpanded\def\tabl_tabulate_A_first
2989  {\global\advance\c_tabl_tabulate_autocolor\plusone
2990   \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
2991   \ifx\m_table_current_row_background_auto\empty
2992     \global\c_tabl_tabulate_autocolor\plusone
2993     \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
2994   \fi
2995   \ifx\m_table_current_row_background_auto\empty
2996     \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default
2997   \fi
2998   \tabl_register_row_background{\m_table_current_row_background_auto}}
2999
3000\unexpanded\def\tabl_tabulate_NA_first
3001  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
3002   \iftrialtypesetting\else
3003     \ifcase\c_tabl_tabulate_column\or
3004       \tabl_tabulate_A_first
3005     \fi
3006   \fi
3007   \ignorespaces}
3008
3009\unexpanded\def\tabl_tabulate_BA_first
3010  {\tabl_tabulate_column_normal\plusone\zerocount\relax
3011   \iftrialtypesetting\else
3012     \ifcase\c_tabl_tabulate_column\or
3013       \tabl_tabulate_A_first
3014     \fi
3015   \fi
3016   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
3017   \ignorespaces}
3018
3019\appendtoks
3020    \let\NL\tabl_tabulate_NL_first % NC with Line
3021    \let\ND\tabl_tabulate_ND_first % NC with Default Line
3022    \let\LB\tabl_tabulate_LB_first % BC with Line
3023    \let\DB\tabl_tabulate_DB_first % BC with Default Line
3024    \let\NF\tabl_tabulate_NF_first % NC with Filler
3025    \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler
3026    \let\FB\tabl_tabulate_FB_first % BC with Filler
3027    \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler
3028    \let\NA\tabl_tabulate_NA_first % NC with Auto Line
3029    \let\BA\tabl_tabulate_BA_first % NC with Auto Line
3030\to \t_tabl_tabulate_initializers_first
3031
3032\appendtoks
3033   \edef\m_table_current_row_background_default       {\tabulateparameter\c!backgroundcolor}%
3034   \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}%
3035   \let \m_table_current_row_background_auto           \empty
3036\to \everytabulate
3037
3038\setuptabulate
3039  [\c!headcolor=,
3040   \c!headstyle=\bf,
3041   \c!backgroundcolor=\tabulationparameter\c!rulecolor,
3042   \c!foregroundcolor=,
3043   \c!foregroundstyle=\tabulationparameter\c!headstyle]
3044
3045\protect \endinput
3046