tabl-tbl.mkiv /size: 104 Kb    last modification: 2021-10-28 13:50
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  {\dofastloopcs\c_tabl_tabulate_max_vrulecolumn\tabl_tabulate_vrule_reset_step
1555   \global\c_tabl_tabulate_max_vrulecolumn\zerocount}
1556
1557\def\tabl_tabulate_vrule_reset_step % undefined or relax
1558  {\expandafter\glet\csname\??tabulatevrule\the\fastloopindex\endcsname\undefined}
1559
1560\appendtoks
1561    \tabl_tabulate_vrule_reset
1562\to \t_tabl_tabulate_every_after_row
1563
1564% sometimes more efficient:
1565%
1566% \def\tabl_tabulate_column_vruled_yes#1#2[#3]%
1567%   {\rawprocesscommalist[#3]\tabl_tabulate_column_vruled_step
1568%    \expandafter\xdef\csname\??tabulatevrule\the\c_tabl_tabulate_column\endcsname
1569%      {\global\d_tabl_tabulate_vrulethickness_local\the\d_tabl_tabulate_vrulethickness_default
1570%       \noexpand\xdef\noexpand\m_tabl_tabulate_vrule_color_local{\m_tabl_tabulate_vrule_color_local}}%
1571%    \tabl_tabulate_column_normal#1#2}
1572
1573\def\tabl_tabulate_column_vruled_normal
1574  {\vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
1575
1576\def\tabl_tabulate_column_vruled_colored
1577  {\dousecolorparameter\m_tabl_tabulate_vrule_color
1578   \vrule\s!width\d_tabl_tabulate_vrulethickness\relax}
1579
1580\unexpanded\def\tabl_tabulate_column_vrule_inject_first
1581  {\ifcase\d_tabl_tabulate_vrulethickness\else
1582     \tabl_tabulate_column_vruled_normal % could be a skip instead
1583   \fi
1584   \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
1585
1586\unexpanded\def\tabl_tabulate_column_vrule_inject_second
1587  {\ifcase\d_tabl_tabulate_vrulethickness\else
1588     \ifx\m_tabl_tabulate_vrule_color\empty
1589       \tabl_tabulate_column_vruled_normal
1590     \else
1591       \tabl_tabulate_column_vruled_colored
1592     \fi
1593   \fi
1594   \global\d_tabl_tabulate_vrulethickness\zeropoint} % nils second one
1595
1596\let\tabl_tabulate_column_vrule_inject\relax
1597
1598\appendtoks
1599    \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_first
1600\to \t_tabl_tabulate_initializers_first
1601
1602\appendtoks
1603    \let\tabl_tabulate_column_vrule_inject\tabl_tabulate_column_vrule_inject_second
1604\to \t_tabl_tabulate_initializers_second
1605
1606% auto columns
1607
1608\def\tabl_tabulate_column_inject_auto
1609  {\tabl_tabulate_column_normal\zerocount\zerocount
1610   \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_columns\relax
1611     \expandafter\NR
1612   \else
1613     \expandafter\ignorespaces % interferes with the more tricky hooks
1614   \fi}
1615
1616\unexpanded\def\setquicktabulate#1% see \startlegend \startgiven (for the moment still public)
1617  {\let#1\tabl_tabulate_column_inject_auto
1618   \let\\\tabl_tabulate_column_inject_auto} % brrr, will go
1619
1620\setvalue{\??tabulateseparator\v!blank }{\s_tabl_tabulate_separator\bigskipamount}
1621\setvalue{\??tabulateseparator\v!depth }{\s_tabl_tabulate_separator\strutdp}
1622\setvalue{\??tabulateseparator\v!small }{\def\m_tabl_tabulate_separator_factor{.25}}
1623\setvalue{\??tabulateseparator\v!medium}{\def\m_tabl_tabulate_separator_factor{.5}}
1624\setvalue{\??tabulateseparator\v!big   }{}
1625\setvalue{\??tabulateseparator\v!none  }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
1626\setvalue{\??tabulateseparator\v!grid  }{\s_tabl_tabulate_separator\zeropoint\let\m_tabl_tabulate_separator_factor\zerocount}
1627
1628\def\tabl_tabulate_column_rule_separator_step#1%
1629  {\ifcsname\??tabulateseparator#1\endcsname
1630     \lastnamedcs
1631   \else
1632     \s_tabl_tabulate_separator#1\relax
1633   \fi}
1634
1635\def\tabl_tabulate_column_rule_separator_inject % can be sped up (will do when used frequently)
1636  {\bgroup
1637   \s_tabl_tabulate_separator\strutdp
1638   \ifx\p_distance\empty\else
1639     \let\m_tabl_tabulate_separator_factor\plusone
1640     \processcommacommand[\p_distance]\tabl_tabulate_column_rule_separator_step
1641     \s_tabl_tabulate_separator\m_tabl_tabulate_separator_factor\s_tabl_tabulate_separator
1642   \fi
1643   % someamble: footer or header: unfortunately a skip can trigger a page break (weird
1644   % as we have lots of nobreaks)
1645 % \ifconditional\c_tabl_tabulate_someamble\kern\else\vskip\fi\s_tabl_tabulate_separator % new
1646 % \directvspacing{\the\s_tabl_tabulate_separator}% new
1647   \directvskip\s_tabl_tabulate_separator
1648   \egroup}
1649
1650\def\tabl_tabulate_hrule_spec_ignore#1%
1651  {%\glet\currenttabulationlocalhrulecolor\empty
1652   %\global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
1653   \doifelsefastoptionalcheck#1#1}
1654
1655\def\tabl_tabulate_hrule_spec_pickup#1%
1656  {\glet\currenttabulationlocalhrulecolor\m_tabl_tabulate_hrule_color_default
1657   \global\d_tabl_tabulate_hrulethickness_local\d_tabl_tabulate_hrulethickness_default
1658   \doifelsefastoptionalcheck{\tabl_tabulate_hrule_preset#1}#1}
1659
1660\def\tabl_tabulate_hrule_preset_step#1%
1661  {\doifelsenumber{#1}
1662     {\global\d_tabl_tabulate_hrulethickness_local#1\d_tabl_tabulate_hrulethickness_default}
1663     {\xdef\currenttabulationlocalhrulecolor{#1}}}
1664
1665\def\tabl_tabulate_hrule_preset#1[#2]%
1666  {\rawprocesscommalist[#2]\tabl_tabulate_hrule_preset_step
1667   #1}
1668
1669\def\tabl_tabulate_hrule_inject_normal
1670  {\autorule
1671     \s!height.5\d_tabl_tabulate_hrulethickness_local
1672     \s!depth .5\d_tabl_tabulate_hrulethickness_local
1673     \s!left    \d_tabl_tabulate_indent
1674   \relax}
1675
1676\def\tabl_tabulate_hrule_inject_colored
1677  {\dousecolorparameter\currenttabulationlocalhrulecolor
1678   \tabl_tabulate_hrule_inject_normal}
1679
1680\unexpanded\def\tabl_tabulate_hrule_inject_first
1681  {\ifcase\d_tabl_tabulate_hrulethickness_local\else
1682     \tabl_tabulate_hrule_inject_normal
1683   \fi}
1684
1685\unexpanded\def\tabl_tabulate_hrule_inject_second
1686  {\ifcase\d_tabl_tabulate_hrulethickness_local\else
1687     \ifx\currenttabulationlocalhrulecolor\empty
1688       \tabl_tabulate_hrule_inject_normal
1689     \else
1690       \tabl_tabulate_hrule_inject_colored
1691     \fi
1692   \fi}
1693
1694\let\tabl_tabulate_hrule_inject\relax
1695
1696\appendtoks
1697    \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_first
1698\to \t_tabl_tabulate_initializers_first
1699
1700\appendtoks
1701    \let\tabl_tabulate_hrule_inject\tabl_tabulate_hrule_inject_second
1702\to \t_tabl_tabulate_initializers_second
1703
1704%D Color:
1705
1706% \starttabulate[||p||]
1707% \NC test \NC test \NC test \NC \NR
1708% \NC test \CC[green] \input tufte  \CC[yellow] test \NC \NR
1709% \NC test \NC test \NC 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% \CC[blue] test \CC[red] test \NC test \NC \NR
1714% \NC test \NC 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 \CC[gray] test \NC \NR
1718% \NC test \NC test \NC test \NC \NR
1719% \NC test \NC test \NC test \NC \NR
1720% \CC[blue] test \NC test \NC test \NC \NR
1721% \NC test \NC test \NC test \NC \NR
1722% \NC test \NC test \CC[magenta] test \NC \NR
1723% \NC test \NC test \NC test \NC \NR
1724% \NC test \CC[cyan] \dorecurse{10}{\input ward }\NC test \NC \NR
1725% \NC test \NC test \NC test \NC \NR
1726% \NC test \CC[yellow] test \NC test \NC \NR
1727% \stoptabulate
1728
1729\unexpanded\def\tabl_tabulate_color_set#1% we could store the attributes at the cost of a lua call
1730  {\begingroup
1731   \clf_enablebackgroundalign % was \node_backgrounds_align_initialize
1732   \glet\tabl_tabulate_color_repeat\tabl_tabulate_color_repeat_second
1733   \global\settrue\c_tabl_tabulate_has_colors
1734   \ifnum\c_tabl_tabulate_column>\c_tabl_tabulate_max_colorcolumn
1735     \global\c_tabl_tabulate_max_colorcolumn\c_tabl_tabulate_column
1736   \fi
1737   \expandafter\xdef\csname\??tabulatecolor\the\c_tabl_tabulate_column\endcsname{#1}%
1738   \hpack \thealignbackgroundcolorattr{#1}{}% pack ?
1739   \endgroup}
1740
1741\def\tabl_tabulate_color_repeat_second % for split off lines
1742  {\begingroup
1743   \scratchcounter\numexpr\c_tabl_tabulate_column-\plusone\relax % ugly !
1744   \ifcsname\??tabulatecolor\the\scratchcounter\endcsname
1745   % \hbox \thealignbackgroundcolorattr{\csname\??tabulatecolor\the\scratchcounter\endcsname}{}% pack ?
1746     \hpack \expandafter\thealignbackgroundcolorattr\expandafter{\lastnamedcs}{}% pack ?
1747   \fi
1748   \endgroup}
1749
1750\let\tabl_tabulate_color_repeat\relax
1751
1752\appendtoks
1753    \let\tabl_tabulate_color_repeat\relax
1754\to \everytabulate
1755
1756\def\tabl_tabulate_color_reset
1757  {\ifcase\c_tabl_tabulate_max_colorcolumn\else
1758     \tabl_tabulate_color_reset_indeed
1759   \fi}
1760
1761% \def\tabl_tabulate_color_reset_indeed
1762%   {\dorecurse\c_tabl_tabulate_max_colorcolumn{\letgvalue{\??tabulatecolor\recurselevel}\undefined}} % slow
1763
1764\def\tabl_tabulate_color_reset_indeed
1765  {\dofastloopcs\c_tabl_tabulate_max_colorcolumn\tabl_tabulate_color_reset_step}
1766
1767\def\tabl_tabulate_color_reset_step % undefined or empty?
1768  {\expandafter\glet\csname\??tabulatecolor\number\fastloopindex\endcsname\undefined}
1769
1770\appendtoks
1771    \tabl_tabulate_color_reset
1772\to \t_tabl_tabulate_every_after_row
1773
1774% \def\tabl_tabulate_register_par_options_indeed
1775%   {\iftrialtypesetting \else
1776%      \registerparoptions
1777%      \ifinsidefloat
1778%        % that is, an unbreakable one
1779%        \glet\tabl_tabulate_register_par_options\empty
1780%      \else
1781%        % unsafe in crossing pages, at each b...
1782%        % \glet\tabl_tabulate_register_par_options\empty
1783%      \fi
1784%    \fi}
1785%
1786% \appendtoks
1787%     \glet\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_indeed
1788% \to \everytabulate
1789
1790\def\tabl_tabulate_register_par_options_first % maybe track here if needed
1791  {}
1792
1793\def\tabl_tabulate_register_par_options_second
1794  {\registerparoptions
1795   \ifinsidefloat
1796     % that is, an unbreakable one
1797     \glet\tabl_tabulate_register_par_options\empty
1798   \else
1799     % unsafe in crossing pages, at each b...
1800     % \glet\tabl_tabulate_register_par_options\empty
1801   \fi}
1802
1803\let\tabl_tabulate_register_par_options\relax
1804
1805\appendtoks
1806    \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_first
1807\to \t_tabl_tabulate_initializers_first
1808
1809\appendtoks
1810    \let\tabl_tabulate_register_par_options\tabl_tabulate_register_par_options_second
1811\to \t_tabl_tabulate_initializers_second
1812
1813\appendtoks
1814    \tabl_tabulate_register_par_options
1815\to \t_tabl_tabulate_every_row
1816
1817\def\tabl_tabulate_flush_indent_indeed
1818  {\hbox to \d_tabl_tabulate_indent % pack ?
1819     {% we now have a local hsize, and since we want to
1820      % register positional info (i.e. real hsizes) we
1821      % need to reconstitute the original hsize
1822      \advance\hsize\d_tabl_tabulate_indent
1823      % this is indeed rather messy and took a few hours
1824      % to dis/uncover
1825      \the\t_tabl_tabulate_every_row
1826      \hss}}
1827
1828\def\tabl_tabulate_flush_indent
1829  {\ifnum\c_tabl_tabulate_column=\zerocount
1830     \tabl_tabulate_flush_indent_indeed
1831   \fi}
1832
1833\def\tabl_tabulate_digits{\digits}
1834
1835%D Beware, we cannot use \type {\unexpanded} on \type {\HL} cum suis, since \TEX's
1836%D hard coded noalign lookahead fails on it! I mistakenly added this for a while.
1837
1838\setvalue{\??tabulatealigning\v!normal}{0}
1839\setvalue{\??tabulatealigning\v!right }{1}
1840\setvalue{\??tabulatealigning\v!left  }{2}
1841\setvalue{\??tabulatealigning\v!middle}{3}
1842
1843\setvalue{\??tabulateheader\v!repeat}{\plusone}
1844\setvalue{\??tabulateheader\v!text  }{\plustwo}
1845
1846\unexpanded\def\tabl_tabulate_bskip_first {\setbox\b_tabl_tabulate\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
1847\unexpanded\def\tabl_tabulate_eskip_first {\par\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
1848\unexpanded\def\tabl_tabulate_xbskip_first{\hpack\bgroup\vbox\bgroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_nop}
1849\unexpanded\def\tabl_tabulate_xeskip_first{\par\egroup\egroup\glet\tabl_tabulate_hook\tabl_tabulate_hook_yes}
1850
1851\let\tabl_tabulate_bbskip\relax
1852\let\tabl_tabulate_eeskip\relax
1853\let\tabl_tabulate_bskip \relax
1854\let\tabl_tabulate_eskip \relax
1855\let\tabl_tabulate_xbskip\relax
1856\let\tabl_tabulate_xeskip\relax
1857
1858\appendtoks
1859   \let\tabl_tabulate_bbskip\relax
1860  %\let\tabl_tabulate_eeskip\relax % adapted by bskip
1861   \let\tabl_tabulate_bskip \tabl_tabulate_bskip_first
1862   \let\tabl_tabulate_eskip \tabl_tabulate_eskip_first
1863   \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_first
1864   \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_first
1865\to \t_tabl_tabulate_initializers_first
1866
1867\def\tabl_tabulate_baselinecorrection % keep an eye on this one
1868  {\def\dobaselinecorrection{\vskip\dimexpr-\prevdepth+\strutdp+\strutdp\relax}% todo: mkiv
1869   \baselinecorrection}
1870
1871% some hack to prevent an allowbreak ... actually we could set up a system then
1872% that is dealt with atthe lua end in the skip handler: turn penalties with attributes
1873% values into other penalties that get removed
1874
1875\installcorenamespace{tabulatenobreak}
1876
1877\def\tabl_tabulate_break_allow{\directvpenalty\zerocount}
1878\def\tabl_tabulate_break_maybe{\directvpenalty\zerocount}
1879\def\tabl_tabulate_break_no   {\directvpenalty\plustenthousand} % ,order:2}}
1880
1881\let\tabl_tabulate_break_state_set       \relax
1882\let\tabl_tabulate_break_state_reset     \relax
1883\let\tabl_tabulate_break_state_allowbreak\tabl_tabulate_break_maybe
1884
1885% so far
1886
1887\unexpanded\def\tabl_tabulate_VL_first{\tabl_tabulate_column_vruled\zerocount\zerocount}
1888\unexpanded\def\tabl_tabulate_NC_first{\tabl_tabulate_column_normal\zerocount\zerocount}
1889\unexpanded\def\tabl_tabulate_RC_first{\tabl_tabulate_column_normal\zerocount\plusone}
1890\unexpanded\def\tabl_tabulate_HC_first{\tabl_tabulate_column_normal\zerocount\plustwo}
1891\unexpanded\def\tabl_tabulate_EQ_first{\tabl_tabulate_column_equal \plustwo  \zerocount}
1892\unexpanded\def\tabl_tabulate_RQ_first{\tabl_tabulate_column_equal \zerocount\plusone}
1893\unexpanded\def\tabl_tabulate_HQ_first{\tabl_tabulate_column_equal \zerocount\plustwo}
1894
1895\unexpanded\def\tabl_tabulate_NG_first{\tabl_tabulate_column_normal\zerocount\zerocount}
1896\unexpanded\def\tabl_tabulate_NN_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % new, undocumented, test first
1897\unexpanded\def\tabl_tabulate_ND_first{\tabl_tabulate_column_normal\zerocount\zerocount\tabl_tabulate_digits} % same, for old times sake
1898
1899\unexpanded\def\tabl_tabulate_NR_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_check_penalties} % next row
1900\unexpanded\def\tabl_tabulate_NB_first {\tabl_tabulate_NR_common\conditionaltrue \tabl_tabulate_nobreak_inject } % next row no break
1901
1902\unexpanded\def\tabl_tabulate_NR_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_check_penalties} % next row
1903\unexpanded\def\tabl_tabulate_NB_second{\tabl_tabulate_NR_common\conditionalfalse\tabl_tabulate_nobreak_inject } % next row no break
1904
1905\unexpanded\def\tabl_tabulate_CC_first{\global\c_tabl_tabulate_localcolorspan\zerocount\tabl_tabulate_set_color_column\zerocount}
1906\unexpanded\def\tabl_tabulate_CL_first{\global\c_tabl_tabulate_localcolorspan\plusone  \tabl_tabulate_set_color_column\zerocount}
1907\unexpanded\def\tabl_tabulate_CM_first{\global\c_tabl_tabulate_localcolorspan\plustwo  \tabl_tabulate_set_color_column\zerocount}
1908\unexpanded\def\tabl_tabulate_CR_first{\global\c_tabl_tabulate_localcolorspan\plusthree\tabl_tabulate_set_color_column\zerocount}
1909
1910%D Sort of special:
1911%D
1912%D \startbuffer
1913%D \startitemize[n]
1914%D \starttabulate[|||||]
1915%D \NC p \NC \itemtag \NC q \NC r \NC \NR
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 \stoptabulate
1920%D \stopitemize
1921%D
1922%D \startitemize[n]
1923%D \starttabulate[|||||]
1924%D \NI b \NC c \NC d \NC \NR
1925%D \NC a \NI c \NC d \NC \NR
1926%D \NC a \NC b \NI d \NC \NR
1927%D \NC a \NC b \NC c \NI \NR
1928%D \stoptabulate
1929%D \stopitemize
1930%D \stopbuffer
1931%D
1932%D \typebuffer \getbuffer
1933
1934\unexpanded\def\tabl_tabulate_NI_first{\doifelsefastoptionalcheck\tabl_tbl_NI_yes\tabl_tbl_NI_nop}
1935
1936\def\tabl_tbl_NI_yes[#1]{\NC \itemtag[#1]\NC}
1937\def\tabl_tbl_NI_nop    {\NC \itemtag    \NC}
1938
1939%D The following shortcut is handy for tables where one needs bold headers:
1940
1941\unexpanded\def\tabl_tabulate_BC_first
1942  {\tabl_tabulate_column_normal\plusone\zerocount
1943   \let\fontstyle\globalfontstyle
1944   \bf}
1945
1946\appendtoks
1947    \let\VL\tabl_tabulate_VL_first
1948    \let\NC\tabl_tabulate_NC_first
1949    \let\BC\tabl_tabulate_BC_first
1950    \let\RC\tabl_tabulate_RC_first
1951    \let\HC\tabl_tabulate_HC_first
1952    \let\EQ\tabl_tabulate_EQ_first
1953    \let\RQ\tabl_tabulate_RQ_first
1954    \let\HQ\tabl_tabulate_HQ_first
1955    \let\NG\tabl_tabulate_NG_first
1956    \let\NN\tabl_tabulate_NN_first
1957    \let\ND\tabl_tabulate_ND_first
1958    \let\NR\tabl_tabulate_NR_first
1959    \let\NB\tabl_tabulate_NB_first
1960    \let\CC\tabl_tabulate_CC_first
1961    \let\CL\tabl_tabulate_CL_first
1962    \let\CM\tabl_tabulate_CM_first
1963    \let\CR\tabl_tabulate_CR_first
1964    \let\NI\tabl_tabulate_NI_first
1965\to \t_tabl_tabulate_initializers_first
1966
1967\appendtoks
1968    \let\NR\tabl_tabulate_NR_second
1969    \let\NB\tabl_tabulate_NB_second
1970\to \t_tabl_tabulate_initializers_second
1971
1972\appendtoks
1973    \let\SR\NR
1974    \let\FR\NR
1975    \let\MR\NR
1976    \let\LR\NR
1977    \let\AR\NR
1978\to \t_tabl_tabulate_initializers_first
1979
1980\unexpanded\def\tabl_tabulate_NR_common#1#2%
1981  {\global\advance\c_tabl_tabulate_noflines\plusone
1982   \global\setfalse\c_tabl_tabulate_firstflushed
1983   \global\setfalse\c_tabl_tabulate_equal
1984   \global\c_tabl_tabulate_column\zerocount
1985   \ifconditional#1\relax
1986     \tabl_tabulate_break_state_reset
1987   \fi
1988   \tabl_tabulate_pheight_reset
1989   \unskip\unskip\crcr\tabl_tabulate_flush_collected
1990   % can we omit the next one in the first run? probably
1991   \starttabulatenoalign
1992     \the\t_tabl_tabulate_every_after_row
1993     #2%
1994   \stoptabulatenoalign}
1995
1996\def\tabl_tabulate_check_penalties
1997  {\ifconditional\c_tabl_tabulate_tolerant_break\else
1998     \ifnum\c_tabl_tabulate_totalnoflines=\plusone
1999     %  \tabl_tabulate_break_allow
2000     \else
2001       \ifconditional\c_tabl_tabulate_someamble \ifcase\c_tabl_tabulate_repeathead \else
2002         \tabl_tabulate_break_allow
2003       \fi \fi
2004       \ifnum\c_tabl_tabulate_noflines=\plusone
2005         \tabl_tabulate_nobreak_inject
2006       \else \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_minusnoflines
2007         \ifnum\c_tabl_tabulate_plines_max<\plustwo
2008           \tabl_tabulate_nobreak_inject
2009         \else
2010           \tabl_tabulate_break_allow % needed with pbreak prevention
2011         \fi
2012       \else
2013         \tabl_tabulate_break_state_allowbreak
2014       \fi \fi
2015     \fi
2016   \fi
2017   \global\setfalse\c_tabl_tabulate_firstflushed}
2018
2019\unexpanded\def\tabl_tabulate_bbskip_second_split_yes
2020  {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
2021     \ifx\tabl_tabulate_flush_collected_indeed\empty\else
2022       \setbox0\hbox
2023     \fi
2024  \fi}
2025
2026\unexpanded\def\tabl_tabulate_eskip_second
2027  {\par\egroup
2028   \tabl_tabulate_pheight_set
2029   \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2030   \tabl_tabulate_splitoff_box}
2031
2032\unexpanded\def\tabl_tabulate_bskip_second_split_yes
2033  {\ifvoid\b_tabl_tabulate_current\c_tabl_tabulate_column
2034     % first line
2035     \global\setbox\b_tabl_tabulate_current\c_tabl_tabulate_column\vbox
2036     \bgroup
2037     \glet\tabl_tabulate_hook\tabl_tabulate_hook_nop
2038     \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
2039     % \begstrut % interferes with pre-\pars
2040     % evt: \appendtoks\begstrut\to\everypar
2041     \ignorespaces
2042     \let\tabl_tabulate_eskip\tabl_tabulate_eskip_second
2043   \else
2044     % successive lines
2045     \let\tabl_tabulate_eskip\empty
2046     \dontcomplain
2047     \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2048     \expandafter\tabl_tabulate_splitoff_box
2049   \fi}
2050
2051\unexpanded\def\tabl_tabulate_xbskip_second{\tabl_tabulate_bskip}
2052\unexpanded\def\tabl_tabulate_xeskip_second{\tabl_tabulate_eskip}
2053
2054\unexpanded\def\tabl_tabulate_flush_second_indeed
2055  {\glet\tabl_tabulate_flush_collected_indeed\empty
2056   \global\c_tabl_tabulate_column\zerocount
2057   \tabl_tabulate_pbreak_check
2058   \dofastloopcs\c_tabl_tabulate_columns\tabl_tabulate_flush_second_step
2059   \global\settrue\c_tabl_tabulate_firstflushed}
2060
2061\unexpanded\def\tabl_tabulate_flush_second_step
2062  {\ifvoid\b_tabl_tabulate_current\fastloopindex\else
2063     \gdef\tabl_tabulate_flush_collected_indeed{\the\t_tabl_tabulate_dummy}%
2064   \fi}
2065
2066\def\tabl_tabulate_flush_second
2067  {\tabulatenoalign{\tabl_tabulate_flush_second_indeed}%
2068   \tabl_tabulate_flush_collected_indeed}
2069
2070\unexpanded\def\tabl_tabulate_bskip_second_split_nop
2071  {\vtop\bgroup
2072     \ifconditional\c_tabl_tabulate_automode\hsize\d_tabl_tabulate_width\fi
2073     % \begstrut % interferes with pre-\pars
2074     % evt: \appendtoks\begstrut\to\everypar
2075     \ignorespaces}
2076
2077\unexpanded\def\tabl_tabulate_eskip_second_split_nop % vertical strut added august 2003
2078  {\par\verticalstrut
2079   \vskip-\struttotal
2080   \egroup}
2081
2082% \let\tabl_tabulate_eskip \relax % adapted by bskip
2083% \let\tabl_tabulate_eeskip\relax % adapted by bskip
2084
2085\appendtoks
2086   \let\tabl_tabulate_xbskip\tabl_tabulate_xbskip_second
2087   \let\tabl_tabulate_xeskip\tabl_tabulate_xeskip_second
2088   \ifconditional\c_tabl_tabulate_split
2089     \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_yes
2090     \let\tabl_tabulate_bbskip\tabl_tabulate_bbskip_second_split_yes
2091   \else
2092     \let\tabl_tabulate_bskip \tabl_tabulate_bskip_second_split_nop
2093     \let\tabl_tabulate_eskip \tabl_tabulate_eskip_second_split_nop
2094   \fi
2095\to \t_tabl_tabulate_initializers_second
2096
2097% see ***
2098%
2099% \enabletrackers[nodes.page_vspacing]
2100% \starttext
2101%     \starttabulate[||] \dorecurse{100}{\NC Eins \NC \NR \HL} \stoptabulate
2102% \stoptext
2103
2104\def\tabl_tabulate_XX_none
2105  {\starttabulatenoalign
2106     \tabl_tabulate_break_state_set
2107     \tabl_tabulate_hrule_spec_ignore
2108   \stoptabulatenoalign}
2109
2110\def\tabl_tabulate_FL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_FL_second_indeed}
2111\def\tabl_tabulate_ML_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_ML_second_indeed}
2112\def\tabl_tabulate_LL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_LL_second_indeed}
2113\def\tabl_tabulate_TL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_TL_second_indeed}
2114\def\tabl_tabulate_BL_second{\starttabulatenoalign\tabl_tabulate_hrule_spec_pickup\tabl_tabulate_BL_second_indeed}
2115
2116\unexpanded\def\tabl_tabulate_FL_second_indeed
2117  {\ifinsidefloat\else
2118     \doifempty{\tabulationparameter\c!before}\tabl_tabulate_baselinecorrection % no expansion
2119   \fi
2120   \tabl_tabulate_hrule_inject
2121   \tabl_tabulate_nobreak_inject
2122   \tabl_tabulate_column_rule_separator_inject
2123   \prevdepth\strutdp
2124   \tabl_tabulate_nobreak_inject
2125   \stoptabulatenoalign}
2126
2127\def\spac_vspacing_no_topskip % use grouped
2128  {\c_attr_skipcategory\plusten}
2129
2130\unexpanded\def\tabl_tabulate_ML_second_indeed
2131  {\tabl_tabulate_break_no
2132   \tabl_tabulate_column_rule_separator_inject
2133   \tabl_tabulate_break_no
2134   \tabl_tabulate_hrule_inject
2135   \vskip-\p_rulethickness\relax
2136   \begingroup
2137   \spac_vspacing_no_topskip
2138   \tabl_tabulate_hrule_inject
2139   \endgroup
2140   \tabl_tabulate_break_no
2141   \tabl_tabulate_column_rule_separator_inject
2142   \stoptabulatenoalign}
2143
2144\unexpanded\def\tabl_tabulate_LL_second_indeed
2145  {\tabl_tabulate_nobreak_inject
2146   \tabl_tabulate_column_rule_separator_inject
2147   \tabl_tabulate_nobreak_inject
2148   \tabl_tabulate_hrule_inject
2149   \ifinsidefloat
2150     \tabl_tabulate_inside_inbetween
2151   \else
2152     \tabl_tabulate_outside_inbetween
2153   \fi
2154   \stoptabulatenoalign}
2155
2156\unexpanded\def\tabl_tabulate_TL_second_indeed
2157  {\tabl_tabulate_nobreak_inject
2158   \tabl_tabulate_column_rule_separator_inject
2159   \tabl_tabulate_nobreak_inject
2160   \tabl_tabulate_hrule_inject
2161   \tabl_tabulate_nobreak_inject
2162   \tabl_tabulate_column_rule_separator_inject
2163  %\prevdepth\strutdp % todo, might differ between TL and BL
2164   \tabl_tabulate_nobreak_inject
2165   \stoptabulatenoalign}
2166
2167\let\tabl_tabulate_BL_second_indeed\tabl_tabulate_TL_second_indeed
2168
2169\def\tabl_tabulate_HL_second
2170  {\csname
2171     \ifnum\c_tabl_tabulate_noflines=\zerocount                     F\else
2172     \ifnum\c_tabl_tabulate_noflines=\c_tabl_tabulate_totalnoflines L\else
2173                                                                    M\fi\fi
2174   L\endcsname}
2175
2176\appendtoks
2177    \let\FL\tabl_tabulate_XX_none
2178    \let\ML\tabl_tabulate_XX_none
2179    \let\LL\tabl_tabulate_XX_none
2180    \let\TL\tabl_tabulate_XX_none
2181    \let\BL\tabl_tabulate_XX_none
2182    \let\HL\tabl_tabulate_XX_none
2183    \let\HR\tabl_tabulate_XX_none
2184\to \t_tabl_tabulate_initializers_first
2185
2186\appendtoks
2187    \let\FL\tabl_tabulate_FL_second
2188    \let\ML\tabl_tabulate_ML_second
2189    \let\LL\tabl_tabulate_LL_second
2190    \let\TL\tabl_tabulate_TL_second
2191    \let\BL\tabl_tabulate_BL_second
2192    \let\HL\tabl_tabulate_HL_second
2193    \let\HR\tabl_tabulate_HL_second
2194\to \t_tabl_tabulate_initializers_second
2195
2196% \def\tabulatedoHRfive % horizontal rule line (break untested)
2197%   {\starttabulatenoalign
2198%      \glet\dotabulateautoline\dotabulatelinerule
2199%     %\ifcase#1\or % todo: check what this does
2200%        \ifnum\noftabulatelines=\zerocount
2201%          \glet\dotabulateautoline\donothing
2202%        \else\ifnum\noftabulatelines=\totalnoftabulatelines
2203%          \glet\dotabulateautoline\donothing
2204%        \fi\fi
2205%     %\fi
2206%      \dotabulatenobreak
2207%    \stoptabulatenoalign
2208%    \dotabulateautoline
2209%    \starttabulatenoalign
2210%      \tabl_tabulate_break_no
2211%      \ifx\dotabulateautoline\dotabulatelinerule\kern-\lineheight\fi
2212%      \ifnum\noftabulatelines=\totalnoftabulatelines
2213%        \expandafter\dotabulatenobreak
2214%      \else
2215%        \expandafter\tabl_tabulate_break_allow
2216%      \fi
2217%    \stoptabulatenoalign
2218%    \dotabulateautoline
2219%    \starttabulatenoalign
2220%      \dotabulatenobreak
2221%    \stoptabulatenoalign}
2222
2223% \dorecurse{10}{
2224%     \starttabulate[|l|]
2225%     \FL
2226%     \NC first line, bound to next rule    \NC \NR
2227%     \TL
2228%     \NC bound to previous rule            \NC \NR
2229%     \NC some line                         \NC \NR
2230%     \NC some line                         \NC \NR
2231%     \NC some line                         \NC \NR
2232%     \NC bound to next rule                \NC \NR
2233%     \ML
2234%     \NC bound to previous rule            \NC \NR
2235%     \NC bound to next rule                \NC \NR
2236%     \BL
2237%     \NC last line, bound to previous rule \NC \NR
2238%     \LL
2239%     \stoptabulate
2240% }
2241
2242% This needs checking:
2243
2244\def\tabulaterule    {\HR} % a rule with lineheight
2245\def\tabulateline    {\HL} % just a spaced rule
2246\def\tabulateautorule{\HR}%
2247\def\tabulateautoline{\HL} % no longer different (to be looked into)
2248
2249%D When support for vertical rules we needed a way to pick up the specification for
2250%D the final rule and a \type {|{}} interface was chosen. As a result parsing had to
2251%D become more complex and I was not in the mood for messing up the code too much.
2252%D Therefore from now on the preamble is split by \LUA. There are definitely more
2253%D places where we can use \LUA\ code (for instance in alignment of numbers. The
2254%D repeat parser is replace at the \LUA\ end as well.
2255
2256\let\tabl_tabulate_flush_collected       \empty
2257\let\tabl_tabulate_flush_collected_indeed\empty
2258
2259\let\v_tabl_tabulate_align\!!zerocount
2260
2261\def\tabl_tabulate_check_side_float % new per 29-07-2016
2262  {\ifdefined\page_sides_check_floats_indeed
2263     \page_sides_check_floats_indeed
2264     \ifdim\hangindent>\zeropoint
2265       \advance\d_tabl_tabulate_indent\hangindent
2266     \fi
2267   \fi}
2268
2269\def\tabl_tabulate_set_local_hsize
2270  {\setlocalhsize
2271   \hsize\localhsize}
2272
2273\def\tabl_tabulate_process
2274  {\c_tabl_tabulate_pass\plusone
2275   \tabl_tabulate_check_full_content
2276   \edef\v_tabl_tabulate_align{\ifcsname\??tabulatealigning\p_align\endcsname\lastnamedcs\else0\fi}%
2277   \s_tabl_tabulate_first.5\d_tabl_tabulate_unit
2278   \s_tabl_tabulate_last\s_tabl_tabulate_first
2279   \s_tabl_tabulate_pre\zeropoint
2280   \s_tabl_tabulate_post\zeropoint
2281   \global\c_tabl_tabulate_columns\zerocount
2282   \global\c_tabl_tabulate_nofauto\zerocount
2283   \global\c_tabl_tabulate_noflines\zerocount
2284   \c_tabl_tabulate_totalnoflines\zerocount
2285   \c_tabl_tabulate_minusnoflines\zerocount
2286   \global\d_tabl_tabulate_width_p\zeropoint
2287   \global\d_tabl_tabulate_width_w\zeropoint
2288   \global\setfalse\c_tabl_tabulate_equal
2289   \tabl_tabulate_pheight_reset
2290   \tabskip\zeropoint
2291   \ifinsidesplitfloat
2292     \donetrue
2293   \else\ifinsidefloat
2294     \donefalse
2295   \else
2296     \donetrue
2297   \fi\fi
2298   \global\c_tabl_tabulate_repeathead
2299     \ifdone
2300       \ifcsname\??tabulateheader\tabulationparameter\c!header\endcsname
2301         \lastnamedcs
2302       \else
2303         \zerocount
2304       \fi
2305     \else
2306       \zerocount
2307     \fi
2308   %
2309   \the\t_tabl_tabulate_initializers_first % collect more here
2310   %
2311   \glet\tabl_tabulate_flush_collected\empty
2312   \ifdim\d_tabl_tabulate_margin>\zeropoint
2313     \t_tabl_tabulate_preamble
2314       {\aligntab
2315        \tabl_tabulate_flush_indent
2316        \strut
2317        \alignmark\alignmark
2318        \tabskip\d_tabl_tabulate_margin
2319        \strut
2320        \aligntab
2321        \alignmark\alignmark
2322        \tabskip\zeropoint}%
2323   \else
2324     \t_tabl_tabulate_preamble
2325       {\aligntab
2326        \tabl_tabulate_flush_indent
2327        \strut
2328        \alignmark\alignmark
2329        \aligntab
2330        \alignmark\alignmark
2331        \tabskip\zeropoint}%
2332   \fi
2333   \d_tabl_tabulate_width\zeropoint
2334   % these counters are set at the lua end
2335   \c_tabl_tabulate_nofcolumns         \zerocount
2336   \c_tabl_tabulate_has_rule_spec_first\zerocount
2337   \c_tabl_tabulate_has_rule_spec_last \zerocount
2338   \clf_presettabulate{\detokenizedtabulationparameter\c!format}%
2339   %
2340   \d_tabl_tabulate_width\zeropoint
2341   \tabl_tabulate_initialize_boxes\c_tabl_tabulate_columns
2342   \toksapp\t_tabl_tabulate_preamble{%
2343     \aligntab\alignmark\alignmark
2344     \global\advance\c_tabl_tabulate_column\plusone % maybe just set it already
2345   }%
2346   \toksapp\t_tabl_tabulate_dummy{%
2347     \NC\unskip\unskip\crcr\tabl_tabulate_flush_collected % no count
2348   }%
2349   \global\c_tabl_tabulate_column\zerocount
2350   \tabl_tabulate_pheight_reset
2351   \glet\tabl_tabulate_hook\tabl_tabulate_hook_yes
2352   \ifx\p_indenting\v!no
2353     \forgetparindent
2354   \fi
2355   \ifinsidefloat
2356     \d_tabl_tabulate_indent\zeropoint
2357   \else
2358     \tabl_tabulate_check_side_float
2359     \tabl_tabulate_set_local_hsize
2360   \fi
2361   \dontcomplain
2362   \forgetall % hm, interference with preceding \forgetparindent probably bug, to be solved
2363   \everypar\everytabulatepar
2364   \setbox\scratchbox\vbox % outside \if because of line counting
2365     {\notesenabledfalse
2366      \d_tabl_tabulate_indent\zeropoint
2367      \settrialtypesetting % very important
2368      \anch_backgrounds_text_level_start
2369      \expandafter\halign\expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}}%
2370      \anch_backgrounds_text_level_stop
2371      \ifcase\c_anch_backgrounds_text_state\else
2372        \global\settrue\tablehaspositions
2373      \fi
2374   \ifnum\c_tabl_tabulate_nofauto>\zerocount
2375     % so, even if the natural size is larger, in the final run, we force the calculated width
2376     \d_tabl_tabulate_width\dimexpr\hsize-\wd\scratchbox-\d_tabl_tabulate_width_p-\d_tabl_tabulate_width_w\relax
2377     \ifnum\c_tabl_tabulate_nofauto>\zerocount
2378       \divide\d_tabl_tabulate_width \c_tabl_tabulate_nofauto\relax
2379     \fi
2380   \fi
2381   \setbox\scratchbox\emptybox % free memory
2382   \ifconditional\c_tabl_tabulate_split
2383     \splittopskip\strutht
2384     \glet\tabl_tabulate_flush_collected_indeed\empty
2385     \glet\tabl_tabulate_flush_collected\tabl_tabulate_flush_second
2386   \fi
2387   \c_tabl_tabulate_totalnoflines\c_tabl_tabulate_noflines
2388   \c_tabl_tabulate_minusnoflines\numexpr\c_tabl_tabulate_noflines+\minusone\relax
2389   \global\c_tabl_tabulate_noflines\zerocount
2390   %
2391   \c_tabl_tabulate_pass\plustwo % final pass
2392   \the\t_tabl_tabulate_initializers_second % collect more here
2393   %
2394   \ifx\p_line\v!line
2395     \let\HL\HR
2396     \let\tabulateautoline\tabulateautorule
2397     \let\tabulateline\tabulaterule
2398   \fi
2399   %
2400   \ifcase\c_tabl_tabulate_repeathead
2401     \ifinsidesplitfloat
2402        \global\setbox\b_tabl_tabulate\vbox \bgroup
2403      \else
2404        \startframedcontent[\tabulationparameter\c!frame]%
2405      \fi
2406   \else
2407     \global\setbox\b_tabl_tabulate\vbox \bgroup
2408   \fi
2409   %
2410   \dostarttaggedchained\t!tabulate\empty\??tabulation
2411   \dostarttagged\t!tabulaterow\empty
2412   \setfalse\inhibitmargindata % new per 2012.06.13 ... really needed
2413   \toksapp\everycr{%
2414     \noalign{\the\t_tabl_tabulate_every_real_row}%
2415     \dostoptagged
2416     \dostarttagged\t!tabulaterow\empty
2417   }%
2418    % we are in sync but just to be sure:
2419   \synchronizedisplaydirection
2420   \synchronizeinlinedirection
2421   \halign
2422     \usedirectionparameterreverse\tabulateparameter
2423     \expandafter{\the\t_tabl_tabulate_preamble\crcr\tabl_tabulate_insert_content\crcr}%
2424   \dostoptagged
2425   \dostoptagged
2426   \ifhmode\par\prevdepth\strutdp\fi % temporary hack
2427   \ifx\p_distance\v!grid
2428     \vskip-\strutdp % experimental tm-prikkels
2429   \fi
2430   %
2431   \ifcase\c_tabl_tabulate_repeathead
2432     \ifinsidesplitfloat
2433       \egroup % box
2434       \egroup % settings
2435       \tabl_split_box\b_tabl_tabulate
2436     \else
2437       \stopframedcontent
2438       \egroup
2439     \fi
2440   \else
2441     \egroup % box
2442     \egroup % settings
2443     \tabl_split_box\b_tabl_tabulate
2444   \fi
2445   %
2446   \ifinsidefloat
2447     \tabl_tabulate_inside_after
2448   \else
2449     \tabl_tabulate_outside_after
2450   \fi
2451   \egroup} % whole thing
2452
2453% \egroup
2454
2455% \setuptabulate[split=yes,header=text,title=Vervolg van Tabel]
2456%
2457% % \starttabulatehead
2458% % \NC test \NC hans\NC \NR
2459% % \stoptabulatehead
2460%
2461% \starttabulate
2462% \NC test \NC \input tufte \relax \NC \NR
2463% \NC test \NC \input knuth \relax \NC \NR
2464% \NC test \NC \input knuth \relax \NC \NR
2465% \NC test \NC \input tufte \relax \NC \NR
2466% \NC test \NC \input tufte \relax \NC \NR
2467% \NC test \NC \input tufte \relax \NC \NR
2468% \stoptabulate
2469
2470\def\tabl_split_box#1% #1 <> 0/2 / derived from the one in core-ntb.tex
2471  {\ifinsidesplitfloat
2472     \tabl_split_box_indeed#1%
2473   \else\ifinsidefloat
2474     \unvbox#1%
2475   \else
2476     \tabl_split_box_indeed#1%
2477   \fi\fi}
2478
2479\def\tabl_split_box_indeed#1%
2480  {\resettsplit
2481   \def\tsplitminimumfreelines{2}%
2482   \def\tsplitminimumfreespace{0pt}%
2483   \setbox\tsplitcontent\box#1%
2484   \ifcase\c_tabl_tabulate_repeathead\or
2485     \setbox\tsplithead\vsplit\tsplitcontent to \lineheight
2486     \setbox\tsplithead\vbox{\unvbox\tsplithead}%
2487   \or
2488     \setbox\tsplithead\vbox{\hbox{\strut\tabulationparameter\c!title}}%
2489   \fi
2490   \handletsplit}
2491
2492%D \starttyping
2493%D \setuptabulate[split=no,rule=line]
2494%D
2495%D \starttabulate
2496%D \NC tufte \NC \input tufte \NC \NR \tabulateautorule
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 \stoptabulate
2503%D \stoptyping
2504
2505%D Spacing:
2506%
2507% \starttabulate
2508% \NC text \NC text \NC \NR
2509% \TB[small]
2510% \NC text \NC text \NC \NR
2511% \TB[4*big]
2512% \NC text \NC text \NC \NR
2513% \stoptabulate
2514
2515\def\tabl_tabulate_TB
2516  {\starttabulatenoalign
2517   \dosingleempty\tabl_tabulate_TB_indeed}
2518
2519\def\tabl_tabulate_TB_indeed[#1]%
2520  {\iffirstargument
2521     \blank[#1]
2522   \else\ifx\m_tabl_tabulate_blank_default\empty
2523     \blank
2524   \else
2525     \blank[\m_tabl_tabulate_blank_default]%
2526   \fi\fi
2527   \stoptabulatenoalign}
2528
2529% to be tested:
2530%
2531% \def\tabl_tabulate_TB
2532%   {\starttabulatenoalign
2533%    \doiffastoptionalcheckelse\tabl_tabulate_TB_yes\tabl_tabulate_TB_nop}
2534%
2535% \def\tabl_tabulate_TB_yes[#1]%
2536%   {\blank[#1]
2537%    \stoptabulatenoalign}
2538%
2539% \def\tabl_tabulate_TB_nop[#1]%
2540%   {\blank
2541%    \stoptabulatenoalign}
2542
2543\appendtoks
2544    \let\TB\tabl_tabulate_TB
2545\to \everytabulate
2546
2547% %D Between alignment lines certain rules apply, and even a simple test can mess
2548% %D up a table, which is why we have a special test facilityL
2549% %D
2550% %D \startbuffer
2551% %D \starttabulate[|l|p|]
2552% %D \NC 1test \NC test \NC \NR
2553% %D \tableifelse{\doifelse{a}{a}}{\NC Xtest \NC test \NC \NR}{}%
2554% %D \stoptabulate
2555% %D \stopbuffer
2556% %D
2557% %D \typebuffer \getbuffer
2558%
2559% \def\tableifelse#1% should be tabulatenoalign then
2560%   {\tablenoalign
2561%      {#1%
2562%        {\aftergroup \firstoftwoarguments}%
2563%        {\aftergroup\secondoftwoarguments}}}
2564%
2565% \def\tableiftextelse#1{\tableifelse{\doiftextelse{#1}}}
2566
2567%D Some new trickery:
2568%D
2569%D \startbuffer
2570%D \settrue\c_tabl_tabulate_splitoff_whitespace
2571%D
2572%D \starttabulate[|p(2cm)|p(2cm)|p(2cm)|]
2573%D     \NC test 1a \NC test 2a \NC test 3a
2574%D                                 \par
2575%D                                 test 3b          \NC \NR
2576%D     \NC test 1a \NC test 2a \NC test 3a
2577%D                                 \blank[line]
2578%D                                 test 3b          \NC \NR
2579%D     \NC test 1a \NC test 2a \NC test 3a
2580%D                                 \blank[halfline]
2581%D                                 test 3b
2582%D                                 \blank[halfline]
2583%D                                 test 3c          \NC \NR
2584%D     \NC \blank  \NC \blank  \NC \blank           \NC \NR
2585%D     \NC test 1a \NC test 2a \NC test 3a
2586%D                                 \blank[halfline]
2587%D                                 test 3b
2588%D                                 \blank[halfline]
2589%D                                 test 3c          \NC \NR
2590%D     \NC \blank  \NC \blank  \NC                  \NC \NR
2591%D     \NC test 1a
2592%D         \par
2593%D         test 1b
2594%D         \par
2595%D         test 1b \NC test 2a
2596%D                     \par
2597%D                     test 2b
2598%D                     \par
2599%D                     test 2b \NC test 3a          \NC \NR
2600%D     \NC test 1a
2601%D         \blank
2602%D         test 1b
2603%D         \par
2604%D         test 1b \NC test 2a
2605%D                     \par
2606%D                     test 2b
2607%D                     \blank
2608%D                     test 2b \NC test 3a          \NC \NR
2609%D \stoptabulate
2610%D \stopbuffer
2611%D
2612%D \typebuffer \start \getbuffer \stop
2613
2614% \starttabulatie[|mc|]
2615% \NC \digits{100.000,00} \NC\NR
2616% \NC \digits{@10.000,00} \NC\NR
2617% \NC \digits{@@@.100,00} \NC\NR
2618% \NC \digits{@@@.@10,@@} \NC\NR
2619% \NC \digits{@@@.@@1,@@} \NC\NR
2620% \stoptabulatie
2621%
2622% \starttabulatie[|mc|]
2623% \ND 100.000,00 \NC\NR
2624% \ND @10.000,00 \NC\NR
2625% \ND @@@.100,00 \NC\NR
2626% \ND @@@.@10,@@ \NC\NR
2627% \ND @@@.@@1,@@ \NC\NR
2628% \stoptabulatie
2629%
2630% \starttabulatie[|c|]
2631% \ND $100.000,00$ \NC\NR
2632% \ND $@10.000,00$ \NC\NR
2633% \ND $@@@.100,00$ \NC\NR
2634% \ND $@@@.@10,@@$ \NC\NR
2635% \ND $@@@.@@1,@@$ \NC\NR
2636% \stoptabulatie
2637%
2638% \starttabulatie[|c|]
2639% \NC $\digits 100.000,00 $ \NC\NR
2640% \NC $\digits @10.000,00 $ \NC\NR
2641% \NC $\digits @@@.100,00 $ \NC\NR
2642% \NC $\digits @@@.@10,@@ $ \NC\NR
2643% \NC $\digits @@@.@@1,@@ $ \NC\NR
2644% \stoptabulatie
2645%
2646% \starttabulatie[|c|]
2647% \NC \digits $100.000,00$ \NC\NR
2648% \NC \digits $@10.000,00$ \NC\NR
2649% \NC \digits $@@@.100,00$ \NC\NR
2650% \NC \digits $@@@.@10,@@$ \NC\NR
2651% \NC \digits $@@@.@@1,@@$ \NC\NR
2652% \stoptabulatie
2653
2654%D Predefined categories (moved from core-mis):
2655
2656\definetabulate
2657  [\v!legend]
2658  [|emj1|i1|mR|]
2659
2660\setuptabulate
2661  [\v!legend]
2662  [\c!unit=.75em,\c!inner=\setquicktabulate\leg,EQ={=}]
2663
2664\definetabulate
2665  [\v!legend][\v!two]
2666  [|emj1|emk1|i1|mR|]
2667
2668\definetabulate
2669  [\v!fact]
2670  [|R|ecmj1|i1mR|]
2671
2672\setuptabulate
2673  [\v!fact]
2674  [\c!unit=.75em,\c!inner=\setquicktabulate\fact,EQ={=}]
2675
2676%D Another example:
2677%D
2678%D \starttyping
2679%D \definetabulate
2680%D   [whatever]
2681%D   [|l|r|]
2682%D
2683%D \definetabulate
2684%D   [whatever][else]
2685%D   [|l|c|r|]
2686%D
2687%D \startwhatever
2688%D \NC l    \NC r     \NC \NR
2689%D \NC left \NC right \NC \NR
2690%D \stopwhatever
2691%D
2692%D \startwhatever[else]
2693%D \NC l    \NC m      \NC r     \NC \NR
2694%D \NC left \NC middle \NC right \NC \NR
2695%D \stopwhatever
2696%D
2697%D \startwhatever[else][format={|c|c|c|c|}]
2698%D \NC l    \NC m      \NC m      \NC r     \NC \NR
2699%D \NC left \NC middle \NC middle \NC right \NC \NR
2700%D \stopwhatever
2701%D \stoptyping
2702
2703%D This is needed because we sometimes use the english command in tracing macros. In
2704%D fact, most detailed tracing macros that are done with \LUA\ only work in the
2705%D english interface anyway.
2706
2707% \definetabulate[tabulate] \setuptabulate[tabulate][\c!format=\v!none] % so no \v! here
2708
2709\newconditional\c_tabl_generic
2710
2711\unexpanded\setuvalue{starttabulate}%
2712  {\bgroup % whole thing
2713   \settrue\c_tabl_generic
2714   \let\currenttabulationparent\empty
2715   \dodoubleempty\tabl_start_regular}
2716
2717\letvalue{stoptabulate}\relax
2718
2719%D The following helpers are just there because we also have them at the \LUA\ end:
2720%D
2721%D \startbuffer
2722%D \starttabulate[|l|c|r|]
2723%D     \tabulaterow    {a,b,c}
2724%D     \tabulaterowbold{aa,bb,cc}
2725%D     \tabulaterowtype{aaa,bbb,ccc}
2726%D     \tabulaterowtyp {aaaa,bbbb,cccc}
2727%D \stoptabulate
2728%D \stopbuffer
2729%D
2730%D \typebuffer \getbuffer
2731
2732\def\tabl_tabulate_compact_row#1#2%
2733  {\NC\tabl_tabulate_compact_step#1#2,\end,}
2734
2735\def\tabl_tabulate_compact_step#1#2#3,%
2736  {\ifx#2\end
2737     \NR
2738     \expandafter\gobbleoneargument
2739   \else
2740     #1{#2#3}\NC
2741     \expandafter\tabl_tabulate_compact_step
2742   \fi#1}
2743
2744\unexpanded\def\tabulaterow    {\tabl_tabulate_compact_row\relax}
2745\unexpanded\def\tabulaterowbold{\tabl_tabulate_compact_row\bold}
2746\unexpanded\def\tabulaterowtype{\tabl_tabulate_compact_row\type}
2747\unexpanded\def\tabulaterowtyp {\tabl_tabulate_compact_row\typ}
2748
2749%D Here we plug in a row background feature. As we only have support for
2750%D \type {frame=name} we can use these variables.
2751%D
2752%D \starttyping
2753%D \startuseMPgraphic{foo}
2754%D     fill unitsquare
2755%D         xyscaled (RuleWidth,RuleHeight+RuleDepth) enlarged (ExHeight/4,ExHeight/8)
2756%D         randomized ExHeight
2757%D         shifted  (-ExHeight/8,ExHeight/16)
2758%D         withcolor RuleColor ;
2759%D \stopuseMPgraphic
2760%D
2761%D \setuptabulate % wel only have frame=name so we can use these:
2762%D   [background=foo,
2763%D    backgroundcolor=darkred,
2764%D    foregroundcolor=white]
2765%D
2766%D \definelinefiller[foo][mp=foo,color=darkgreen]
2767%D \definelinefiller[bar][mp=foo,color=darkred]
2768%D
2769%D \starttabulate[|||]
2770%D     \DB foo \BC bar \BC \NR
2771%D     \NC foo \NC bar \NC \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 \stoptabulate
2776%D
2777%D \starttabulate[|||]
2778%D     \PB foo \BC bar \BC \NR
2779%D     \NC foo \NC bar \NC \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 \stoptabulate
2784%D
2785%D \starttabulate[|||]
2786%D     \FB[bar] foo \BC bar \BC \NR
2787%D     \NC      foo \NC bar \NC \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 \stoptabulate
2792%D
2793%D \startnarrower
2794%D     \starttabulate[|||]
2795%D         \DB foo \DB bar \BC \NR
2796%D         \NC foo \NC bar \NC \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     \stoptabulate
2801%D \stopnarrower
2802%D
2803%D \starttabulate[|||]
2804%D     \BC          foo \BC bar \BC \NR
2805%D     \NL[magenta] foo \NC bar \NC \NR
2806%D     \NL[yellow]  foo \NC bar \NC \NR
2807%D     \NL[cyan]    foo \NC bar \NC \NR
2808%D     \NL[gray]    foo \NC bar \NC \NR
2809%D \stoptabulate
2810%D
2811%D \starttabulate
2812%D     \NL[red]     foo \NC bar \NC \NR
2813%D     \NL[green]   foo \NL[red] bar \NC \NR
2814%D     \NC          foo \NC bar \NC \NR
2815%D     \NL[blue]    foo \NC \input tufte  \NC \NR
2816%D     \NL[gray]    foo \NC bar \NC \NR
2817%D     \NL[yellow]  foo \NC bar \NC \NR
2818%D \stoptabulate
2819%D \stoptyping
2820
2821% \setuptabulate
2822%   [\c!background=,
2823%    \c!backgroundcolor=,
2824%    \c!foregroundcolor=,
2825%    \c!foregroundstyle=]
2826
2827\let\m_table_current_row_background              \empty
2828\let\m_table_current_row_background_default      \empty
2829\let\m_table_current_row_background_filler       \empty
2830\let\m_table_current_row_background_defaultfiller\empty
2831\let\m_table_current_row_background_auto         \empty
2832
2833\unexpanded\def\tabl_register_row_background#1%
2834  {\xdef\m_table_current_row_background{#1}}
2835
2836\unexpanded\def\tabl_register_row_background_filler#1%
2837  {\xdef\m_table_current_row_background_filler{#1}}
2838
2839\unexpanded\def\tabl_synchronize_row_background
2840  {\iftrialtypesetting\else
2841     \ifx\m_table_current_row_background_filler\empty
2842       \ifx\m_table_current_row_background\empty
2843         % nothing
2844         \tabl_synchronize_row_background_dummy
2845       \else
2846         \tabl_synchronize_row_background_indeed\m_table_current_row_background
2847       \fi
2848     \else
2849       \tabl_synchronize_row_background_filler_indeed\m_table_current_row_background_filler
2850     \fi
2851   \fi}
2852
2853\unexpanded\def\tabl_synchronize_row_background_dummy
2854  {\iftrialtypesetting\else
2855     \begingroup
2856    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\zerocount\zeropoint
2857     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\zerocount\zeropoint
2858     \endgroup
2859   \fi}
2860
2861\unexpanded\def\tabl_synchronize_row_background_indeed#1%
2862  {\iftrialtypesetting\else
2863     \begingroup
2864     \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
2865     \dousecolorparameter{#1}%
2866     \setbox\scratchbox\hpack{}%
2867    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
2868     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
2869     \endgroup
2870   \fi}
2871
2872\unexpanded\def\tabl_synchronize_row_background_filler_indeed#1%
2873  {\iftrialtypesetting\else
2874     \begingroup
2875     \clf_enablebackgroundalign % can be moved into \clf_setbackgroundrowdata
2876     \node_linefiller_set{#1}%
2877     \setbox\scratchbox\hpack{}%
2878    %\clf_setbackgroundrowdata\numexpr\c_tabl_tabulate_nofrealrows+\minusone\relax\scratchbox\d_tabl_tabulate_indent
2879     \clf_setbackgroundrowdata\c_tabl_tabulate_nofrealrows\scratchbox\d_tabl_tabulate_indent
2880     \endgroup
2881   \fi}
2882
2883\appendtoks
2884    \glet\m_table_current_row_background\empty
2885    \glet\m_table_current_row_background_filler\empty
2886    \global\c_tabl_tabulate_nofrealrows\zerocount
2887    \global\c_tabl_tabulate_autocolor\zerocount
2888    \clf_resetbackgroundrowdata
2889\to \t_tabl_tabulate_initializers_first
2890
2891\appendtoks
2892    \glet\m_table_current_row_background\empty
2893    \glet\m_table_current_row_background_filler\empty
2894    \global\c_tabl_tabulate_nofrealrows\zerocount
2895    \global\c_tabl_tabulate_autocolor\zerocount
2896    \clf_resetbackgroundrowdata
2897\to \t_tabl_tabulate_initializers_second
2898
2899\appendtoks
2900    \tabl_synchronize_row_background
2901\to \t_tabl_tabulate_every_real_row
2902
2903\appendtoks
2904    \glet\m_table_current_row_background\empty
2905    \glet\m_table_current_row_background_filler\empty
2906\to \t_tabl_tabulate_every_after_row
2907
2908\unexpanded\def\tabl_tabulate_NL_first[#1]%
2909  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2910   \ifcase\c_tabl_tabulate_column\or
2911     \tabl_register_row_background{#1}%
2912   \fi
2913   \ignorespaces}
2914
2915\unexpanded\def\tabl_tabulate_ND_first
2916  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2917   \ifcase\c_tabl_tabulate_column\or
2918     \tabl_register_row_background\m_table_current_row_background_default
2919   \fi
2920   \ignorespaces}
2921
2922\unexpanded\def\tabl_tabulate_LB_first[#1]%
2923  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2924   \ifcase\c_tabl_tabulate_column\or
2925     \tabl_register_row_background{#1}%
2926   \fi
2927   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2928   \ignorespaces}
2929
2930\unexpanded\def\tabl_tabulate_DB_first
2931  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2932   \ifcase\c_tabl_tabulate_column\or
2933     \tabl_register_row_background\m_table_current_row_background_default
2934   \fi
2935   \let\fontstyle\globalfontstyle
2936   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2937   \ignorespaces}
2938
2939\unexpanded\def\tabl_tabulate_NF_first[#1]%
2940  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2941   \ifcase\c_tabl_tabulate_column\or
2942     \tabl_register_row_background_filler{#1}%
2943   \fi
2944   \ignorespaces}
2945
2946\unexpanded\def\tabl_tabulate_NP_first
2947  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2948   \ifcase\c_tabl_tabulate_column\or
2949     \tabl_register_row_background_filler\m_table_current_row_background_default_filler
2950   \fi
2951   \ignorespaces}
2952
2953\unexpanded\def\tabl_tabulate_FB_first[#1]%
2954  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2955   \ifcase\c_tabl_tabulate_column\or
2956     \tabl_register_row_background_filler{#1}%
2957   \fi
2958   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2959   \ignorespaces}
2960
2961\unexpanded\def\tabl_tabulate_PB_first
2962  {\tabl_tabulate_column_normal\plusone\zerocount\relax
2963   \ifcase\c_tabl_tabulate_column\or
2964     \tabl_register_row_background_filler\m_table_current_row_background_default_filler
2965   \fi
2966   \let\fontstyle\globalfontstyle
2967   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2968   \ignorespaces}
2969
2970\unexpanded\def\tabl_tabulate_BC_first % overloaded
2971  {\tabl_tabulate_column_normal\plusone\zerocount
2972   \let\fontstyle\globalfontstyle
2973   \ifx\m_table_current_row_background\empty
2974     \ifx\m_table_current_row_background_filler\empty
2975       \usetabulationstyleandcolor\c!headstyle\c!headcolor
2976     \else
2977       \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2978     \fi
2979   \else
2980     \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
2981   \fi}
2982
2983\unexpanded\def\tabl_tabulate_A_first
2984  {\global\advance\c_tabl_tabulate_autocolor\plusone
2985   \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
2986   \ifx\m_table_current_row_background_auto\empty
2987     \global\c_tabl_tabulate_autocolor\plusone
2988     \edef\m_table_current_row_background_auto{\tabulateparameter{\c!backgroundcolor:\number\c_tabl_tabulate_autocolor}}%
2989   \fi
2990   \ifx\m_table_current_row_background_auto\empty
2991     \let\m_table_current_row_background_auto\empty % \m_table_current_row_background_default
2992   \fi
2993   \tabl_register_row_background{\m_table_current_row_background_auto}}
2994
2995\unexpanded\def\tabl_tabulate_NA_first
2996  {\tabl_tabulate_column_normal\zerocount\zerocount\relax
2997   \iftrialtypesetting\else
2998     \ifcase\c_tabl_tabulate_column\or
2999       \tabl_tabulate_A_first
3000     \fi
3001   \fi
3002   \ignorespaces}
3003
3004\unexpanded\def\tabl_tabulate_BA_first
3005  {\tabl_tabulate_column_normal\plusone\zerocount\relax
3006   \iftrialtypesetting\else
3007     \ifcase\c_tabl_tabulate_column\or
3008       \tabl_tabulate_A_first
3009     \fi
3010   \fi
3011   \usetabulationstyleandcolor\c!foregroundstyle\c!foregroundcolor
3012   \ignorespaces}
3013
3014\appendtoks
3015    \let\NL\tabl_tabulate_NL_first % NC with Line
3016    \let\ND\tabl_tabulate_ND_first % NC with Default Line
3017    \let\LB\tabl_tabulate_LB_first % BC with Line
3018    \let\DB\tabl_tabulate_DB_first % BC with Default Line
3019    \let\NF\tabl_tabulate_NF_first % NC with Filler
3020    \let\NP\tabl_tabulate_NP_first % NC with Predefined Filler
3021    \let\FB\tabl_tabulate_FB_first % BC with Filler
3022    \let\PB\tabl_tabulate_PB_first % BC with Predefined Filler
3023    \let\NA\tabl_tabulate_NA_first % NC with Auto Line
3024    \let\BA\tabl_tabulate_BA_first % NC with Auto Line
3025\to \t_tabl_tabulate_initializers_first
3026
3027\appendtoks
3028   \edef\m_table_current_row_background_default       {\tabulateparameter\c!backgroundcolor}%
3029   \edef\m_table_current_row_background_default_filler{\tabulateparameter\c!background}%
3030   \let \m_table_current_row_background_auto           \empty
3031\to \everytabulate
3032
3033\setuptabulate
3034  [\c!headcolor=,
3035   \c!headstyle=\bf,
3036   \c!backgroundcolor=\tabulationparameter\c!rulecolor,
3037   \c!foregroundcolor=,
3038   \c!foregroundstyle=\tabulationparameter\c!headstyle]
3039
3040\protect \endinput
3041