tabl-ltb.mkxl /size: 24 Kb    last modification: 2025-02-21 11:03
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       {\pagegoal-\pagetotal}%
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}%
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}%
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-\linetablecparameter\c!rightoffset}%
231     \fi
232     \ifcase\c_tabl_lines_mode
233       \dosetraggedcommand{\linetablecparameter\c!align}%
234       \vtop \ifdim\d_tabl_lines_height>\zeropoint to\d_tabl_lines_height \fi \bgroup
235         \hsize\scratchdimen
236         \raggedcommand
237     \else
238       \setalignmentswitch{\linetablecparameter\c!align}%
239       \hbox \ifcase\c_tabl_lines_mode \or to\scratchdimen \fi \bgroup
240         \ifcase\alignmentswitch\hss\or\hss\fi
241     \fi
242     \dousestyleparameter{\linetablecparameter\c!style}%
243     \dousecolorparameter{\linetablecparameter\c!color}%
244     \begstrut \ignorespaces}
245
246\permanent\protected\def\stoplinetablecell
247  {\unskip \endstrut
248   \ifcase\c_tabl_lines_mode
249     \endgraf
250   \else
251     \ifcase\alignmentswitch\else\hss\fi
252   \fi
253   \egroup
254   \hskip{\linetablecparameter\c!rightoffset}\relax
255   \egroup
256   \ifconditional\c_tabl_lines_preroll
257     \box\scratchbox
258   \else
259     \tabl_lines_wrap_up
260   \fi
261   \egroup}
262
263\def\tabl_lines_wrap_up
264  {\ifcstok{\linetablecparameter\c!background}\v!color
265     \ifconditional\linetableautoheight
266       \tabl_lines_wrap_up_auto
267     \else
268       \tabl_lines_wrap_up_line
269      \fi
270   \else
271     \box\scratchbox
272   \fi}
273
274% \startuseMPgraphic{one}
275%     path p, q ;
276%     numeric r ;
277%     r := RuleThickness ;
278%     p := unitsquare xysized(RuleWidth,RuleHeight+RuleDepth) ;
279%     q := p topenlarged -r bottomenlarged -r ;
280%     draw q ;
281%     setbounds currentpicture to p;
282% \stopuseMPgraphic
283%
284% \setuplinetable[r][odd] [type=mp,mp=one,backgroundcolor=gray,rulethickness=1pt]
285% \setuplinetable[r][even][type=mp,mp=one,backgroundcolor=green,rulethickness=1pt]
286%
287% \startlinetable
288%     \dorecurse{10}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
289% \stoplinetable
290
291\def\tabl_lines_wrap_up_auto
292  {\edef\p_height{\linetablerparameter{x\c!height}}%
293   \edef\p_depth {\linetablerparameter{x\c!depth }}%
294   \hpack
295     {\blackrule
296        [ \c!color=\linetablecparameter\c!backgroundcolor,
297           \c!type=\linetablecparameter\c!type,
298             \c!mp=\linetablecparameter\c!mp,
299  \c!rulethickness=\linetablecparameter\c!rulethickness,
300         \c!height=\ifchkdimension\p_height\or\lastchkdimension\else\ht\scratchbox\fi,
301          \c!depth=\ifchkdimension\p_depth \or\lastchkdimension\else\dp\scratchbox\fi,
302          \c!width=\wd\scratchbox]%
303      \hkern-\wd\scratchbox\box\scratchbox}}
304
305\def\tabl_lines_wrap_up_auto_r
306  {\hpack
307     {\blackrule
308        [ \c!color=\linetablerparameter\c!backgroundcolor,
309           \c!type=\linetablerparameter\c!type,
310             \c!mp=\linetablerparameter\c!mp,
311  \c!rulethickness=\linetablerparameter\c!rulethickness,
312         \c!height=\ht\scratchbox,
313          \c!depth=\dp\scratchbox,
314          \c!width=\wd\scratchbox]%
315      \hkern-\wd\scratchbox\box\scratchbox}}
316
317\def\tabl_lines_wrap_up_line
318  {\backgroundline[\linetablecparameter\c!backgroundcolor]{\box\scratchbox}}
319
320\def\tabl_lines_save_part
321  {\global\setbox\b_tabl_lines_current\c_tabl_lines_part
322   \ifcase\c_tabl_lines_part\relax
323     \box\scratchbox % just storing
324   \else
325     \vbox
326       {\ifvoid\b_tabl_lines_current\c_tabl_lines_part\else\unvbox\b_tabl_lines_current\c_tabl_lines_part\fi
327        \ifcstok{\linetablerparameter\c!background}\v!color
328          \backgroundline[\linetablerparameter\c!backgroundcolor]{\box\scratchbox}%
329        \orelse\ifempty{\linetablerparameter\c!type}%
330          \box\scratchbox
331        \else
332          \tabl_lines_wrap_up_auto_r
333        \fi
334        \endgraf
335        \linetablerparameter\c!after}%
336   \fi}
337
338\def\tabl_lines_flush_parts
339  {\global\advanceby\c_tabl_lines_line\plusone
340   \ifnum\c_tabl_lines_line<\c_tabl_lines_n_of_lines
341     % keep collecting
342   \else
343     \ifconditional\c_tabl_lines_preroll
344       % forget about them
345     \else
346       \dorecurse\c_tabl_lines_n_of_parts
347         {\c_tabl_lines_part\recurselevel
348          \dp\b_tabl_lines_current\c_tabl_lines_part\strutdepth
349          % noindent en endgraf needed else whitespace mess-up!
350          \whitespace % here not after verticalstrut
351          \ifzeropt\topskipgap\else
352            \verticalstrut
353            \nobreak
354            \kern-\struttotal
355            \kern-\parskip
356            \nobreak
357            \nointerlineskip % fix topskip
358          \fi
359          \noindent\strut
360          \hpack to \hsize{\box\b_tabl_lines_current\c_tabl_lines_part\hss}%
361          \endgraf
362          \ifnum\c_tabl_lines_part<\c_tabl_lines_n_of_parts\relax
363            \linetableparameter\c!inbetween
364          \fi}%
365       \ifnum\c_tabl_lines_rows<\c_tabl_lines_n_of_rows
366         \linetableparameter\c!inbetween
367       \else
368         % after, later
369       \fi
370       \c_tabl_lines_head_state\plusthree
371       \global\setbox\b_tabl_lines_current\zerocount\emptybox % here
372     \fi
373     % reset \c_tabl_lines_row will be an option, currently
374     % starts at zero after split
375     \global\c_tabl_lines_row\zerocount
376     \global\c_tabl_lines_line\zerocount
377     \global\c_tabl_lines_page\zerocount
378     \global\d_tabl_lines_width\zeropoint
379     \tabl_lines_set
380   \fi}
381
382\def\tabl_lines_start_part
383  {\global\c_tabl_lines_subcol\zerocount
384   \setbox\scratchbox\hbox\bgroup
385   \dousestyleparameter{\linetablerparameter\c!style}%
386   \dousecolorparameter{\linetablerparameter\c!color}%
387   \ignorespaces}
388
389\def\tabl_lines_stop_part
390  {\ifnum\c_tabl_lines_part>\zerocount
391     \unskip \unskip % remove last intercolumn skip (distance+fill)
392   \fi
393   \egroup
394   \ifconditional\c_tabl_lines_preroll
395   \orelse\ifcase\c_tabl_lines_part
396     % we're collecting the repeater
397   \orelse\ifdim{\hsize-\wd\scratchbox}>{\linetableparameter\c!stretch}%
398   \else
399     \setbox\scratchbox\hpack to \hsize{\unhbox\scratchbox}%
400   \fi}
401
402\def\tabl_lines_check_part
403  {\global\advanceby\d_tabl_lines_width\wd\b_tabl_lines_cell
404   \global\advanceby\c_tabl_lines_column\c_tabl_lines_step
405   \global\advanceby\c_tabl_lines_subcol\c_tabl_lines_step
406   \relax
407   %\message{\the\c_tabl_lines_column,\the\c_tabl_lines_subcol}\wait
408   % from now on the column counter is already incremented
409   \ifcase\c_tabl_lines_split_state
410     \ifconditional\c_tabl_lines_preroll
411     \else
412       \box\b_tabl_lines_cell
413       % the columncounter is one ahead !
414       \hskip\scratchskip
415     \fi
416     %%%
417     \donefalse
418     \ifcase\c_tabl_lines_repeat
419     \orelse\ifnum\c_tabl_lines_repeat={r\c_tabl_lines_column-\plustwo}% calculate ahead
420       \donetrue % collecting repeater
421     \fi
422     %%%%
423     \ifdone
424       % collecting repeater
425     \orelse\ifnum\c_tabl_lines_column>\csname\??linetablepart\the\c_tabl_lines_part\endcsname\relax
426       \donetrue
427     \fi
428     \ifdone
429       \tabl_lines_stop_part
430       \ifconditional\c_tabl_lines_preroll \else
431         \tabl_lines_save_part
432       \fi
433       \ifcase\c_tabl_lines_page \or
434         \global\c_tabl_lines_page \plustwo
435       \else
436         \global\c_tabl_lines_page \plusone
437       \fi
438       \global\advanceby\c_tabl_lines_part\plusone
439       \global\d_tabl_lines_width\wd\b_tabl_lines_current\zerocount
440       \tabl_lines_start_part
441     \fi
442   \else
443     \donefalse
444     \scratchconditiononefalse
445     \ifcase\c_tabl_lines_repeat\else
446       % calculate ahead
447       \ifnum\c_tabl_lines_repeat={\c_tabl_lines_column-\plustwo}%
448         \donetrue % collecting repeater
449       \fi
450     \fi
451     \ifdone
452       \scratchconditiononetrue
453       % collecting repeater
454     \orelse\ifdim\d_tabl_lines_width>\hsize
455       \donetrue
456     \else
457       \global\advanceby\d_tabl_lines_width\scratchskip
458       \ifdim\d_tabl_lines_width>\hsize % ?
459         \donetrue
460       \fi
461     \fi
462     \ifdone
463       \tabl_lines_stop_part
464       \tabl_lines_save_part
465       \ifcase\c_tabl_lines_page \or
466         \global\c_tabl_lines_page \plustwo
467       \else
468         \global\c_tabl_lines_page \plusone
469       \fi
470       \global\advanceby\c_tabl_lines_part\plusone
471       \ifnum\c_tabl_lines_part>\c_tabl_lines_n_of_parts
472         \global\c_tabl_lines_n_of_parts\c_tabl_lines_part
473         \tabl_lines_initialize_box\c_tabl_lines_part
474       \fi
475       \global\d_tabl_lines_width\wd\b_tabl_lines_cell
476       \tabl_lines_start_part
477       \ifscratchconditionone \orelse \ifcase\c_tabl_lines_repeat \else
478         % check for left/right page
479         \ifcase\c_tabl_lines_page\donetrue\or\donetrue\or\donefalse\fi
480         \ifdone
481           % insert repeater
482           \global\advanceby\d_tabl_lines_width\wd\b_tabl_lines_current\zerocount
483           \ifconditional\c_tabl_lines_preroll\kern\wd\else\unhcopy\fi\b_tabl_lines_current\zerocount
484         \fi
485       \fi
486     \fi
487     \ifconditional\c_tabl_lines_preroll \else
488       \box\b_tabl_lines_cell
489       % the columncounter is one ahead !
490      %\dorecurse\c_tabl_lines_step{\strut\hfil}%
491       \strut
492       \hskip\scratchskip
493     \fi
494   \fi}
495
496\permanent\protected\def\startlinetablerun % to do: quit when nested
497  {\bgroup
498   \dontcomplain
499   \c_tabl_lines_in_table\conditionaltrue
500   % autowidth
501   \ifcstok{\linetableparameter\c!maxwidth}\v!fit
502     \setuplinetable[\c!maxwidth=\zeropoint]%
503   \fi
504   \processaction
505     [\linetableparameter\c!stretch]
506     [ \v!no=>{\setuplinetable[\c!stretch=\maxdimen]},% no stretch
507      \v!yes=>{\setuplinetable[\c!stretch=\zeropoint]}]% max stretch
508   \c_tabl_lines_repeat{\linetableparameter\c!nleft}%
509   \c_tabl_lines_split_state % =
510     \ifdim{\linetableparameter\c!maxwidth}>\zeropoint
511       \zerocount \else \plusone
512     \fi
513   % optional prevdepth correction
514   \ifconditional\c_tabl_lines_preroll
515     \global\c_tabl_lines_n_of_rows\zerocount
516   \else
517     \linetableparameter\c!before
518   \fi
519   \global\c_tabl_lines_rows\zerocount
520   \global\c_tabl_lines_n_of_columns\zerocount
521   \global\c_tabl_lines_n_of_parts\zerocount
522   \scratchcounter\zerocount
523   \def\docommand##1%
524     {\global\advanceby\c_tabl_lines_n_of_parts\plusone
525      \advanceby\scratchcounter##1%
526      \xdefcsname\??linetablepart\the\c_tabl_lines_n_of_parts\endcsname{\the\scratchcounter}}%
527   \processcommacommand[\linetableparameter\c!n]\docommand
528   \tabl_lines_initialize_boxes\c_tabl_lines_n_of_parts
529   \global\c_tabl_lines_part\ifcase\c_tabl_lines_repeat\plusone\else\zerocount\fi % repeater
530   \global\c_tabl_lines_step\plusone
531   \global\c_tabl_lines_line\zerocount
532   \global\c_tabl_lines_row \zerocount
533   \global\c_tabl_lines_column\zerocount
534   \global\c_tabl_lines_subcol\zerocount
535   \global\d_tabl_lines_width\zeropoint
536   \ifconditional\c_tabl_lines_preroll\orelse\ifdim\pagetotal>\zeropoint
537     \verticalstrut\kern-\struttotal
538   \fi
539   \tabl_lines_set
540   \tabl_lines_check_page
541   \enforced\let\BR\tabl_lines_BR
542   \enforced\let\ER\tabl_lines_ER
543   \enforced\let\BH\tabl_lines_BR
544   \enforced\let\EH\tabl_lines_ER
545   \enforced\let\BC\tabl_lines_BC
546   \enforced\let\EC\tabl_lines_EC
547   \enforced\let\NC\tabl_lines_NC
548   \enforced\let\NR\tabl_lines_NR
549   \tabl_lines_flush_head}
550
551\permanent\protected\def\stoplinetablerun
552  {\global\c_tabl_lines_line\maxcard
553   \c_tabl_lines_head_state\zerocount % blocked
554   \tabl_lines_flush_parts
555   \ifconditional\c_tabl_lines_preroll \else
556     \linetableparameter\c!after
557   \fi
558   \global\c_tabl_lines_part\zerocount
559   \global\c_tabl_lines_n_of_parts\zerocount
560   \egroup}
561
562\permanent\def\checklinecolumndimension#1#2#3%
563  {\global\edefcsname#1\number#3\endcsname
564     {\expandafter\ifrelax\csname#1\number#3\endcsname
565        \the#2\b_tabl_lines_cell
566      \orelse\ifdim\csname#1\number#3\endcsname<#2\b_tabl_lines_cell
567        \the#2\b_tabl_lines_cell
568      \else
569        \csname#1\number#3\endcsname
570      \fi}}
571
572\def\tabl_lines_check_width {\checklinecolumndimension\??linetablewidth \wd\c_tabl_lines_column}
573\def\tabl_lines_check_height{\checklinecolumndimension\??linetableheight\ht\c_tabl_lines_row}
574\def\tabl_lines_check_depth {\checklinecolumndimension\??linetabledepth \dp\c_tabl_lines_row}
575
576\permanent\tolerant\protected\def\tabl_lines_BR[#1]% #1 not yet implemented
577  {\ifnum\c_tabl_lines_head_state=1\else
578     \global\advanceby\c_tabl_lines_row\plusone
579     \global\advanceby\c_tabl_lines_rows\plusone
580   \fi
581   \global\c_tabl_lines_column\plusone
582   \global\c_tabl_lines_subcol\plusone
583   \d_tabl_lines_height\zeropoint
584   \edef\p_height{\linetablerparameter\c!height}%
585   \ifempty\p_height
586     \c_tabl_lines_hmode \zerocount
587   \orelse\ifx\p_height\v!fit
588     \c_tabl_lines_hmode \plusone
589   \orelse\ifx\p_height\v!line
590     \c_tabl_lines_hmode \plustwo
591   \else
592     \d_tabl_lines_height{\p_height-\strutdepth}%
593   \fi
594   \tabl_lines_start_part}
595
596\permanent\protected\def\tabl_lines_BC
597  {\startlinetablecell}
598
599\permanent\protected\def\tabl_lines_EC
600  {\stoplinetablecell
601   \ifconditional\c_tabl_lines_preroll
602     \tabl_lines_check_width
603     \tabl_lines_check_height
604     \tabl_lines_check_depth
605   \fi
606   \tabl_lines_check_part}
607
608\permanent\protected\def\tabl_lines_ER
609  {% \stoplinetablecell
610   % no \box\b_tabl_lines_cell, i.e. dummy columnn, last \NC \NR
611   \tabl_lines_stop_part
612   \tabl_lines_save_part
613   \advanceby\c_tabl_lines_column \minusone
614   \ifnum\c_tabl_lines_column>\c_tabl_lines_n_of_columns
615     \global\c_tabl_lines_n_of_columns\c_tabl_lines_column
616   \fi
617   \tabl_lines_flush_parts
618   \global\c_tabl_lines_column\zerocount
619   \global\d_tabl_lines_width \zeropoint
620   \ifcase\c_tabl_lines_repeat
621     \global\c_tabl_lines_part\plusone
622   \else
623     \global\c_tabl_lines_part\zerocount % repeater
624   \fi
625   \tabl_lines_check_page
626   \tabl_lines_flush_head}
627
628\def\tabl_lines_check_page
629  {\global\c_tabl_lines_page\zerocount
630   \ifcase\c_tabl_lines_repeat\orelse\ifcase\c_tabl_lines_page
631     \ifcstok{\linetableparameter\c!repeat}\v!no
632       \global\c_tabl_lines_page\doifelseoddpage\plusone\plustwo
633     \fi
634   \fi}
635
636\def\tabl_lines_flush_head
637  {\ifcase\c_tabl_lines_head_state
638     % 0 blocked
639   \or
640     % 1 doing head
641   \or
642     % 2 head done
643   \or
644     % 3 trigger flush
645     \c_tabl_lines_head_state\plusone
646     \expand\t_tabl_lines_head\relax
647     \c_tabl_lines_head_state\plustwo
648   \fi}
649
650\permanent\protected\def\tabl_lines_NC % first time special treatment
651  {\relax
652   \ifcase\c_tabl_lines_column
653     \tabl_lines_BR
654   \else
655     \tabl_lines_EC
656   \fi
657   \tabl_lines_BC} % beware, this will result in BR BC EC BC NR
658
659\permanent\protected\def\tabl_lines_NR
660  {\stoplinetablecell % dummy
661   \tabl_lines_ER}
662
663\permanent\protected\def\startlinetable
664  {\startlinetablerun}
665
666\permanent\protected\def\stoplinetable
667  {\stoplinetablerun}
668
669\permanent\protected\def\startlinetableanalysis
670  {\bgroup
671   \c_tabl_lines_preroll\conditionaltrue
672   \settrialtypesetting
673   \startlinetablerun}
674
675\permanent\protected\def\stoplinetableanalysis
676  {\stoplinetablerun
677   \egroup
678   \global\c_tabl_lines_n_of_rows\c_tabl_lines_rows
679   \dorecurse\c_tabl_lines_n_of_rows % global, from last run {\linetableparameter\c!n}
680     {\edefcsname\??linetable r:##1x\c!height\endcsname{\csname\??linetableheight##1\endcsname}%
681      \edefcsname\??linetable r:##1x\c!depth \endcsname{\csname\??linetabledepth ##1\endcsname}%
682      \gletcsname\??linetableheight##1\endcsname\zeropoint
683      \gletcsname\??linetabledepth ##1\endcsname\zeropoint}
684   \dorecurse\c_tabl_lines_n_of_columns % global, from last run {\linetableparameter\c!n}
685     {\edefcsname\??linetable c:##1\c!width\endcsname{\csname\??linetablewidth##1\endcsname}%
686      \gletcsname\??linetablewidth##1\endcsname\zeropoint}} % init next table
687
688% todo: store in box instead of macro
689
690\permanent\protected\lettonothing\stoplinetablehead
691
692\permanent\protected\def\startlinetablehead#1\stoplinetablehead
693  {\ifconditional\c_tabl_lines_in_table
694     \t_tabl_lines_head\emptytoks
695   \fi
696   \c_tabl_lines_head_state\plusthree % full
697   \t_tabl_lines_head{#1}%
698   \ifconditional\c_tabl_lines_in_table
699     \tabl_lines_flush_head
700   \fi}
701
702\permanent\protected\def\tabl_lines_BH
703  {\ifrelax\EC
704     % signal, grabbing lines
705   \else
706     \t_tabl_lines_head\emptytoks
707   \fi
708   \push_macro_BC
709   \push_macro_EC
710   \enforced\permanent\protected\def\BC##1\EC{\toksapp\t_tabl_lines_head{##1}}%
711   \enforced\permanent          \let\EC\relax} % signal
712
713\permanent\protected\def\tabl_lines_EH
714  {\pop_macro_EC
715   \pop_macro_BC
716   \expandafter\startlinetablehead\expand\t_tabl_lines_head\stoplinetablehead}
717
718\permanent\let\startlinetablebody\relax
719\permanent\let\stoplinetablebody \relax
720
721\permanent\tolerant\protected\def\processlinetablebuffer[#1]%
722  {\bgroup
723   \enforced\let\startlinetable\relax
724   \enforced\let\stoplinetable \relax
725   \startlinetableanalysis\getbuffer[#1]\stoplinetableanalysis
726   \startlinetablerun     \getbuffer[#1]\stoplinetablerun
727   \egroup}
728
729\permanent\tolerant\protected\def\processlinetablefile[#1]% maybe accept #1 as well as [#1]
730  {\bgroup
731   \enforced\let\startlinetable\relax
732   \enforced\let\stoplinetable \relax
733   \startlinetableanalysis\readfile{#1}\donothing\donothing\stoplinetableanalysis
734   \startlinetablerun     \readfile{#1}\donothing\donothing\stoplinetablerun
735   \egroup}
736
737\popoverloadmode
738
739\setuplinetable
740  [\c!n=\maxcard,
741   \c!lines=\maxcard,
742   \c!nx=\plusone,
743   \c!nleft=\zerocount,
744   \c!repeat=\v!yes, % when nleft > 0, repeat on both pages
745   \c!before=,
746   \c!after=,
747   \c!inbetween=\page,
748   \c!distance=\zeropoint,
749   \c!stretch=\v!no,
750   \c!align=\c!right,
751   \c!leftoffset=.25\exheight,
752   \c!rightoffset=\linetableparameter\c!leftoffset,
753   \c!maxwidth=\zeropoint,
754   \c!width=5\emwidth,
755   \c!height=\v!fit, % \v!line = faster
756   \c!background=,
757   \c!backgroundcolor=,
758   \c!rulethickness=\linewidth]
759
760\protect
761
762\continueifinputfile{tabl-ltb.mkxl}
763
764\setuplinetable[n=6,m={2,2,2},lines=25] % m ?
765
766\setuplinetable[c][1]   [width=2cm,background=color,backgroundcolor=red]
767\setuplinetable[c][4]   [width=3cm,background=color,backgroundcolor=yellow]
768\setuplinetable[c][6]   [width=3cm,background=color,backgroundcolor=magenta]
769\setuplinetable[r][odd] [background=color,backgroundcolor=gray]
770\setuplinetable[r][even][background=color,backgroundcolor=green]
771
772\starttext
773
774\showframe \showstruts
775
776\setuppagenumbering[alternative=doublesided]\page[left]
777
778\startlinetable
779\NC aaa\crlf aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR
780\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
781\stoplinetable
782
783\startlinetable
784\NC[style=slanted,color=green,background=color,backgroundcolor=darkred,nx=2,uitlijnen=middle] xxx
785                 \NC yy \NC ddddd \NC eeee \NC ff \NC \NR
786\dorecurse{100}{\NC aaa \NC bb \NC c \NC ddddd \NC eeee \NC ff \NC \NR}
787\stoplinetable
788
789% \startbuffer[lt]
790% \NC aaa\crlf aaa \NC bb \NC c  \NC ddddd \NC ee   \NC ff \NC \NR
791% \NC aaa\crlf aaa \NC b  \NC cc \NC ddd   \NC eeee \NC f  \NC \NR
792% \stopbuffer
793%
794% \processlinetablebuffer[lt]
795
796\stoptext
797