tabl-ltb.mkxl /size: 24 Kb    last modification: 2023-12-21 09:44
1%D \module
2%D   [       file=tabl-ltb,
3%D        version=2002.10.31, % updated 2016.01.08
4%D          title=\CONTEXT\ Table Macros,
5%D       subtitle=Line Tables,
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%D This module was made for some special project where we needed to typeset tables
15%D spanning spanning many pages horizontally and vertically, with repeated header
16%D lines and (entry) columns, tab tracking, color, etc. We do two passes over a
17%D table, which is why the table can go into a buffer or file. As said, tables can
18%D be real huge but performance is still quite okay (there is room for some speed
19%D up). The code has been adapted to \MKIV\ but the functionality is the same as in
20%D \MKII.
21
22% \BH \BC .. \EC \BC .. \EC \EH % append
23% \BR \BC .. \EC \BC .. \EC \ER
24%
25% or
26%
27% \NC .. \NC .. \NC \NR (todo: optional last \NC)
28
29% alternative:
30%
31% (1) direct run, save content in macro, but only if needed
32%
33% todo
34%
35% (2) buffered table content
36%
37% \startbuffer
38%   \startlinetablehead
39%   \stoplinetablehead
40%   \startlinetablebody
41%   \stoplinetablebody
42% \stopbuffer
43%
44% \processlinetablebuffer[buffer]
45%
46% in buffer : head and body
47%
48% (3) unbuffered run, multipass
49%
50% - run with starting width zero / prev run
51% - clip on prev run
52% - flush real widths
53
54\writestatus{loading}{ConTeXt Table Macros / Line Tables}
55
56\unprotect
57
58\installcorenamespace{linetable}
59\installcorenamespace{linetablepart}
60\installcorenamespace{linetablewidth}
61\installcorenamespace{linetableheight}
62\installcorenamespace{linetabledepth}
63
64% (For now) we share these three:
65
66\aliased\let\tabl_lines_initialize_box  \tabl_tabulate_initialize_box
67\aliased\let\tabl_lines_initialize_boxes\tabl_tabulate_initialize_boxes
68\aliased\let\b_tabl_lines_current       \b_tabl_tabulate_current
69
70\newconditional \c_tabl_lines_preroll
71\newconditional \c_tabl_lines_in_table
72
73\newdimension   \d_tabl_lines_width
74\newdimension   \d_tabl_lines_height
75%newdimension   \d_tabl_lines_depth
76
77\newbox         \b_tabl_lines_cell
78
79\newinteger     \c_tabl_lines_n_of_columns
80\newinteger     \c_tabl_lines_n_of_rows
81\newinteger     \c_tabl_lines_n_of_lines
82\newinteger     \c_tabl_lines_n_of_parts
83\newinteger     \c_tabl_lines_part           \c_tabl_lines_part\plusone
84\newinteger     \c_tabl_lines_step           \c_tabl_lines_step\plusone
85\newinteger     \c_tabl_lines_line
86\newinteger     \c_tabl_lines_row
87\newinteger     \c_tabl_lines_rows
88\newinteger     \c_tabl_lines_column
89\newinteger     \c_tabl_lines_subcol
90
91\newconstant    \c_tabl_lines_hmode
92\newconstant    \c_tabl_lines_page
93\newconstant    \c_tabl_lines_repeat
94\newconstant    \c_tabl_lines_split_state
95\newconstant    \c_tabl_lines_head_state
96\newconstant    \c_tabl_lines_mode
97
98\newtoks        \t_tabl_lines_head
99
100\newconditional \linetableautoheight  \linetableautoheight\conditionaltrue
101
102\tabl_lines_initialize_box\zerocount % holds repeater
103
104\pushoverloadmode
105
106\permanent\tolerant\protected\def\setuplinetable[#S#1]#*[#S#2]#*[#S#3]%
107  {\ifarguments\or
108     \getparameters[\??linetable][#1]%
109   \or
110     \getparameters[\??linetable#1:][#2]%
111   \or
112     \getparameters[\??linetable#1:#2][#3]%
113   \fi}
114
115\permanent\def\linetableparameter#1%
116  {\begincsname\??linetable#1\endcsname}
117
118\permanent\protected\def\doifelselinetablecparameter#1%
119  {\ifcsname\??linetable c:\the\c_tabl_lines_column#1\endcsname
120     \expandafter\firstoftwoarguments
121   \orelse\ifcsname\??linetable c:#1\endcsname
122     \expandafter\firstoftwoarguments
123   \else
124     \expandafter\secondoftwoarguments
125   \fi}
126
127\aliased\let\doiflinetablecparameterelse\doifelselinetablecparameter
128
129\permanent\def\linetablecparameter#1%
130  {\begincsname
131     \??linetable
132     \ifcsname\??linetable c:\the\c_tabl_lines_column#1\endcsname
133       c:\the\c_tabl_lines_column
134     \orelse\ifcsname\??linetable c:#1\endcsname
135       c:%
136     \fi
137     #1%
138   \endcsname}
139
140\permanent\def\linetablerparameter#1% faster, leaner and meaner
141  {\begincsname
142     \??linetable
143   % \ifnum\c_tabl_lines_row=\zerocount % geen ifcase
144     \ifzero\c_tabl_lines_row
145       \ifcsname\??linetable r:\v!header#1\endcsname
146         r:\v!header
147       \orelse\ifcsname\??linetable r:0#1\endcsname
148         r:0%
149       \fi
150     \else
151       \ifcsname\??linetable r:\the\c_tabl_lines_row#1\endcsname
152         r:\the\c_tabl_lines_row
153       \orelse\ifcsname\??linetable r:\v!oddeven\c_tabl_lines_row#1\endcsname
154         r:\v!oddeven\c_tabl_lines_row
155       \fi
156     \fi
157     #1%
158   \endcsname}
159
160\protected\def\tabl_lines_set
161  {\edef\p_lines{\linetableparameter\c!lines}%
162   \ifx\p_lines\v!fit
163     \tabl_lines_set_indeed
164   \else
165     \global\c_tabl_lines_n_of_lines\p_lines
166   \fi}
167
168\protected\def\tabl_lines_set_indeed
169  {% whitespace already added by vertical strut
170  %\triggerpagebuilder
171   \scratchdimen
172     \ifdim\pagegoal<\maxdimen
173       \dimexpr\pagegoal-\pagetotal\relax
174     \else
175       \textheight
176     \fi
177   \getrawnoflines\scratchdimen
178   \global\c_tabl_lines_n_of_lines\noflines
179   \ifconditional\c_tabl_lines_preroll\orelse\ifnum\c_tabl_lines_n_of_lines<\plustwo
180     \page
181     \tabl_lines_set
182   \fi}
183
184\def\tabl_lines_step_cell
185  {\advanceby\scratchdimen\linetablecparameter\c!width
186   \global\advanceby      \c_tabl_lines_column\plusone
187   \advanceby\scratchskip \linetablecparameter\c!distance}
188
189\permanent\tolerant\protected\def\startlinetablecell[#S#1]%
190  {\global\setbox\b_tabl_lines_cell\hbox\bgroup
191   \ifparameter#1\or
192     \getparameters[\??linetable c:\the\c_tabl_lines_column][#1]%
193   \fi
194   \global\c_tabl_lines_step\linetablecparameter\c!nx\relax
195   \ifcase\c_tabl_lines_step\or
196     \scratchdimen\linetablecparameter\c!width
197     \scratchskip \linetablecparameter\c!distance
198   \else
199     \scratchdimen  \zeropoint
200     \scratchskip   \zeroskip
201     \scratchcounter\c_tabl_lines_column
202     \dorecurse\c_tabl_lines_step\tabl_lines_step_cell
203     \global\c_tabl_lines_column\scratchcounter
204   \fi
205   \c_tabl_lines_mode
206     \ifconditional\c_tabl_lines_preroll
207       \ifdim\scratchdimen>\zeropoint \zerocount \else \plustwo \fi
208     \else
209       \zerocount
210     \fi
211   \ifcase\c_tabl_lines_mode
212     \ifcase\c_tabl_lines_hmode
213       % nothing
214     \or
215       % fit, keep it simple
216     \or
217       \c_tabl_lines_mode\plusone % line
218     \else
219       % some already calculated height
220     \fi
221   \fi
222   \setbox\scratchbox\hbox
223     \bgroup
224     \dontcomplain
225     \hskip\linetablecparameter\c!leftoffset\relax
226     % 0 = width, unknown height
227     % 1 = width, fixed height
228     % 2 = no width, auto hsize
229     \ifnum\c_tabl_lines_mode<\plustwo
230       \advanceby\scratchdimen-\linetablecparameter\c!leftoffset
231       \advanceby\scratchdimen-\linetablecparameter\c!rightoffset
232     \fi
233     \ifcase\c_tabl_lines_mode
234       \dosetraggedcommand{\linetablecparameter\c!align}%
235       \vtop \ifdim\d_tabl_lines_height>\zeropoint to\d_tabl_lines_height \fi \bgroup
236         \hsize\scratchdimen
237         \raggedcommand
238     \else
239       \setalignmentswitch{\linetablecparameter\c!align}%
240       \hbox \ifcase\c_tabl_lines_mode \or to\scratchdimen \fi \bgroup
241         \ifcase\alignmentswitch\hss\or\hss\fi
242     \fi
243     \dousestyleparameter{\linetablecparameter\c!style}%
244     \dousecolorparameter{\linetablecparameter\c!color}%
245     \begstrut \ignorespaces}
246
247\permanent\protected\def\stoplinetablecell
248  {\unskip \endstrut
249   \ifcase\c_tabl_lines_mode
250     \endgraf
251   \else
252     \ifcase\alignmentswitch\else\hss\fi
253   \fi
254   \egroup
255   \hskip\linetablecparameter\c!rightoffset
256   \egroup
257   \ifconditional\c_tabl_lines_preroll
258     \box\scratchbox
259   \else
260     \tabl_lines_wrap_up
261   \fi
262   \egroup}
263
264\def\tabl_lines_wrap_up
265  {\ifcstok{\linetablecparameter\c!background}\v!color
266     \ifconditional\linetableautoheight
267       \tabl_lines_wrap_up_auto
268     \else
269       \tabl_lines_wrap_up_line
270      \fi
271   \else
272     \box\scratchbox
273   \fi}
274
275% \startuseMPgraphic{one}
276%     path p, q ;
277%     numeric r ;
278%     r := RuleThickness ;
279%     p := unitsquare xysized(RuleWidth,RuleHeight+RuleDepth) ;
280%     q := p topenlarged -r bottomenlarged -r ;
281%     draw q ;
282%     setbounds currentpicture to p;
283% \stopuseMPgraphic
284%
285% \setuplinetable[r][odd] [type=mp,mp=one,backgroundcolor=gray,rulethickness=1pt]
286% \setuplinetable[r][even][type=mp,mp=one,backgroundcolor=green,rulethickness=1pt]
287%
288% \startlinetable
289%     \dorecurse{10}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
290% \stoplinetable
291
292\def\tabl_lines_wrap_up_auto
293  {\edef\p_height{\linetablerparameter{x\c!height}}%
294   \edef\p_depth {\linetablerparameter{x\c!depth }}%
295   \hpack
296     {\blackrule
297        [ \c!color=\linetablecparameter\c!backgroundcolor,
298           \c!type=\linetablecparameter\c!type,
299             \c!mp=\linetablecparameter\c!mp,
300  \c!rulethickness=\linetablecparameter\c!rulethickness,
301         \c!height=\ifempty\p_height\ht\scratchbox\else\p_height\fi,
302          \c!depth=\ifempty\p_depth \dp\scratchbox\else\p_depth \fi,
303          \c!width=\wd\scratchbox]%
304      \hkern-\wd\scratchbox\box\scratchbox}}
305
306\def\tabl_lines_wrap_up_auto_r
307  {\hpack
308     {\blackrule
309        [ \c!color=\linetablerparameter\c!backgroundcolor,
310           \c!type=\linetablerparameter\c!type,
311             \c!mp=\linetablerparameter\c!mp,
312  \c!rulethickness=\linetablerparameter\c!rulethickness,
313         \c!height=\ht\scratchbox,
314          \c!depth=\dp\scratchbox,
315          \c!width=\wd\scratchbox]%
316      \hkern-\wd\scratchbox\box\scratchbox}}
317
318\def\tabl_lines_wrap_up_line
319  {\backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}}
320
321\def\tabl_lines_save_part
322  {\global\setbox\b_tabl_lines_current\c_tabl_lines_part
323   \ifcase\c_tabl_lines_part\relax
324     \box\scratchbox % just storing
325   \else
326     \vbox
327       {\ifvoid\b_tabl_lines_current\c_tabl_lines_part\else\unvbox\b_tabl_lines_current\c_tabl_lines_part\fi
328        \ifcstok{\linetablerparameter\c!background}\v!color
329          \backgroundline[\linetablerparameter\c!backgroundcolor]{\box\scratchbox}%
330        \orelse\ifempty{\linetablerparameter\c!type}%
331          \box\scratchbox
332        \else
333          \tabl_lines_wrap_up_auto_r
334        \fi
335        \endgraf
336        \linetablerparameter\c!after}%
337   \fi}
338
339\def\tabl_lines_flush_parts
340  {\global\advanceby\c_tabl_lines_line\plusone
341   \ifnum\c_tabl_lines_line<\c_tabl_lines_n_of_lines
342     % keep collecting
343   \else
344     \ifconditional\c_tabl_lines_preroll
345       % forget about them
346     \else
347       \dorecurse\c_tabl_lines_n_of_parts
348         {\c_tabl_lines_part\recurselevel
349          \dp\b_tabl_lines_current\c_tabl_lines_part\strutdepth
350          % noindent en endgraf needed else whitespace mess-up!
351          \whitespace % here not after verticalstrut
352          \ifzeropt\topskipgap\else
353            \verticalstrut
354            \nobreak
355            \kern-\struttotal
356            \kern-\parskip
357            \nobreak
358            \nointerlineskip % fix topskip
359          \fi
360          \noindent\strut
361          \hpack to \hsize{\box\b_tabl_lines_current\c_tabl_lines_part\hss}%
362          \endgraf
363          \ifnum\c_tabl_lines_part<\c_tabl_lines_n_of_parts\relax
364            \linetableparameter\c!inbetween
365          \fi}%
366       \ifnum\c_tabl_lines_rows<\c_tabl_lines_n_of_rows
367         \linetableparameter\c!inbetween
368       \else
369         % after, later
370       \fi
371       \c_tabl_lines_head_state\plusthree
372       \global\setbox\b_tabl_lines_current\zerocount\emptybox % here
373     \fi
374     % reset \c_tabl_lines_row will be an option, currently
375     % starts at zero after split
376     \global\c_tabl_lines_row\zerocount
377     \global\c_tabl_lines_line\zerocount
378     \global\c_tabl_lines_page\zerocount
379     \global\d_tabl_lines_width\zeropoint
380     \tabl_lines_set
381   \fi}
382
383\def\tabl_lines_start_part
384  {\global\c_tabl_lines_subcol\zerocount
385   \setbox\scratchbox\hbox\bgroup
386   \dousestyleparameter{\linetablerparameter\c!style}%
387   \dousecolorparameter{\linetablerparameter\c!color}%
388   \ignorespaces}
389
390\def\tabl_lines_stop_part
391  {\ifnum\c_tabl_lines_part>\zerocount
392     \unskip \unskip % remove last intercolumn skip (distance+fill)
393   \fi
394   \egroup
395   \ifconditional\c_tabl_lines_preroll
396   \orelse\ifcase\c_tabl_lines_part
397     % we're collecting the repeater
398   \orelse\ifdim\dimexpr\hsize-\wd\scratchbox\relax>\linetableparameter\c!stretch
399   \else
400     \setbox\scratchbox\hpack to \hsize{\unhbox\scratchbox}%
401   \fi}
402
403\def\tabl_lines_check_part
404  {\global\advanceby\d_tabl_lines_width\wd\b_tabl_lines_cell
405   \global\advanceby\c_tabl_lines_column\c_tabl_lines_step
406   \global\advanceby\c_tabl_lines_subcol\c_tabl_lines_step
407   \relax
408   %\message{\the\c_tabl_lines_column,\the\c_tabl_lines_subcol}\wait
409   % from now on the column counter is already incremented
410   \ifcase\c_tabl_lines_split_state
411     \ifconditional\c_tabl_lines_preroll
412     \else
413       \box\b_tabl_lines_cell
414       % the columncounter is one ahead !
415       \hskip\scratchskip
416     \fi
417     %%%
418     \donefalse
419     \ifcase\c_tabl_lines_repeat
420     \orelse\ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax % calculate ahead
421       \donetrue % collecting repeater
422     \fi
423     %%%%
424     \ifdone
425       % collecting repeater
426     \orelse\ifnum\c_tabl_lines_column>\csname\??linetablepart\the\c_tabl_lines_part\endcsname\relax
427       \donetrue
428     \fi
429     \ifdone
430       \tabl_lines_stop_part
431       \ifconditional\c_tabl_lines_preroll \else
432         \tabl_lines_save_part
433       \fi
434       \ifcase\c_tabl_lines_page \or
435         \global\c_tabl_lines_page \plustwo
436       \else
437         \global\c_tabl_lines_page \plusone
438       \fi
439       \global\advanceby\c_tabl_lines_part\plusone
440       \global\d_tabl_lines_width\wd\b_tabl_lines_current\zerocount
441       \tabl_lines_start_part
442     \fi
443   \else
444     \donefalse
445     \scratchconditiononefalse
446     \ifcase\c_tabl_lines_repeat\else
447       % calculate ahead
448       \ifnum\c_tabl_lines_repeat=\numexpr\c_tabl_lines_column-\plustwo\relax
449         \donetrue % collecting repeater
450       \fi
451     \fi
452     \ifdone
453       \scratchconditiononetrue
454       % collecting repeater
455     \orelse\ifdim\d_tabl_lines_width>\hsize
456       \donetrue
457     \else
458       \global\advanceby\d_tabl_lines_width\scratchskip
459       \ifdim\d_tabl_lines_width>\hsize % ?
460         \donetrue
461       \fi
462     \fi
463     \ifdone
464       \tabl_lines_stop_part
465       \tabl_lines_save_part
466       \ifcase\c_tabl_lines_page \or
467         \global\c_tabl_lines_page \plustwo
468       \else
469         \global\c_tabl_lines_page \plusone
470       \fi
471       \global\advanceby\c_tabl_lines_part\plusone
472       \ifnum\c_tabl_lines_part>\c_tabl_lines_n_of_parts
473         \global\c_tabl_lines_n_of_parts\c_tabl_lines_part
474         \tabl_lines_initialize_box\c_tabl_lines_part
475       \fi
476       \global\d_tabl_lines_width\wd\b_tabl_lines_cell
477       \tabl_lines_start_part
478       \ifscratchconditionone \orelse \ifcase\c_tabl_lines_repeat \else
479         % check for left/right page
480         \ifcase\c_tabl_lines_page\donetrue\or\donetrue\or\donefalse\fi
481         \ifdone
482           % insert repeater
483           \global\advanceby\d_tabl_lines_width\wd\b_tabl_lines_current\zerocount
484           \ifconditional\c_tabl_lines_preroll\kern\wd\else\unhcopy\fi\b_tabl_lines_current\zerocount
485         \fi
486       \fi
487     \fi
488     \ifconditional\c_tabl_lines_preroll \else
489       \box\b_tabl_lines_cell
490       % the columncounter is one ahead !
491      %\dorecurse\c_tabl_lines_step{\strut\hfil}%
492       \strut
493       \hskip\scratchskip
494     \fi
495   \fi}
496
497\permanent\protected\def\startlinetablerun % to do: quit when nested
498  {\bgroup
499   \dontcomplain
500   \c_tabl_lines_in_table\conditionaltrue
501   % autowidth
502   \ifcstok{\linetableparameter\c!maxwidth}\v!fit
503     \setuplinetable[\c!maxwidth=\zeropoint]%
504   \fi
505   \processaction
506     [\linetableparameter\c!stretch]
507     [ \v!no=>{\setuplinetable[\c!stretch=\maxdimen]},% no stretch
508      \v!yes=>{\setuplinetable[\c!stretch=\zeropoint]}]% max stretch
509   \c_tabl_lines_repeat\linetableparameter\c!nleft
510   \c_tabl_lines_split_state % =
511     \ifdim\linetableparameter\c!maxwidth>\zeropoint
512       \zerocount \else \plusone
513     \fi
514   % optional prevdepth correction
515   \ifconditional\c_tabl_lines_preroll
516     \global\c_tabl_lines_n_of_rows\zerocount
517   \else
518     \linetableparameter\c!before
519   \fi
520   \global\c_tabl_lines_rows\zerocount
521   \global\c_tabl_lines_n_of_columns\zerocount
522   \global\c_tabl_lines_n_of_parts\zerocount
523   \scratchcounter\zerocount
524   \def\docommand##1%
525     {\global\advanceby\c_tabl_lines_n_of_parts\plusone
526      \advanceby\scratchcounter##1%
527      \xdefcsname\??linetablepart\the\c_tabl_lines_n_of_parts\endcsname{\the\scratchcounter}}%
528   \processcommacommand[\linetableparameter\c!n]\docommand
529   \tabl_lines_initialize_boxes\c_tabl_lines_n_of_parts
530   \global\c_tabl_lines_part\ifcase\c_tabl_lines_repeat\plusone\else\zerocount\fi % repeater
531   \global\c_tabl_lines_step\plusone
532   \global\c_tabl_lines_line\zerocount
533   \global\c_tabl_lines_row \zerocount
534   \global\c_tabl_lines_column\zerocount
535   \global\c_tabl_lines_subcol\zerocount
536   \global\d_tabl_lines_width\zeropoint
537   \ifconditional\c_tabl_lines_preroll\orelse\ifdim\pagetotal>\zeropoint
538     \verticalstrut\kern-\struttotal
539   \fi
540   \tabl_lines_set
541   \tabl_lines_check_page
542   \enforced\let\BR\tabl_lines_BR
543   \enforced\let\ER\tabl_lines_ER
544   \enforced\let\BH\tabl_lines_BR
545   \enforced\let\EH\tabl_lines_ER
546   \enforced\let\BC\tabl_lines_BC
547   \enforced\let\EC\tabl_lines_EC
548   \enforced\let\NC\tabl_lines_NC
549   \enforced\let\NR\tabl_lines_NR
550   \tabl_lines_flush_head}
551
552\permanent\protected\def\stoplinetablerun
553  {\global\c_tabl_lines_line\maxcard
554   \c_tabl_lines_head_state\zerocount % blocked
555   \tabl_lines_flush_parts
556   \ifconditional\c_tabl_lines_preroll \else
557     \linetableparameter\c!after
558   \fi
559   \global\c_tabl_lines_part\zerocount
560   \global\c_tabl_lines_n_of_parts\zerocount
561   \egroup}
562
563\permanent\def\checklinecolumndimension#1#2#3%
564  {\global\edef#1\number#3\endcsname
565     {\expandafter\ifrelax\csname#1\number#3\endcsname
566        \the#2\b_tabl_lines_cell
567      \orelse\ifdim\csname#1\number#3\endcsname<#2\b_tabl_lines_cell
568        \the#2\b_tabl_lines_cell
569      \else
570        \csname#1\number#3\endcsname
571      \fi}}
572
573\def\tabl_lines_check_width {\checklinecolumndimension\??linetablewidth \wd\c_tabl_lines_column}
574\def\tabl_lines_check_height{\checklinecolumndimension\??linetableheight\ht\c_tabl_lines_row}
575\def\tabl_lines_check_depth {\checklinecolumndimension\??linetabledepth \dp\c_tabl_lines_row}
576
577\permanent\tolerant\protected\def\tabl_lines_BR[#1]% #1 not yet implemented
578  {\ifnum\c_tabl_lines_head_state=1\else
579     \global\advanceby\c_tabl_lines_row\plusone
580     \global\advanceby\c_tabl_lines_rows\plusone
581   \fi
582   \global\c_tabl_lines_column\plusone
583   \global\c_tabl_lines_subcol\plusone
584   \d_tabl_lines_height\zeropoint
585   \edef\p_height{\linetablerparameter\c!height}%
586   \ifempty\p_height
587     \c_tabl_lines_hmode \zerocount
588   \orelse\ifx\p_height\v!fit
589     \c_tabl_lines_hmode \plusone
590   \orelse\ifx\p_height\v!line
591     \c_tabl_lines_hmode \plustwo
592   \else
593     \d_tabl_lines_height\dimexpr\p_height-\strutdepth\relax
594   \fi
595   \tabl_lines_start_part}
596
597\permanent\protected\def\tabl_lines_BC
598  {\startlinetablecell}
599
600\permanent\protected\def\tabl_lines_EC
601  {\stoplinetablecell
602   \ifconditional\c_tabl_lines_preroll
603     \tabl_lines_check_width
604     \tabl_lines_check_height
605     \tabl_lines_check_depth
606   \fi
607   \tabl_lines_check_part}
608
609\permanent\protected\def\tabl_lines_ER
610  {% \stoplinetablecell
611   % no \box\b_tabl_lines_cell, i.e. dummy columnn, last \NC \NR
612   \tabl_lines_stop_part
613   \tabl_lines_save_part
614   \advanceby\c_tabl_lines_column \minusone
615   \ifnum\c_tabl_lines_column>\c_tabl_lines_n_of_columns
616     \global\c_tabl_lines_n_of_columns\c_tabl_lines_column
617   \fi
618   \tabl_lines_flush_parts
619   \global\c_tabl_lines_column\zerocount
620   \global\d_tabl_lines_width \zeropoint
621   \ifcase\c_tabl_lines_repeat
622     \global\c_tabl_lines_part\plusone
623   \else
624     \global\c_tabl_lines_part\zerocount % repeater
625   \fi
626   \tabl_lines_check_page
627   \tabl_lines_flush_head}
628
629\def\tabl_lines_check_page
630  {\global\c_tabl_lines_page\zerocount
631   \ifcase\c_tabl_lines_repeat\orelse\ifcase\c_tabl_lines_page
632     \ifcstok{\linetableparameter\c!repeat}\v!no
633       \global\c_tabl_lines_page\doifelseoddpage\plusone\plustwo
634     \fi
635   \fi}
636
637\def\tabl_lines_flush_head
638  {\ifcase\c_tabl_lines_head_state
639     % 0 blocked
640   \or
641     % 1 doing head
642   \or
643     % 2 head done
644   \or
645     % 3 trigger flush
646     \c_tabl_lines_head_state\plusone
647     \expand\t_tabl_lines_head\relax
648     \c_tabl_lines_head_state\plustwo
649   \fi}
650
651\permanent\protected\def\tabl_lines_NC % first time special treatment
652  {\relax
653   \ifcase\c_tabl_lines_column
654     \tabl_lines_BR
655   \else
656     \tabl_lines_EC
657   \fi
658   \tabl_lines_BC} % beware, this will result in BR BC EC BC NR
659
660\permanent\protected\def\tabl_lines_NR
661  {\stoplinetablecell % dummy
662   \tabl_lines_ER}
663
664\permanent\protected\def\startlinetable
665  {\startlinetablerun}
666
667\permanent\protected\def\stoplinetable
668  {\stoplinetablerun}
669
670\permanent\protected\def\startlinetableanalysis
671  {\bgroup
672   \c_tabl_lines_preroll\conditionaltrue
673   \settrialtypesetting
674   \startlinetablerun}
675
676\permanent\protected\def\stoplinetableanalysis
677  {\stoplinetablerun
678   \egroup
679   \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows
680   \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n}
681     {\edefcsname\??linetable r:##1x\c!height\endcsname{\csname\??linetableheight##1\endcsname}%
682      \edefcsname\??linetable r:##1x\c!depth \endcsname{\csname\??linetabledepth ##1\endcsname}%
683      \gletcsname\??linetableheight##1\endcsname\zeropoint
684      \gletcsname\??linetabledepth ##1\endcsname\zeropoint}
685   \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n}
686     {\edefcsname\??linetable c:##1\c!width\endcsname{\csname\??linetablewidth##1\endcsname}%
687      \gletcsname\??linetablewidth##1\endcsname\zeropoint}} % init next table
688
689% todo: store in box instead of macro
690
691\permanent\protected\lettonothing\stoplinetablehead
692
693\permanent\protected\def\startlinetablehead#1\stoplinetablehead
694  {\ifconditional\c_tabl_lines_in_table
695     \t_tabl_lines_head\emptytoks
696   \fi
697   \c_tabl_lines_head_state\plusthree % full
698   \t_tabl_lines_head{#1}%
699   \ifconditional\c_tabl_lines_in_table
700     \tabl_lines_flush_head
701   \fi}
702
703\permanent\protected\def\tabl_lines_BH
704  {\ifrelax\EC
705     % signal, grabbing lines
706   \else
707     \t_tabl_lines_head\emptytoks
708   \fi
709   \push_macro_BC
710   \push_macro_EC
711   \enforced\permanent\protected\def\BC##1\EC{\toksapp\t_tabl_lines_head{##1}}%
712   \enforced\permanent          \let\EC\relax} % signal
713
714\permanent\protected\def\tabl_lines_EH
715  {\pop_macro_EC
716   \pop_macro_BC
717   \expandafter\startlinetablehead\expand\t_tabl_lines_head\stoplinetablehead}
718
719\permanent\let\startlinetablebody\relax
720\permanent\let\stoplinetablebody \relax
721
722\permanent\tolerant\protected\def\processlinetablebuffer[#1]%
723  {\bgroup
724   \enforced\let\startlinetable\relax
725   \enforced\let\stoplinetable \relax
726   \startlinetableanalysis\getbuffer[#1]\stoplinetableanalysis
727   \startlinetablerun     \getbuffer[#1]\stoplinetablerun
728   \egroup}
729
730\permanent\tolerant\protected\def\processlinetablefile[#1]% maybe accept #1 as well as [#1]
731  {\bgroup
732   \enforced\let\startlinetable\relax
733   \enforced\let\stoplinetable \relax
734   \startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis
735   \startlinetablerun     \readfile{#1}\donothing\donothing\stoplinetablerun
736   \egroup}
737
738\popoverloadmode
739
740\setuplinetable
741  [\c!n=\maxcard,
742   \c!lines=\maxcard,
743   \c!nx=\plusone,
744   \c!nleft=\zerocount,
745   \c!repeat=\v!yes, % when nleft > 0, repeat on both pages
746   \c!before=,
747   \c!after=,
748   \c!inbetween=\page,
749   \c!distance=\zeropoint,
750   \c!stretch=\v!no,
751   \c!align=\c!right,
752   \c!leftoffset=.25\exheight,
753   \c!rightoffset=\linetableparameter\c!leftoffset,
754   \c!maxwidth=\zeropoint,
755   \c!width=5\emwidth,
756   \c!height=\v!fit, % \v!line = faster
757   \c!background=,
758   \c!backgroundcolor=,
759   \c!rulethickness=\linewidth]
760
761\protect
762
763\continueifinputfile{tabl-ltb.mkxl}
764
765\setuplinetable[n=6,m={2,2,2},lines=25] % m ?
766
767\setuplinetable[c][1]   [width=2cm,background=color,backgroundcolor=red]
768\setuplinetable[c][4]   [width=3cm,background=color,backgroundcolor=yellow]
769\setuplinetable[c][6]   [width=3cm,background=color,backgroundcolor=magenta]
770\setuplinetable[r][odd] [background=color,backgroundcolor=gray]
771\setuplinetable[r][even][background=color,backgroundcolor=green]
772
773\starttext
774
775\showframe \showstruts
776
777\setuppagenumbering[alternative=doublesided]\page[left]
778
779\startlinetable
780\NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR
781\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
782\stoplinetable
783
784\startlinetable
785\NC[style=slanted,color=green,background=color,backgroundcolor=darkred,nx=2,uitlijnen=middle] xxx
786                 \NC yy \NC ddddd \NC eeee \NC ff \NC \NR
787\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
788\stoplinetable
789
790% \startbuffer[lt]
791% \NC aaa\crlf aaa \NC bb \NC c  \NC ddddd \NC ee   \NC ff \NC \NR
792% \NC aaa\crlf aaa \NC b  \NC cc \NC ddd   \NC eeee \NC f  \NC \NR
793% \stopbuffer
794%
795% \processlinetablebuffer[lt]
796
797\stoptext
798