tabl-tbl.mkiv /size: 104 Kb    last modification: 2023-12-21 09:44
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       \setbox0\hbox
2024     \fi
2025  \fi}
2026
2027\unexpanded\def\tabl_tabulate_eskip_second
2028  {\par\egroup
2029   \tabl_tabulate_pheight_set
2030   \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2031   \tabl_tabulate_splitoff_box}
2032
2033\unexpanded\def\tabl_tabulate_bskip_second_split_yes
2034  {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
2035     % first line
2036     \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox
2037     \bgroup
2038     \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
2039     \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
2040     % \begstrut % interferes with pre-\pars
2041     % evt: \appendtoks\begstrut\to\everypar
2042     \ignorespaces
2043     \let\tabl_tabulate_eskip\tabl_tabulate_eskip_second
2044   \else
2045     % successive lines
2046     \let\tabl_tabulate_eskip\empty
2047     \dontcomplain
2048     \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2049     \expandafter\tabl_tabulate_splitoff_box
2050   \fi}
2051
2052\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
2053\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
2054
2055\unexpanded\def\tabl_tabulate_flush_second_indeed
2056  {\glet\tabl_tabulate_flush_collected_indeed\empty
2057   \global\c_tabl_tabulate_column\zerocount
2058   \tabl_tabulate_pbreak_check
2059   \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step
2060   \global\settrue\c_tabl_tabulate_firstflushed}
2061
2062\unexpanded\def\tabl_tabulate_flush_second_step
2063  {\ifvoid\b_tabl_tabulate_current\fastloopindex\else
2064     \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}%
2065   \fi}
2066
2067\def\tabl_tabulate_flush_second
2068  {\tabulatenoalign{\tabl_tabulate_flush_second_indeed}%
2069   \tabl_tabulate_flush_collected_indeed}
2070
2071\unexpanded\def\tabl_tabulate_bskip_second_split_nop
2072  {\vtop\bgroup
2073     \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
2074     % \begstrut % interferes with pre-\pars
2075     % evt: \appendtoks\begstrut\to\everypar
2076     \ignorespaces}
2077
2078\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
2079  {\par\verticalstrut
2080   \vskip-\struttotal
2081   \egroup}
2082
2083% \let\tabl_tabulate_eskip \relax % adapted by bskip
2084% \let\tabl_tabulate_eeskip\relax % adapted by bskip
2085
2086\appendtoks
2087   \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_second
2088   \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_second
2089   \ifconditional\c_tabl_tabulate_split
2090     \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_yes
2091     \let\tabl_tabulate_bbskip\tabl_tabulate_bbskip_second_split_yes
2092   \else
2093     \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_nop
2094     \let\tabl_tabulate_eskip \tabl_tabulate_eskip_second_split_nop
2095   \fi
2096\to \t_tabl_tabulate_initializers_second
2097
2098% see ***
2099%
2100% \enabletrackers[nodes.page_vspacing]
2101% \starttext
2102%     \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate
2103% \stoptext
2104
2105\def\tabl_tabulate_XX_none
2106  {\starttabulatenoalign
2107     \tabl_tabulate_break_state_set
2108     \tabl_tabulate_hrule_spec_ignore
2109   \stoptabulatenoalign}
2110
2111\def\tabl_tabulate_FL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_FL_second_indeed}
2112\def\tabl_tabulate_ML_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_ML_second_indeed}
2113\def\tabl_tabulate_LL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_LL_second_indeed}
2114\def\tabl_tabulate_TL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_TL_second_indeed}
2115\def\tabl_tabulate_BL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_BL_second_indeed}
2116
2117\unexpanded\def\tabl_tabulate_FL_second_indeed
2118  {\ifinsidefloat\else
2119     \doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion
2120   \fi
2121   \tabl_tabulate_hrule_inject
2122   \tabl_tabulate_nobreak_inject
2123   \tabl_tabulate_column_rule_separator_inject
2124   \prevdepth\strutdp
2125   \tabl_tabulate_nobreak_inject
2126   \stoptabulatenoalign}
2127
2128\def\spac_vspacing_no_topskip % use grouped
2129  {\c_attr_skipcategory\plusten}
2130
2131\unexpanded\def\tabl_tabulate_ML_second_indeed
2132  {\tabl_tabulate_break_no
2133   \tabl_tabulate_column_rule_separator_inject
2134   \tabl_tabulate_break_no
2135   \tabl_tabulate_hrule_inject
2136   \vskip-\p_rulethickness\relax
2137   \begingroup
2138   \spac_vspacing_no_topskip
2139   \tabl_tabulate_hrule_inject
2140   \endgroup
2141   \tabl_tabulate_break_no
2142   \tabl_tabulate_column_rule_separator_inject
2143   \stoptabulatenoalign}
2144
2145\unexpanded\def\tabl_tabulate_LL_second_indeed
2146  {\tabl_tabulate_nobreak_inject
2147   \tabl_tabulate_column_rule_separator_inject
2148   \tabl_tabulate_nobreak_inject
2149   \tabl_tabulate_hrule_inject
2150   \ifinsidefloat
2151     \tabl_tabulate_inside_inbetween
2152   \else
2153     \tabl_tabulate_outside_inbetween
2154   \fi
2155   \stoptabulatenoalign}
2156
2157\unexpanded\def\tabl_tabulate_TL_second_indeed
2158  {\tabl_tabulate_nobreak_inject
2159   \tabl_tabulate_column_rule_separator_inject
2160   \tabl_tabulate_nobreak_inject
2161   \tabl_tabulate_hrule_inject
2162   \tabl_tabulate_nobreak_inject
2163   \tabl_tabulate_column_rule_separator_inject
2164  %\prevdepth\strutdp % todo, might differ between TL and BL
2165   \tabl_tabulate_nobreak_inject
2166   \stoptabulatenoalign}
2167
2168\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed
2169
2170\def\tabl_tabulate_HL_second
2171  {\csname
2172     \ifnum\c_tabl_tabulate_noflines=\zerocount                     F\else
2173     \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else
2174                                                                    M\fi\fi
2175   L\endcsname}
2176
2177\appendtoks
2178    \let\FL\tabl_tabulate_XX_none
2179    \let\ML\tabl_tabulate_XX_none
2180    \let\LL\tabl_tabulate_XX_none
2181    \let\TL\tabl_tabulate_XX_none
2182    \let\BL\tabl_tabulate_XX_none
2183    \let\HL\tabl_tabulate_XX_none
2184    \let\HR\tabl_tabulate_XX_none
2185\to \t_tabl_tabulate_initializers_first
2186
2187\appendtoks
2188    \let\FL\tabl_tabulate_FL_second
2189    \let\ML\tabl_tabulate_ML_second
2190    \let\LL\tabl_tabulate_LL_second
2191    \let\TL\tabl_tabulate_TL_second
2192    \let\BL\tabl_tabulate_BL_second
2193    \let\HL\tabl_tabulate_HL_second
2194    \let\HR\tabl_tabulate_HL_second
2195\to \t_tabl_tabulate_initializers_second
2196
2197% \def\tabulatedoHRfive % horizontal rule line (break untested)
2198%   {\starttabulatenoalign
2199%      \glet\dotabulateautoline\dotabulatelinerule
2200%     %\ifcase#1\or % todo: check what this does
2201%        \ifnum\noftabulatelines=\zerocount
2202%          \glet\dotabulateautoline\donothing
2203%        \else\ifnum\noftabulatelines=\totalnoftabulatelines
2204%          \glet\dotabulateautoline\donothing
2205%        \fi\fi
2206%     %\fi
2207%      \dotabulatenobreak
2208%    \stoptabulatenoalign
2209%    \dotabulateautoline
2210%    \starttabulatenoalign
2211%      \tabl_tabulate_break_no
2212%      \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
2213%      \ifnum\noftabulatelines=\totalnoftabulatelines
2214%        \expandafter\dotabulatenobreak
2215%      \else
2216%        \expandafter\tabl_tabulate_break_allow
2217%      \fi
2218%    \stoptabulatenoalign
2219%    \dotabulateautoline
2220%    \starttabulatenoalign
2221%      \dotabulatenobreak
2222%    \stoptabulatenoalign}
2223
2224% \dorecurse{10}{
2225%     \starttabulate[|l|]
2226%     \FL
2227%     \NC first line, bound to next rule    \NC \NR
2228%     \TL
2229%     \NC bound to previous rule            \NC \NR
2230%     \NC some line                         \NC \NR
2231%     \NC some line                         \NC \NR
2232%     \NC some line                         \NC \NR
2233%     \NC bound to next rule                \NC \NR
2234%     \ML
2235%     \NC bound to previous rule            \NC \NR
2236%     \NC bound to next rule                \NC \NR
2237%     \BL
2238%     \NC last line, bound to previous rule \NC \NR
2239%     \LL
2240%     \stoptabulate
2241% }
2242
2243% This needs checking:
2244
2245\def\tabulaterule    {\HR} % a rule with lineheight
2246\def\tabulateline    {\HL} % just a spaced rule
2247\def\tabulateautorule{\HR}%
2248\def\tabulateautoline{\HL} % no longer different (to be looked into)
2249
2250%D When support for vertical rules we needed a way to pick up the specification for
2251%D the final rule and a \type {|{}} interface was chosen. As a result parsing had to
2252%D become more complex and I was not in the mood for messing up the code too much.
2253%D Therefore from now on the preamble is split by \LUA. There are definitely more
2254%D places where we can use \LUA\ code (for instance in alignment of numbers. The
2255%D repeat parser is replace at the \LUA\ end as well.
2256
2257\let\tabl_tabulate_flush_collected       \empty
2258\let\tabl_tabulate_flush_collected_indeed\empty
2259
2260\let\v_tabl_tabulate_align\!!zerocount
2261
2262\def\tabl_tabulate_check_side_float % new per 29-07-2016
2263  {\ifdefined\page_sides_check_floats_indeed
2264     \page_sides_check_floats_indeed
2265     \ifdim\hangindent>\zeropoint
2266       \advance\d_tabl_tabulate_indent\hangindent
2267     \fi
2268   \fi}
2269
2270\def\tabl_tabulate_set_local_hsize
2271  {\setlocalhsize
2272   \hsize\localhsize}
2273
2274\def\tabl_tabulate_process
2275  {\c_tabl_tabulate_pass\plusone
2276   \tabl_tabulate_check_full_content
2277   \edef\v_tabl_tabulate_align{\ifcsname\??tabulatealigning\p_align\endcsname\lastnamedcs\else0\fi}%
2278   \s_tabl_tabulate_first.5\d_tabl_tabulate_unit
2279   \s_tabl_tabulate_last\s_tabl_tabulate_first
2280   \s_tabl_tabulate_pre\zeropoint
2281   \s_tabl_tabulate_post\zeropoint
2282   \global\c_tabl_tabulate_columns\zerocount
2283   \global\c_tabl_tabulate_nofauto\zerocount
2284   \global\c_tabl_tabulate_noflines\zerocount
2285   \c_tabl_tabulate_totalnoflines\zerocount
2286   \c_tabl_tabulate_minusnoflines\zerocount
2287   \global\d_tabl_tabulate_width_p\zeropoint
2288   \global\d_tabl_tabulate_width_w\zeropoint
2289   \global\setfalse\c_tabl_tabulate_equal
2290   \tabl_tabulate_pheight_reset
2291   \tabskip\zeropoint
2292   \ifinsidesplitfloat
2293     \donetrue
2294   \else\ifinsidefloat
2295     \donefalse
2296   \else
2297     \donetrue
2298   \fi\fi
2299   \global\c_tabl_tabulate_repeathead
2300     \ifdone
2301       \ifcsname\??tabulateheader\tabulationparameter\c!header\endcsname
2302         \lastnamedcs
2303       \else
2304         \zerocount
2305       \fi
2306     \else
2307       \zerocount
2308     \fi
2309   %
2310   \the\t_tabl_tabulate_initializers_first % collect more here
2311   %
2312   \glet\tabl_tabulate_flush_collected\empty
2313   \ifdim\d_tabl_tabulate_margin>\zeropoint
2314     \t_tabl_tabulate_preamble
2315       {\aligntab
2316        \tabl_tabulate_flush_indent
2317        \strut
2318        \alignmark\alignmark
2319        \tabskip\d_tabl_tabulate_margin
2320        \strut
2321        \aligntab
2322        \alignmark\alignmark
2323        \tabskip\zeropoint}%
2324   \else
2325     \t_tabl_tabulate_preamble
2326       {\aligntab
2327        \tabl_tabulate_flush_indent
2328        \strut
2329        \alignmark\alignmark
2330        \aligntab
2331        \alignmark\alignmark
2332        \tabskip\zeropoint}%
2333   \fi
2334   \d_tabl_tabulate_width\zeropoint
2335   % these counters are set at the lua end
2336   \c_tabl_tabulate_nofcolumns         \zerocount
2337   \c_tabl_tabulate_has_rule_spec_first\zerocount
2338   \c_tabl_tabulate_has_rule_spec_last \zerocount
2339   \clf_presettabulate{\detokenizedtabulationparameter\c!format}%
2340   %
2341   \d_tabl_tabulate_width\zeropoint
2342   \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
2343   \toksapp\t_tabl_tabulate_preamble{%
2344     \aligntab\alignmark\alignmark
2345     \global\advance\c_tabl_tabulate_column\plusone % maybe just set it already
2346   }%
2347   \toksapp\t_tabl_tabulate_dummy{%
2348     \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
2349   }%
2350   \global\c_tabl_tabulate_column\zerocount
2351   \tabl_tabulate_pheight_reset
2352   \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2353   \ifx\p_indenting\v!no
2354     \forgetparindent
2355   \fi
2356   \ifinsidefloat
2357     \d_tabl_tabulate_indent\zeropoint
2358   \else
2359     \tabl_tabulate_check_side_float
2360     \tabl_tabulate_set_local_hsize
2361   \fi
2362   \dontcomplain
2363   \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved
2364   \everypar\everytabulatepar
2365   \setbox\scratchbox\vbox % outside \if because of line counting
2366     {\notesenabledfalse
2367      \d_tabl_tabulate_indent\zeropoint
2368      \settrialtypesetting % very important
2369      \anch_backgrounds_text_level_start
2370      \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}%
2371      \anch_backgrounds_text_level_stop
2372      \ifcase\c_anch_backgrounds_text_state\else
2373        \global\settrue\tablehaspositions
2374      \fi
2375   \ifnum\c_tabl_tabulate_nofauto>\zerocount
2376     % so, even if the natural size is larger, in the final run, we force the calculated width
2377     \d_tabl_tabulate_width\dimexpr\hsize-\wd\scratchbox-\d_tabl_tabulate_width_p-\d_tabl_tabulate_width_w\relax
2378     \ifnum\c_tabl_tabulate_nofauto>\zerocount
2379       \divide\d_tabl_tabulate_width \c_tabl_tabulate_nofauto\relax
2380     \fi
2381   \fi
2382   \setbox\scratchbox\emptybox % free memory
2383   \ifconditional\c_tabl_tabulate_split
2384     \splittopskip\strutht
2385     \glet\tabl_tabulate_flush_collected_indeed\empty
2386     \glet\tabl_tabulate_flush_collected\tabl_tabulate_flush_second
2387   \fi
2388   \c_tabl_tabulate_totalnoflines\c_tabl_tabulate_noflines
2389   \c_tabl_tabulate_minusnoflines\numexpr\c_tabl_tabulate_noflines+\minusone\relax
2390   \global\c_tabl_tabulate_noflines\zerocount
2391   %
2392   \c_tabl_tabulate_pass\plustwo % final pass
2393   \the\t_tabl_tabulate_initializers_second % collect more here
2394   %
2395   \ifx\p_line\v!line
2396     \let\HL\HR
2397     \let\tabulateautoline\tabulateautorule
2398     \let\tabulateline\tabulaterule
2399   \fi
2400   %
2401   \ifcase\c_tabl_tabulate_repeathead
2402     \ifinsidesplitfloat
2403        \global\setbox\b_tabl_tabulate\vbox \bgroup
2404      \else
2405        \startframedcontent[\tabulationparameter\c!frame]%
2406      \fi
2407   \else
2408     \global\setbox\b_tabl_tabulate\vbox \bgroup
2409   \fi
2410   %
2411   \dostarttaggedchained\t!tabulate\empty\??tabulation
2412   \dostarttagged\t!tabulaterow\empty
2413   \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
2414   \toksapp\everycr{%
2415     \noalign{\the\t_tabl_tabulate_every_real_row}%
2416     \dostoptagged
2417     \dostarttagged\t!tabulaterow\empty
2418   }%
2419    % we are in sync but just to be sure:
2420   \synchronizedisplaydirection
2421   \synchronizeinlinedirection
2422   \halign
2423     \usedirectionparameterreverse\tabulateparameter
2424     \expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
2425   \dostoptagged
2426   \dostoptagged
2427   \ifhmode\par\prevdepth\strutdp\fi % temporary hack
2428   \ifx\p_distance\v!grid
2429     \vskip-\strutdp % experimental tm-prikkels
2430   \fi
2431   %
2432   \ifcase\c_tabl_tabulate_repeathead
2433     \ifinsidesplitfloat
2434       \egroup % box
2435       \egroup % settings
2436       \tabl_split_box\b_tabl_tabulate
2437     \else
2438       \stopframedcontent
2439       \egroup
2440     \fi
2441   \else
2442     \egroup % box
2443     \egroup % settings
2444     \tabl_split_box\b_tabl_tabulate
2445   \fi
2446   %
2447   \ifinsidefloat
2448     \tabl_tabulate_inside_after
2449   \else
2450     \tabl_tabulate_outside_after
2451   \fi
2452   \egroup} % whole thing
2453
2454% \egroup
2455
2456% \setuptabulate[split=yes,header=text,title=Vervolg van Tabel]
2457%
2458% % \starttabulatehead
2459% % \NC test \NC hans\NC \NR
2460% % \stoptabulatehead
2461%
2462% \starttabulate
2463% \NC test \NC \input tufte \relax \NC \NR
2464% \NC test \NC \input knuth \relax \NC \NR
2465% \NC test \NC \input knuth \relax \NC \NR
2466% \NC test \NC \input tufte \relax \NC \NR
2467% \NC test \NC \input tufte \relax \NC \NR
2468% \NC test \NC \input tufte \relax \NC \NR
2469% \stoptabulate
2470
2471\def\tabl_split_box#1% #1 <> 0/2 / derived from the one in core-ntb.tex
2472  {\ifinsidesplitfloat
2473     \tabl_split_box_indeed#1%
2474   \else\ifinsidefloat
2475     \unvbox#1%
2476   \else
2477     \tabl_split_box_indeed#1%
2478   \fi\fi}
2479
2480\def\tabl_split_box_indeed#1%
2481  {\resettsplit
2482   \def\tsplitminimumfreelines{2}%
2483   \def\tsplitminimumfreespace{0pt}%
2484   \setbox\tsplitcontent\box#1%
2485   \ifcase\c_tabl_tabulate_repeathead\or
2486     \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
2487     \setbox\tsplithead\vbox{\unvbox\tsplithead}%
2488   \or
2489     \setbox\tsplithead\vbox{\hbox{\strut\tabulationparameter\c!title}}%
2490   \fi
2491   \handletsplit}
2492
2493%D \starttyping
2494%D \setuptabulate[split=no,rule=line]
2495%D
2496%D \starttabulate
2497%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2498%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2499%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2500%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2501%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2502%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
2503%D \stoptabulate
2504%D \stoptyping
2505
2506%D Spacing:
2507%
2508% \starttabulate
2509% \NC text \NC text \NC \NR
2510% \TB[small]
2511% \NC text \NC text \NC \NR
2512% \TB[4*big]
2513% \NC text \NC text \NC \NR
2514% \stoptabulate
2515
2516\def\tabl_tabulate_TB
2517  {\starttabulatenoalign
2518   \dosingleempty\tabl_tabulate_TB_indeed}
2519
2520\def\tabl_tabulate_TB_indeed[#1]%
2521  {\iffirstargument
2522     \blank[#1]
2523   \else\ifx\m_tabl_tabulate_blank_default\empty
2524     \blank
2525   \else
2526     \blank[\m_tabl_tabulate_blank_default]%
2527   \fi\fi
2528   \stoptabulatenoalign}
2529
2530% to be tested:
2531%
2532% \def\tabl_tabulate_TB
2533%   {\starttabulatenoalign
2534%    \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop}
2535%
2536% \def\tabl_tabulate_TB_yes[#1]%
2537%   {\blank[#1]
2538%    \stoptabulatenoalign}
2539%
2540% \def\tabl_tabulate_TB_nop[#1]%
2541%   {\blank
2542%    \stoptabulatenoalign}
2543
2544\appendtoks
2545    \let\TB\tabl_tabulate_TB
2546\to \everytabulate
2547
2548% %D Between alignment lines certain rules apply, and even a simple test can mess
2549% %D up a table, which is why we have a special test facilityL
2550% %D
2551% %D \startbuffer
2552% %D \starttabulate[|l|p|]
2553% %D \NC 1test \NC test \NC \NR
2554% %D \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
2555% %D \stoptabulate
2556% %D \stopbuffer
2557% %D
2558% %D \typebuffer \getbuffer
2559%
2560% \def\tableifelse#1% should be tabulatenoalign then
2561%   {\tablenoalign
2562%      {#1%
2563%        {\aftergroup \firstoftwoarguments}%
2564%        {\aftergroup\secondoftwoarguments}}}
2565%
2566% \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
2567
2568%D Some new trickery:
2569%D
2570%D \startbuffer
2571%D \settrue\c_tabl_tabulate_splitoff_whitespace
2572%D
2573%D \starttabulate[|p(2cm)|p(2cm)|p(2cm)|]
2574%D     \NC test 1a \NC test 2a \NC test 3a
2575%D                                 \par
2576%D                                 test 3b          \NC \NR
2577%D     \NC test 1a \NC test 2a \NC test 3a
2578%D                                 \blank[line]
2579%D                                 test 3b          \NC \NR
2580%D     \NC test 1a \NC test 2a \NC test 3a
2581%D                                 \blank[halfline]
2582%D                                 test 3b
2583%D                                 \blank[halfline]
2584%D                                 test 3c          \NC \NR
2585%D     \NC \blank  \NC \blank  \NC \blank           \NC \NR
2586%D     \NC test 1a \NC test 2a \NC test 3a
2587%D                                 \blank[halfline]
2588%D                                 test 3b
2589%D                                 \blank[halfline]
2590%D                                 test 3c          \NC \NR
2591%D     \NC \blank  \NC \blank  \NC                  \NC \NR
2592%D     \NC test 1a
2593%D         \par
2594%D         test 1b
2595%D         \par
2596%D         test 1b \NC test 2a
2597%D                     \par
2598%D                     test 2b
2599%D                     \par
2600%D                     test 2b \NC test 3a          \NC \NR
2601%D     \NC test 1a
2602%D         \blank
2603%D         test 1b
2604%D         \par
2605%D         test 1b \NC test 2a
2606%D                     \par
2607%D                     test 2b
2608%D                     \blank
2609%D                     test 2b \NC test 3a          \NC \NR
2610%D \stoptabulate
2611%D \stopbuffer
2612%D
2613%D \typebuffer \start \getbuffer \stop
2614
2615% \starttabulatie[|mc|]
2616% \NC \digits{100.000,00} \NC\NR
2617% \NC \digits{@10.000,00} \NC\NR
2618% \NC \digits{@@@.100,00} \NC\NR
2619% \NC \digits{@@@.@10,@@} \NC\NR
2620% \NC \digits{@@@.@@1,@@} \NC\NR
2621% \stoptabulatie
2622%
2623% \starttabulatie[|mc|]
2624% \ND 100.000,00 \NC\NR
2625% \ND @10.000,00 \NC\NR
2626% \ND @@@.100,00 \NC\NR
2627% \ND @@@.@10,@@ \NC\NR
2628% \ND @@@.@@1,@@ \NC\NR
2629% \stoptabulatie
2630%
2631% \starttabulatie[|c|]
2632% \ND $100.000,00$ \NC\NR
2633% \ND $@10.000,00$ \NC\NR
2634% \ND $@@@.100,00$ \NC\NR
2635% \ND $@@@.@10,@@$ \NC\NR
2636% \ND $@@@.@@1,@@$ \NC\NR
2637% \stoptabulatie
2638%
2639% \starttabulatie[|c|]
2640% \NC $\digits 100.000,00 $ \NC\NR
2641% \NC $\digits @10.000,00 $ \NC\NR
2642% \NC $\digits @@@.100,00 $ \NC\NR
2643% \NC $\digits @@@.@10,@@ $ \NC\NR
2644% \NC $\digits @@@.@@1,@@ $ \NC\NR
2645% \stoptabulatie
2646%
2647% \starttabulatie[|c|]
2648% \NC \digits $100.000,00$ \NC\NR
2649% \NC \digits $@10.000,00$ \NC\NR
2650% \NC \digits $@@@.100,00$ \NC\NR
2651% \NC \digits $@@@.@10,@@$ \NC\NR
2652% \NC \digits $@@@.@@1,@@$ \NC\NR
2653% \stoptabulatie
2654
2655%D Predefined categories (moved from core-mis):
2656
2657\definetabulate
2658  [\v!legend]
2659  [|emj1|i1|mR|]
2660
2661\setuptabulate
2662  [\v!legend]
2663  [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}]
2664
2665\definetabulate
2666  [\v!legend][\v!two]
2667  [|emj1|emk1|i1|mR|]
2668
2669\definetabulate
2670  [\v!fact]
2671  [|R|ecmj1|i1mR|]
2672
2673\setuptabulate
2674  [\v!fact]
2675  [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}]
2676
2677%D Another example:
2678%D
2679%D \starttyping
2680%D \definetabulate
2681%D   [whatever]
2682%D   [|l|r|]
2683%D
2684%D \definetabulate
2685%D   [whatever][else]
2686%D   [|l|c|r|]
2687%D
2688%D \startwhatever
2689%D \NC l    \NC r     \NC \NR
2690%D \NC left \NC right \NC \NR
2691%D \stopwhatever
2692%D
2693%D \startwhatever[else]
2694%D \NC l    \NC m      \NC r     \NC \NR
2695%D \NC left \NC middle \NC right \NC \NR
2696%D \stopwhatever
2697%D
2698%D \startwhatever[else][format={|c|c|c|c|}]
2699%D \NC l    \NC m      \NC m      \NC r     \NC \NR
2700%D \NC left \NC middle \NC middle \NC right \NC \NR
2701%D \stopwhatever
2702%D \stoptyping
2703
2704%D This is needed because we sometimes use the english command in tracing macros. In
2705%D fact, most detailed tracing macros that are done with \LUA\ only work in the
2706%D english interface anyway.
2707
2708% \definetabulate[tabulate] \setuptabulate[tabulate][\c!format=\v!none] % so no \v! here
2709
2710\newconditional\c_tabl_generic
2711
2712\unexpanded\setuvalue{starttabulate}%
2713  {\bgroup % whole thing
2714   \settrue\c_tabl_generic
2715   \let\currenttabulationparent\empty
2716   \dodoubleempty\tabl_start_regular}
2717
2718\letvalue{stoptabulate}\relax
2719
2720%D The following helpers are just there because we also have them at the \LUA\ end:
2721%D
2722%D \startbuffer
2723%D \starttabulate[|l|c|r|]
2724%D     \tabulaterow    {a,b,c}
2725%D     \tabulaterowbold{aa,bb,cc}
2726%D     \tabulaterowtype{aaa,bbb,ccc}
2727%D     \tabulaterowtyp {aaaa,bbbb,cccc}
2728%D \stoptabulate
2729%D \stopbuffer
2730%D
2731%D \typebuffer \getbuffer
2732
2733\def\tabl_tabulate_compact_row#1#2%
2734  {\NC\tabl_tabulate_compact_step#1#2,\end,}
2735
2736\def\tabl_tabulate_compact_step#1#2#3,%
2737  {\ifx#2\end
2738     \NR
2739     \expandafter\gobbleoneargument
2740   \else
2741     #1{#2#3}\NC
2742     \expandafter\tabl_tabulate_compact_step
2743   \fi#1}
2744
2745\unexpanded\def\tabulaterow    {\tabl_tabulate_compact_row\relax}
2746\unexpanded\def\tabulaterowbold{\tabl_tabulate_compact_row\bold}
2747\unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type}
2748\unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ}
2749
2750%D Here we plug in a row background feature. As we only have support for
2751%D \type {frame=name} we can use these variables.
2752%D
2753%D \starttyping
2754%D \startuseMPgraphic{foo}
2755%D     fill unitsquare
2756%D         xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8)
2757%D         randomized ExHeight
2758%D         shifted  (-ExHeight/8,ExHeight/16)
2759%D         withcolor RuleColor ;
2760%D \stopuseMPgraphic
2761%D
2762%D \setuptabulate % wel only have frame=name so we can use these:
2763%D   [background=foo,
2764%D    backgroundcolor=darkred,
2765%D    foregroundcolor=white]
2766%D
2767%D \definelinefiller[foo][mp=foo,color=darkgreen]
2768%D \definelinefiller[bar][mp=foo,color=darkred]
2769%D
2770%D \starttabulate[|||]
2771%D     \DB foo \BC bar \BC \NR
2772%D     \NC foo \NC bar \NC \NR
2773%D     \NC foo \NC bar \NC \NR
2774%D     \NC foo \NC bar \NC \NR
2775%D     \NC foo \NC bar \NC \NR
2776%D \stoptabulate
2777%D
2778%D \starttabulate[|||]
2779%D     \PB foo \BC bar \BC \NR
2780%D     \NC foo \NC bar \NC \NR
2781%D     \NC foo \NC bar \NC \NR
2782%D     \NC foo \NC bar \NC \NR
2783%D     \NC foo \NC bar \NC \NR
2784%D \stoptabulate
2785%D
2786%D \starttabulate[|||]
2787%D     \FB[bar] foo \BC bar \BC \NR
2788%D     \NC      foo \NC bar \NC \NR
2789%D     \NC      foo \NC bar \NC \NR
2790%D     \NC      foo \NC bar \NC \NR
2791%D     \NC      foo \NC bar \NC \NR
2792%D \stoptabulate
2793%D
2794%D \startnarrower
2795%D     \starttabulate[|||]
2796%D         \DB foo \DB bar \BC \NR
2797%D         \NC foo \NC bar \NC \NR
2798%D         \NC foo \NC bar \NC \NR
2799%D         \NC foo \NC bar \NC \NR
2800%D         \NC foo \NC bar \NC \NR
2801%D     \stoptabulate
2802%D \stopnarrower
2803%D
2804%D \starttabulate[|||]
2805%D     \BC          foo \BC bar \BC \NR
2806%D     \NL[magenta] foo \NC bar \NC \NR
2807%D     \NL[yellow]  foo \NC bar \NC \NR
2808%D     \NL[cyan]    foo \NC bar \NC \NR
2809%D     \NL[gray]    foo \NC bar \NC \NR
2810%D \stoptabulate
2811%D
2812%D \starttabulate
2813%D     \NL[red]     foo \NC bar \NC \NR
2814%D     \NL[green]   foo \NL[red] bar \NC \NR
2815%D     \NC          foo \NC bar \NC \NR
2816%D     \NL[blue]    foo \NC \input tufte  \NC \NR
2817%D     \NL[gray]    foo \NC bar \NC \NR
2818%D     \NL[yellow]  foo \NC bar \NC \NR
2819%D \stoptabulate
2820%D \stoptyping
2821
2822% \setuptabulate
2823%   [\c!background=,
2824%    \c!backgroundcolor=,
2825%    \c!foregroundcolor=,
2826%    \c!foregroundstyle=]
2827
2828\let\m_table_current_row_background              \empty
2829\let\m_table_current_row_background_default      \empty
2830\let\m_table_current_row_background_filler       \empty
2831\let\m_table_current_row_background_defaultfiller\empty
2832\let\m_table_current_row_background_auto         \empty
2833
2834\unexpanded\def\tabl_register_row_background#1%
2835  {\xdef\m_table_current_row_background{#1}}
2836
2837\unexpanded\def\tabl_register_row_background_filler#1%
2838  {\xdef\m_table_current_row_background_filler{#1}}
2839
2840\unexpanded\def\tabl_synchronize_row_background
2841  {\iftrialtypesetting\else
2842     \ifx\m_table_current_row_background_filler\empty
2843       \ifx\m_table_current_row_background\empty
2844         % nothing
2845         \tabl_synchronize_row_background_dummy
2846       \else
2847         \tabl_synchronize_row_background_indeed\m_table_current_row_background
2848       \fi
2849     \else
2850       \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler
2851     \fi
2852   \fi}
2853
2854\unexpanded\def\tabl_synchronize_row_background_dummy
2855  {\iftrialtypesetting\else
2856     \begingroup
2857    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint
2858     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint
2859     \endgroup
2860   \fi}
2861
2862\unexpanded\def\tabl_synchronize_row_background_indeed#1%
2863  {\iftrialtypesetting\else
2864     \begingroup
2865     \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
2866     \dousecolorparameter{#1}%
2867     \setbox\scratchbox\hpack{}%
2868    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
2869     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
2870     \endgroup
2871   \fi}
2872
2873\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1%
2874  {\iftrialtypesetting\else
2875     \begingroup
2876     \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
2877     \node_linefiller_set{#1}%
2878     \setbox\scratchbox\hpack{}%
2879    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
2880     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
2881     \endgroup
2882   \fi}
2883
2884\appendtoks
2885    \glet\m_table_current_row_background\empty
2886    \glet\m_table_current_row_background_filler\empty
2887    \global\c_tabl_tabulate_nofrealrows\zerocount
2888    \global\c_tabl_tabulate_autocolor\zerocount
2889    \clf_resetbackgroundrowdata
2890\to \t_tabl_tabulate_initializers_first
2891
2892\appendtoks
2893    \glet\m_table_current_row_background\empty
2894    \glet\m_table_current_row_background_filler\empty
2895    \global\c_tabl_tabulate_nofrealrows\zerocount
2896    \global\c_tabl_tabulate_autocolor\zerocount
2897    \clf_resetbackgroundrowdata
2898\to \t_tabl_tabulate_initializers_second
2899
2900\appendtoks
2901    \tabl_synchronize_row_background
2902\to \t_tabl_tabulate_every_real_row
2903
2904\appendtoks
2905    \glet\m_table_current_row_background\empty
2906    \glet\m_table_current_row_background_filler\empty
2907\to \t_tabl_tabulate_every_after_row
2908
2909\unexpanded\def\tabl_tabulate_NL_first[#1]%
2910  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2911   \ifcase\c_tabl_tabulate_column\or
2912     \tabl_register_row_background{#1}%
2913   \fi
2914   \ignorespaces}
2915
2916\unexpanded\def\tabl_tabulate_ND_first
2917  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2918   \ifcase\c_tabl_tabulate_column\or
2919     \tabl_register_row_background\m_table_current_row_background_default
2920   \fi
2921   \ignorespaces}
2922
2923\unexpanded\def\tabl_tabulate_LB_first[#1]%
2924  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2925   \ifcase\c_tabl_tabulate_column\or
2926     \tabl_register_row_background{#1}%
2927   \fi
2928   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2929   \ignorespaces}
2930
2931\unexpanded\def\tabl_tabulate_DB_first
2932  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2933   \ifcase\c_tabl_tabulate_column\or
2934     \tabl_register_row_background\m_table_current_row_background_default
2935   \fi
2936   \let\fontstyle\globalfontstyle
2937   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2938   \ignorespaces}
2939
2940\unexpanded\def\tabl_tabulate_NF_first[#1]%
2941  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2942   \ifcase\c_tabl_tabulate_column\or
2943     \tabl_register_row_background_filler{#1}%
2944   \fi
2945   \ignorespaces}
2946
2947\unexpanded\def\tabl_tabulate_NP_first
2948  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2949   \ifcase\c_tabl_tabulate_column\or
2950     \tabl_register_row_background_filler\m_table_current_row_background_default_filler
2951   \fi
2952   \ignorespaces}
2953
2954\unexpanded\def\tabl_tabulate_FB_first[#1]%
2955  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2956   \ifcase\c_tabl_tabulate_column\or
2957     \tabl_register_row_background_filler{#1}%
2958   \fi
2959   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2960   \ignorespaces}
2961
2962\unexpanded\def\tabl_tabulate_PB_first
2963  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2964   \ifcase\c_tabl_tabulate_column\or
2965     \tabl_register_row_background_filler\m_table_current_row_background_default_filler
2966   \fi
2967   \let\fontstyle\globalfontstyle
2968   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2969   \ignorespaces}
2970
2971\unexpanded\def\tabl_tabulate_BC_first % overloaded
2972  {\tabl_tabulate_column_normal\plusone\zerocount
2973   \let\fontstyle\globalfontstyle
2974   \ifx\m_table_current_row_background\empty
2975     \ifx\m_table_current_row_background_filler\empty
2976       \usetabulationstyleandcolor\c!headstyle\c!headcolor
2977     \else
2978       \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2979     \fi
2980   \else
2981     \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2982   \fi}
2983
2984\unexpanded\def\tabl_tabulate_A_first
2985  {\global\advance\c_tabl_tabulate_autocolor\plusone
2986   \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
2987   \ifx\m_table_current_row_background_auto\empty
2988     \global\c_tabl_tabulate_autocolor\plusone
2989     \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
2990   \fi
2991   \ifx\m_table_current_row_background_auto\empty
2992     \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default
2993   \fi
2994   \tabl_register_row_background{\m_table_current_row_background_auto}}
2995
2996\unexpanded\def\tabl_tabulate_NA_first
2997  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2998   \iftrialtypesetting\else
2999     \ifcase\c_tabl_tabulate_column\or
3000       \tabl_tabulate_A_first
3001     \fi
3002   \fi
3003   \ignorespaces}
3004
3005\unexpanded\def\tabl_tabulate_BA_first
3006  {\tabl_tabulate_column_normal\plusone\zerocount\relax
3007   \iftrialtypesetting\else
3008     \ifcase\c_tabl_tabulate_column\or
3009       \tabl_tabulate_A_first
3010     \fi
3011   \fi
3012   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
3013   \ignorespaces}
3014
3015\appendtoks
3016    \let\NL\tabl_tabulate_NL_first % NC with Line
3017    \let\ND\tabl_tabulate_ND_first % NC with Default Line
3018    \let\LB\tabl_tabulate_LB_first % BC with Line
3019    \let\DB\tabl_tabulate_DB_first % BC with Default Line
3020    \let\NF\tabl_tabulate_NF_first % NC with Filler
3021    \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler
3022    \let\FB\tabl_tabulate_FB_first % BC with Filler
3023    \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler
3024    \let\NA\tabl_tabulate_NA_first % NC with Auto Line
3025    \let\BA\tabl_tabulate_BA_first % NC with Auto Line
3026\to \t_tabl_tabulate_initializers_first
3027
3028\appendtoks
3029   \edef\m_table_current_row_background_default       {\tabulateparameter\c!backgroundcolor}%
3030   \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}%
3031   \let \m_table_current_row_background_auto           \empty
3032\to \everytabulate
3033
3034\setuptabulate
3035  [\c!headcolor=,
3036   \c!headstyle=\bf,
3037   \c!backgroundcolor=\tabulationparameter\c!rulecolor,
3038   \c!foregroundcolor=,
3039   \c!foregroundstyle=\tabulationparameter\c!headstyle]
3040
3041\protect \endinput
3042