tabl-xtb.mkvi /size: 32 Kb    last modification: 2021-10-28 13:50
1
% macros=mkvi
2 3
%D \module
4
%D [ file=tabl-xtb,
5
%D version=2011.10.26,
6
%D title=\CONTEXT\ Table Macros,
7
%D subtitle=Xtreme,
8
%D author=Hans Hagen,
9
%D date=\currentdate,
10
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
11
%C
12
%C This module is part of the \CONTEXT\ macro||package and is
13
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
14
%C details.
15 16
\writestatus
{
loading
}
{
ConTeXt
Table
Macros
/
Xtreme
}
17 18
\registerctxluafile
{
tabl
-
xtb
}
{
}
19 20
% todo:
21
%
22
% - yes or no: foregroundstyle/color <- style/color
23
% - template alignment
24
% - maybe split horizontal (a la linetables)
25
% - before/after and wrapping (linecorrection)
26
% - maybe also some before/after commands
27
% - maybe correction when non float usage
28
% - tagging needs to be checked
29
% - maybe only tag the box
30
% - scale to fit
31
%
32
% - buffers permit verbatim but are not always handy
33 34
%D This module started as an afternoon experiment and surprisingly could be
35
%D mostly finished the same evening. Of course it builds upon existing
36
%D functionality. The main reason for writing it is that we occasionally
37
%D run into pretty large tables that take tens of pages and need to be split
38
%D into floats. Speed is one issue there, avoiding to use vsplit is another.
39
%D
40
%D \starttyping
41
%D \definextable [tag] | [tag][parent]
42
%D \setupxtable [settings] | [tag][settings]
43
%D
44
%D \startxtable[tag|settings]
45
%D \startxtablehead|\startxtablenext|\startxtablebody|\startxtablefoot
46
%D \startxrowgroup[tag|settings]
47
%D \startxrow[settings]
48
%D \startxcellgroup[tag|settings]
49
%D \startxcell[settings] ... \stopxcell
50
%D \stopxcellgroup
51
%D \stopxrow
52
%D \startxrowgroup
53
%D \stopxtablehead|\stopxtablenext|\stopxtablebody|\stopxtablefoot
54
%D \stopxtable
55
%D \stoptyping
56
%D
57
%D See xtables-001.tex etc for some examples.
58 59
% We can avoid some checking by using the fastoptionalcheckcs helpers
60
% instead of dosingleempty but the speed gain is neglectable.
61 62
\unprotect
63 64
% option=stretch : equal distribution
65
% option={stretch,width} : proportional distribution
66
% option={max} : prefer max over forced width/height
67
%
68
% cells: option=fixed : nils autostretch (not yet complete)
69 70
% \setbox\scratchbox\hbox attr \taggedattribute \c_attr_tagged {...}
71
%
72
% \let\tsplitbeforeresult\donothing
73
% \let\tsplitafterresult \donothing
74
% \let\tsplitinbetween \donothing
75
% \let\tsplitbefore \donothing
76
% \let\tsplitafter \donothing
77
% \let\postprocesstsplit \donothing
78 79
\let
\dotagxtablecell
\relax
% names will change
80
\let
\dotagxtablesignal
\relax
% names will change
81 82
\appendtoks
83
\def
\dotagxtablecell
84
{
\clf_settagtablecell
85
\numexpr
\tablecellrows
\relax
86
\numexpr
\tablecellcolumns
\relax
87
\numexpr
\raggedstatus
\relax
}
%
88
\def
\dotagxtablesignal
89
{
\signalcharacter
}
% not used
90
\to
\everyenableelements
91 92
\newdimen
\d_tabl_x_width
93
\newdimen
\d_tabl_x_height
94
\newdimen
\d_tabl_x_depth
% not used
95
\newdimen
\d_tabl_x_distance
96
\newcount
\c_tabl_x_nx
97
\newcount
\c_tabl_x_ny
98
\newcount
\c_tabl_x_mode
99
\newbox
\b_tabl_x
100
\newcount
\c_tabl_x_state
% 0=empty 1=content 3=splitleft
101
\newdimen
\d_tabl_x_final_width
102
\newcount
\c_tabl_x_nesting
103
\newcount
\c_tabl_x_skip_mode
% 1 = skip
104
\newdimen
\d_tabl_x_textwidth
105
\newcount
\c_tabl_x_swapped
106
\newcount
\c_tabl_x_swapped_max
107 108
\let
\m_tabl_x_swapped_settings
\empty
109 110
\let
\currentxtablerow
\clf_x_table_r
111
\let
\currentxtablecolumn
\clf_x_table_c
112 113
% \setupxtable[one][parent][a=b,c=d]
114
% \setupxtable[one] [a=b,c=d]
115
% \setupxtable [a=b,c=d]
116 117
\installcorenamespace
{
xtable
}
118
\installcorenamespace
{
xtablecheck
}
119
\installcorenamespace
{
xtableswap
}
120 121
\installframedautocommandhandler
\??xtable
{
xtable
}
\??xtable
122 123
\appendtoks
124
\checkxtableparent
% so we can deal with undefined settings, not that it's efficient
125
\to
\everysetupxtable
126 127
\setupxtable
[
%
128
\c!nr
=
\plusone
,
129
\c!nc
=
\plusone
,
130
\c!nx
=
\plusone
,
% slow
131
\c!ny
=
\plusone
,
% slow
132
\c!align
=
\v!table
,
% {\v!flushleft,\v!broad,\v!high}, % just as \bTABLE .. \eTABLE
133
\c!frameoffset
=
.
5
\linewidth
,
134
\c!backgroundoffset
=
\v!frame
,
135
% \c!framecolor=\s!black,
136
% \c!foregroundstyle=\xtableparameter\c!style, % not clean, better capture elsewhere
137
% \c!foregroundcolor=\xtableparameter\c!color, % not clean, better capture elsewhere
138
% \c!bodyfont=,
139
\c!width
=
\v!fit
,
140
\c!height
=
\v!fit
,
141
\c!maxwidth
=
8
\emwidth
,
142
\c!autowidth
=
\v!yes
,
% controls framed
143
\c!rulethickness
=
\linewidth
,
144
\c!strut
=
\v!yes
,
145
\c!autostrut
=
\v!no
,
146
\c!split
=
\v!auto
,
% a number will take that many lines
147
\c!splitoffset
=
\zeropoint
,
% extra space taken
148
\c!aligncharacter
=
\v!no
,
149
\c!alignmentcharacter
=
{
,
}
,
150
\c!alignmentleftsample
=
,
151
\c!alignmentrightsample
=
,
152
\c!alignmentleftwidth
=
\zeropoint
,
153
\c!alignmentrightwidth
=
\zeropoint
,
154
% \c!option=, % \v!stretch {\v!stretch,\v!width}
155
% \c!footer=,
156
% \c!header=,
157
\c!spaceinbetween
=
,
158
\c!textwidth
=
\v!local
,
% was \hsize,
159
\c!textheight
=
\vsize
,
% used for vertical spread
160
\c!distance
=
\zeropoint
,
% individual column
161
\c!columndistance
=
\zeropoint
,
% each column (whole table)
162
\c!leftmargindistance
=
\zeropoint
,
% whole table
163
\c!rightmargindistance
=
\zeropoint
,
% whole table
164
]
165 166
\unexpanded
\def
\startxtable
167
{
\dosingleempty
\tabl_x_start_table
}
168 169
\let
\stopxtable
\relax
170 171
\def
\tabl_x_default_buffer
{
x
_
table
_
\number
\c_tabl_x_nesting
}
172
\let
\tabl_x_current_buffer
\empty
173 174
\unexpanded
\def
\tabl_x_start_table
[
#
settings
]
% maybe two arguments: [tag][settings] | [tag] | [settings]
175
{
\bgroup
176
\tabl_x_prepare
{
#
settings
}
%
177
\edef
\tabl_x_current_buffer
{
\tabl_x_default_buffer
}
%
178
\buff_pickup
{
\tabl_x_current_buffer
}
{
startxtable
}
{
stopxtable
}
\relax
\tabl_x_process
\zerocount
}
179 180
\unexpanded
\def
\processxtablebuffer
181
{
\dosingleempty
\tabl_x_process_buffer_directly
}
182 183
% These direct buffers can be somewhat faster but it's probably neglectable.
184
% Anyway, no nesting is supported as we then need to catch (e.g.) rows and
185
% keep track of nesting and have a more complex redefinition of nested
186
% instanced \unknown\ it's not worth the trouble. Only use them when you
187
% really need them and use the embeddedxtable command when nesting them.
188
% Implementing nesting would be slower than not using direct buffers.
189 190
\unexpanded
\def
\tabl_x_process_buffer_directly
[
#
name
]
%
191
{
\bgroup
192
\let
\tabl_x_start_table
\tabl_x_process_buffer
193
\edef
\tabl_x_current_buffer
{
#
name
}
%
194
\tabl_x_get_buffer
% settings
195
\tabl_x_process
}
196 197
\unexpanded
\def
\tabl_x_start_ignore
[
#
settings
]
%
198
{
}
199 200
\unexpanded
\def
\tabl_x_process_buffer
[
#
settings
]
%
201
{
\tabl_x_prepare
{
#
settings
}
%
202
\let
\tabl_x_start_table
\tabl_x_start_ignore
203
\gobbleuntil
\stopxtable
}
% nested xtables are not supported,
204 205
%D A bonus: you have to use the following construct inside a macro or
206
%D direct buffer.
207 208
\unexpanded
\def
\startembeddedxtable
209
{
\dosingleempty
\tabl_x_embedded_start
}
210 211
\unexpanded
\def
\tabl_x_embedded_start
[
#
settings
]
#
content
\stopembeddedxtable
212
{
\tabl_x_prepare
{
#
settings
}
%
213
\clf_assignbuffer
{
embedded
_
x
_
table
}
{
\detokenize
{
#
content
}
}
\catcodetable
\relax
214
\bgroup
215
\let
\tabl_x_start_table
\tabl_x_process_buffer
216
\edef
\tabl_x_current_buffer
{
embedded
_
x
_
table
}
%
217
\tabl_x_process
}
218 219
\let
\stopembeddedxtable
\relax
220 221
%D We can also define xtables.
222 223
\appendtoks
224
\setuevalue
{
\e!start
\currentxtable
}
{
\tabl_x_start_named
{
\currentxtable
}
}
%
225
\setuevalue
{
\e!stop
\currentxtable
}
{
\tabl_x_stop_named
}
%
226
\to
\everydefinextable
227 228
\unexpanded
\def
\tabl_x_start_named
#
tag
%
229
{
\bgroup
230
\edef
\currentxtable
{
#
tag
}
%
231
\dosingleempty
\tabl_x_start_named_indeed
}
232 233
\unexpanded
\def
\tabl_x_start_named_indeed
[
#
settings
]
%
234
{
\advance
\c_tabl_x_nesting
\plusone
235
\dostarttaggedchained
\t!table
\empty
\??xtable
236
\iffirstargument
237
\setupcurrentxtable
[
#
settings
]
%
238
\fi
239
\tabl_x_check_textwidth
240
%\forgetall % else whitespace mess
241
\edef
\tabl_x_current_buffer
{
\tabl_x_default_buffer
}
%
242
\normalexpanded
{
\buff_pickup
{
\tabl_x_current_buffer
}
{
\e!start
\currentxtable
}
{
\e!stop
\currentxtable
}
\relax
\tabl_x_process
\zerocount
}
}
243 244
\unexpanded
\def
\tabl_x_stop_named
245
{
}
246 247
%D Now we come to processing:
248 249
\unexpanded
\def
\tabl_x_check_textwidth
250
{
\edef
\p_textwidth
{
\xtableparameter
\c!textwidth
}
%
251
\ifx
\p_textwidth
\v!local
252
\d_tabl_x_textwidth
\availablehsize
253
\else
254
\d_tabl_x_textwidth
\p_textwidth
255
\fi
}
256 257
\newtoks
\everypreparextable
258 259
\unexpanded
\def
\tabl_x_prepare
#
settings
% assumes \iffirstargument to be set
260
{
\advance
\c_tabl_x_nesting
\plusone
261
\dostarttaggedchained
\t!table
\empty
\??xtable
262
\iffirstargument
263
\tabl_x_set_checked
{
#
settings
}
%
264
\fi
265
\tabl_x_check_textwidth
266
\the
\everypreparextable
267
}
% else whitespace mess
268 269
\def
\tabl_x_get_buffer
270
{
\clf_gettexbuffer
{
\tabl_x_current_buffer
}
}
271 272
\let
\tabl_x_start_row_yes
\relax
273
\let
\tabl_x_start_row_nop
\relax
274
\let
\tabl_x_stop_row
\relax
275
\let
\tabl_x_start_cell_yes
\relax
276
\let
\tabl_x_start_cell_nop
\relax
277
\let
\tabl_x_stop_cell
\relax
278 279
\newtoks
\t_table_x_cleanup
280 281
\unexpanded
\def
\tabl_x_process
282
{
\begingroup
% *
283
\forgetall
% moved here
284
\dontcomplain
% for the moment here till we figure out where we get the overflow
285
\usebodyfontparameter
\xtableparameter
286
\setbox
\scratchbox
\vbox
287
{
\doifsomething
{
\xtableparameter
\c!spaceinbetween
}
{
\blank
[
\xtableparameter
\c!spaceinbetween
]
}
}
%
288
\clf_x_table_create
289
option
{
\xtableparameter
\c!option
}
%
290
textwidth
\d_tabl_x_textwidth
291
textheight
\dimexpr
\xtableparameter
\c!textheight
\relax
292
maxwidth
\dimexpr
\xtableparameter
\c!maxwidth
\relax
293
lineheight
\openlineheight
294
columndistance
\dimexpr
\xtableparameter
\c!columndistance
\relax
295
leftmargindistance
\dimexpr
\xtableparameter
\c!leftmargindistance
\relax
296
rightmargindistance
\dimexpr
\xtableparameter
\c!rightmargindistance
\relax
297
rowdistance
\ht
\scratchbox
298
header
{
\xtableparameter
\c!header
}
%
299
footer
{
\xtableparameter
\c!footer
}
%
300
\relax
301
%
302
\letxtableparameter
\c!option
\empty
303
% not so nice but needed as we use this in the setup
304
\linewidth
\xtableparameter
\c!rulethickness
\relax
305
% so we freeze it
306
\c_tabl_x_swapped_max
\zerocount
307
\begingroup
308
\let
\tabl_x_start_row_yes
\tabl_x_start_row_reflow_width_yes
309
\let
\tabl_x_start_row_nop
\tabl_x_start_row_reflow_width_nop
310
\let
\tabl_x_stop_row
\tabl_x_stop_row_reflow_width
311
\let
\tabl_x_start_cell_yes
\tabl_x_start_cell_reflow_width_yes
312
\let
\tabl_x_start_cell_nop
\tabl_x_start_cell_reflow_width_nop
313
\let
\tabl_x_stop_cell
\tabl_x_stop_cell_reflow_width
314
\settrialtypesetting
315
\tabl_x_get_buffer
316
\ifcase
\c_tabl_x_swapped_max
317
\else
318
\tabl_x_flush_swapped
319
\fi
320
\clf_x_table_reflow_width
321
\endgroup
322
\begingroup
323
\let
\tabl_x_start_row_yes
\tabl_x_start_row_reflow_height_yes
324
\let
\tabl_x_start_row_nop
\tabl_x_start_row_reflow_height_nop
325
\let
\tabl_x_stop_row
\tabl_x_stop_row_reflow_height
326
\let
\tabl_x_start_cell_yes
\tabl_x_start_cell_reflow_height_yes
327
\let
\tabl_x_start_cell_nop
\tabl_x_start_cell_reflow_height_nop
328
\let
\tabl_x_stop_cell
\tabl_x_stop_cell_reflow_height
329
\settrialtypesetting
330
\ifcase
\c_tabl_x_swapped_max
331
\tabl_x_get_buffer
332
\else
333
\tabl_x_flush_swapped
334
\fi
335
\clf_x_table_reflow_height
336
\endgroup
337
\begingroup
338
\let
\tabl_x_start_row_yes
\tabl_x_start_row_construct_yes
339
\let
\tabl_x_start_row_nop
\tabl_x_start_row_construct_nop
340
\let
\tabl_x_stop_row
\tabl_x_stop_row_construct
341
\let
\tabl_x_start_cell_yes
\tabl_x_start_cell_construct_yes
342
\let
\tabl_x_start_cell_nop
\tabl_x_start_cell_construct_nop
343
\let
\tabl_x_stop_cell
\tabl_x_stop_cell_construct
344
\ifcase
\c_tabl_x_swapped_max
345
\tabl_x_get_buffer
346
\else
347
\tabl_x_flush_swapped
348
\fi
349
\clf_x_table_construct
350
\endgroup
351
\endgroup
% *
352
\ifinsidesplitfloat
353
\tabl_x_flush_float_split
354
\else
\ifinsidefloat
355
\tabl_x_flush_float_normal
356
\else
357
\tabl_x_flush_text_checked
358
\fi
\fi
359
\clf_x_table_cleanup
360
\dostoptagged
361
\resetbuffer
[
\tabl_x_current_buffer
]
%
362
\resetcharacteralign
363
\the
\t_table_x_cleanup
364
\egroup
}
365 366
% text flow split modes
367 368
\installcorenamespace
{
xtableflushsplit
}
369 370
\unexpanded
\def
\tabl_x_flush_text_checked
371
{
\expandnamespaceparameter
\??xtableflushsplit
\xtableparameter
\c!split
\v!no
}
372 373
% in text flow: headers and footers only once
374 375
\setvalue
{
\??xtableflushsplit
\v!yes
}
%
376
{
\clf_x_table_flush
377
method
{
\v!split
}
%
378
\relax
}
379 380
% in text flow: headers and footers only once
381 382
\setvalue
{
\??xtableflushsplit
\v!no
}
%
383
{
% \noindent % gives extra line after table
384
% \noindentation % messes up the next indentation
385
% \dontleavehmode % no leftskip
386
\kern
\zeropoint
% yet another guess
387
\ignorespaces
388
\clf_x_table_flush
389
method
{
\v!normal
}
%
390
\relax
391
\removeunwantedspaces
}
392 393
% in text flow: headers and footers get repeated
394 395
% \setvalue{\??xtableflushsplit\v!repeat}%
396
% {\doloop
397
% {\clf_x_table_flush
398
% method {\v!split}%
399
% height \ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi
400
% \relax
401
% \ifcase\c_tabl_x_state
402
% \exitloop
403
% \else
404
% \page
405
% \fi}}
406 407
\defcsname
\??xtableflushsplit
\v!repeat
\endcsname
408
{
\doloop
409
{
\testpage
[
5
]
% for now hard coded, just as the \lineheight below, see mail end of april 2021
410
\clf_x_table_flush
411
method
{
\v!split
}
%
412
height
\ifdim
\pagegoal
=
\maxdimen
\textheight
\else
\dimexpr
\pagegoal
-
\pagetotal
-
\lineheight
\relax
\fi
413
\relax
414
\ifcase
\c_tabl_x_state
415
\exitloop
416
\else
417
\page
418
\fi
}
}
419 420
% \setvalue{\??xtableflushsplit\v!setups}%
421
% {\directsetup{xtable:split:user}}
422
%
423
% \startsetups[xtable:split:user]
424
% \doloop {
425
% \xtablesplitflush % uses \xtablesplitvsize (a macro)
426
% \ifcase\xtablesplitstate
427
% \exitloop
428
% \else
429
% \page
430
% \fi
431
% }
432
% \stopsetups
433
%
434
% \unexpanded\def\xtablesplitflush
435
% {\clf_x_table_flush
436
% method {\v!split}%
437
% height \dimexpr\xtablesplitvsize\relax
438
% \relax}
439
%
440
% \def\xtablesplitvsize
441
% {\ifdim\pagegoal=\maxdimen\textheight\else\pagegoal\fi}
442
%
443
% \let\xtablesplitstate\c_tabl_x_state
444 445
\let
\extratxtablesplitheight
\zeropoint
% might disappear so don't depend on it
446 447
\unexpanded
\def
\tabl_x_flush_float_normal
448
{
\clf_x_table_flush
449
method
{
\v!normal
}
%
450
\relax
}
451 452
\unexpanded
\def
\tabl_x_flush_float_split
453
{
\resetdirecttsplit
454
\edef
\extrasplitfloatlines
{
\xtableparameter
\c!split
}
%
455
\edef
\tsplitminimumfreespace
{
\the
\dimexpr
\extratxtablesplitheight
+
\xtableparameter
\c!splitoffset
\relax
}
%
456
% \edef\tsplitminimumfreelines{2}% not needed here as we're precise enough
457
\let
\tsplitdirectsplitter
\tabl_x_split_splitter
458
\let
\tsplitdirectwidth
\d_tabl_x_final_width
459
\handledirecttsplit
}
460 461
\unexpanded
\def
\tabl_x_split_splitter
#
height
%
462
{
\setbox
\tsplitresult
\vbox
463
{
\clf_x_table_flush
464
method
{
\v!split
}
%
465
height
\dimexpr
#
height
\relax
466
\relax
}
%
467
\ifcase
\c_tabl_x_state
468
\global
\setfalse
\somenextsplitofffloat
469
\else
470
\global
\settrue
\somenextsplitofffloat
471
\fi
}
472 473
\unexpanded
\def
\startxrow
474
{
\begingroup
475
\doifelsenextoptionalcs
\tabl_x_start_row_yes
\tabl_x_start_row_nop
}
476 477
\unexpanded
\def
\tabl_x_start_row_reflow_width_yes
[
#
settings
]
%
478
{
\setupcurrentxtable
[
#
settings
]
%
479
\clf_x_table_next_row
}
480 481
\unexpanded
\def
\tabl_x_start_row_reflow_width_nop
482
{
\clf_x_table_next_row
}
483 484
\unexpanded
\def
\tabl_x_stop_row_reflow_width
485
{
}
486 487
\let
\tabl_x_start_row_reflow_height_yes
\tabl_x_start_row_reflow_width_yes
488
\let
\tabl_x_start_row_reflow_height_nop
\tabl_x_start_row_reflow_width_nop
489
\let
\tabl_x_stop_row_reflow_height
\tabl_x_stop_row_reflow_width
490 491
\unexpanded
\def
\tabl_x_start_row_construct_yes
[
#
settings
]
%
492
{
\setupcurrentxtable
[
#
settings
]
%
493
\dostarttagged
\t!tablerow
\empty
494
\clf_x_table_next_row_option
{
\xtableparameter
\c!samepage
}
}
495 496
\unexpanded
\def
\tabl_x_start_row_construct_nop
497
{
\dostarttagged
\t!tablerow
\empty
498
\clf_x_table_next_row
}
499 500
\unexpanded
\def
\tabl_x_stop_row_construct
501
{
\clf_x_table_finish_row
502
\dostoptagged
}
503 504
\unexpanded
\def
\stopxrow
505
{
\tabl_x_stop_row
506
\endgroup
}
507 508
\unexpanded
\def
\startxcell
509
{
\doifelsenextoptionalcs
\tabl_x_start_cell_yes
\tabl_x_start_cell_nop
}
510 511
\unexpanded
\def
\stopxcell
512
{
\tabl_x_stop_cell
}
513 514
% \unexpanded\def\dummyxcell
515
% {\tabl_x_start_cell_nop
516
% \tabl_x_stop_cell}
517 518
\unexpanded
\def
\dummyxcell
519
{
\begingroup
520
\let
\inheritedxtableframed
\relax
521
\tabl_x_start_cell_nop
522
\tabl_x_stop_cell
523
\endgroup
}
524 525
% \unexpanded\def\tabl_x_begin_of_cell
526
% {%\inhibitblank % already in framed
527
% \everypar{\delayedbegstrut}}
528 529
\def
\tabl_x_setup_character_align
530
{
\edef
\p_left
{
\directxtableparameter
\c!alignmentleftsample
}
%
531
\edef
\p_right
{
\directxtableparameter
\c!alignmentrightsample
}
%
532
\ifx
\p_left
\empty
533
\scratchdimenone
\dimexpr
\directxtableparameter
\c!alignmentleftwidth
\relax
534
\else
535
\setbox
\scratchbox
\hbox
{
\p_left
}
%
536
\scratchdimenone
\wd
\scratchbox
537
\fi
538
\ifx
\p_right
\empty
539
\scratchdimentwo
\dimexpr
\directxtableparameter
\c!alignmentrightwidth
\relax
540
\else
541
\setbox
\scratchbox
\hbox
{
\p_right
}
%
542
\scratchdimentwo
\wd
\scratchbox
543
\fi
544
\clf_setcharacteraligndetail
545
\clf_x_table_c
546
{
\directxtableparameter
\c!alignmentcharacter
}
%
547
\scratchdimenone
548
\scratchdimentwo
549
\relax
}
550 551
\newtoks
\t_tabl_x_every_cell
552 553
% \appendtoks
554
% \inhibitblank % already in framed
555
% \to \t_tabl_x_every_cell
556 557
\appendtoks
558
\edef
\p_characteralign
{
\directxtableparameter
\c!aligncharacter
}
%
559
\ifx
\p_characteralign
\v!yes
560
\ifcase
\clf_x_table_r
\or
561
\tabl_x_setup_character_align
562
\fi
563
\signalcharacteralign
\clf_x_table_c
\clf_x_table_r
564
\fi
565
\to
\t_tabl_x_every_cell
566 567
\unexpanded
\def
\tabl_x_begin_of_cell
568
{
\the
\t_tabl_x_every_cell
569
\everypar
{
\delayedbegstrut
}
}
570 571
\unexpanded
\def
\tabl_x_end_of_cell
572
{
\ifhmode
573
\delayedendstrut
574
\par
575
\else
576
\par
577
\ifdim
\prevdepth
<
\zeropoint
% =-1000pt ?
578
\vskip
-
\strutdp
579
\else
580
\removebottomthings
581
\fi
582
\fi
}
583 584
% For historic reasons we support both nx/nc and ny/nr : maybe nx/ny becomes
585
% obsolete some day. The let as well as the direct speed things up a bit. We
586
% could also consider a \defaultxtableparameter.
587
%
588
% \c_tabl_x_nx\defaultxtableparameter\c!nc{\defaultxtableparameter\c!nx\plusone}
589
% \c_tabl_x_ny\defaultxtableparameter\c!nr{\defaultxtableparameter\c!ny\plusone}
590
%
591
% Although this becomes kind of messy. It saves already time that we only check
592
% for it when we have settings.
593 594
% \def\tabl_x_set_hsize
595
% {\hsize.25\maxdimen} % let's be reasonable
596 597
% \def\tabl_x_set_hsize
598
% {\edef\p_width{\xtableparameter\c!width}%
599
% \ifx\p_width\empty
600
% \hsize.25\maxdimen % is this really needed
601
% \fi}
602 603
\let
\tabl_x_set_hsize
\relax
604 605
\unexpanded
\def
\tabl_x_start_cell_reflow_width_yes
[
#
settings
]
%
606
{
\setbox
\b_tabl_x
\hpack
\bgroup
607
\ifnum
\c_tabl_x_nesting
>
\plusone
608
\letxtableparameter
\c!width
\v!fit
% overloads given width
609
\letxtableparameter
\c!height
\v!fit
% overloads given height
610
\fi
611
%
612
\letxtableparameter
\c!nx
\plusone
613
\letxtableparameter
\c!ny
\plusone
614
\letxtableparameter
\c!nc
\plusone
615
\letxtableparameter
\c!nr
\plusone
616
%
617
\setupcurrentxtable
[
#
settings
]
%
618
%
619
\c_tabl_x_nx
\directxtableparameter
\c!nc
\relax
620
\c_tabl_x_ny
\directxtableparameter
\c!nr
\relax
621
\ifnum
\c_tabl_x_nx
=
\plusone
622
\c_tabl_x_nx
\directxtableparameter
\c!nx
\relax
623
\fi
624
\ifnum
\c_tabl_x_ny
=
\plusone
625
\c_tabl_x_ny
\directxtableparameter
\c!ny
\relax
626
\fi
627
%
628
\d_tabl_x_distance
\xtableparameter
\c!distance
\relax
629
\clf_x_table_init_reflow_width_option
{
\xtableparameter
\c!option
}
%
630
\inheritedxtableframed
\bgroup
631
\tabl_x_begin_of_cell
632
\tabl_x_set_hsize
}
633 634
\unexpanded
\def
\tabl_x_start_cell_reflow_width_nop
635
{
\setbox
\b_tabl_x
\hpack
\bgroup
636
\ifnum
\c_tabl_x_nesting
>
\plusone
637
\letxtableparameter
\c!width
\v!fit
% overloads given width
638
\letxtableparameter
\c!height
\v!fit
% overloads given height
639
\fi
640
\c_tabl_x_nx
\plusone
641
\c_tabl_x_ny
\plusone
642
\d_tabl_x_distance
\xtableparameter
\c!distance
\relax
643
\clf_x_table_init_reflow_width
644
\inheritedxtableframed
\bgroup
645
\tabl_x_begin_of_cell
646
\tabl_x_set_hsize
}
647 648
\unexpanded
\def
\tabl_x_stop_cell_reflow_width
649
{
\tabl_x_end_of_cell
650
\egroup
651
\egroup
652
\clf_x_table_set_reflow_width
}
653 654
\unexpanded
\def
\tabl_x_start_cell_reflow_height_yes
[
#
settings
]
%
655
{
\setbox
\b_tabl_x
\hpack
\bgroup
656
\clf_x_table_init_reflow_height
657
\ifcase
\c_tabl_x_skip_mode
% can be sped up
658
\ifnum
\c_tabl_x_nesting
>
\plusone
659
\letxtableparameter
\c!height
\v!fit
% overloads given height
660
\fi
661
\setupcurrentxtable
[
#
settings
]
%
662
\relax
663
\letxtableparameter
\c!width
\d_tabl_x_width
% overloads given width
664
\inheritedxtableframed
\bgroup
665
\tabl_x_begin_of_cell
666
\fi
}
667 668
\unexpanded
\def
\tabl_x_start_cell_reflow_height_nop
669
{
\setbox
\b_tabl_x
\hpack
\bgroup
670
\clf_x_table_init_reflow_height
671
\ifcase
\c_tabl_x_skip_mode
% can be sped up
672
\ifnum
\c_tabl_x_nesting
>
\plusone
673
\letxtableparameter
\c!height
\v!fit
% overloads given height
674
\fi
675
\relax
676
\letxtableparameter
\c!width
\d_tabl_x_width
% overloads given width
677
\inheritedxtableframed
\bgroup
678
\tabl_x_begin_of_cell
679
\fi
}
680 681
\unexpanded
\def
\tabl_x_stop_cell_reflow_height
682
{
\ifcase
\c_tabl_x_skip_mode
683
\tabl_x_end_of_cell
684
\egroup
685
\fi
686
\egroup
687
\clf_x_table_set_reflow_height
}
688 689
\unexpanded
\def
\tabl_x_start_cell_construct_yes
[
#
settings
]
%
690
{
\dostarttagged
\t!tablecell
\empty
% can't we just tag the box
691
\setbox
\b_tabl_x
\hpack
\bgroup
692
\setupcurrentxtable
[
#
settings
]
%
693
\letxtableparameter
\c!width
\d_tabl_x_width
% overloads given width
694
\letxtableparameter
\c!height
\d_tabl_x_height
% overloads given height
695
\clf_x_table_init_construct
696
\inheritedxtableframed
\bgroup
697
\tabl_x_begin_of_cell
698
\dotagxtablecell
}
699 700
\unexpanded
\def
\tabl_x_start_cell_construct_nop
701
{
\dostarttagged
\t!tablecell
\empty
% can't we just tag the box
702
\setbox
\b_tabl_x
\hpack
\bgroup
703
\letxtableparameter
\c!width
\d_tabl_x_width
% overloads given width
704
\letxtableparameter
\c!height
\d_tabl_x_height
% overloads given height (commenting it ... nice option)
705
\clf_x_table_init_construct
706
\inheritedxtableframed
\bgroup
707
\tabl_x_begin_of_cell
708
\dotagxtablecell
}
709 710
\unexpanded
\def
\tabl_x_stop_cell_construct
711
{
\tabl_x_end_of_cell
712
\egroup
713
\dotagxtablesignal
% harmless spot
714
\egroup
715
\clf_x_table_set_construct
716
\dostoptagged
}
717 718
\unexpanded
\def
\startxcellgroup
719
{
\begingroup
720
\dosingleempty
\tabl_x_start_cell_group
}
721 722
\unexpanded
\def
\stopxcellgroup
723
{
\endgroup
}
724 725
\unexpanded
\def
\tabl_x_start_cell_group
[
#
settings
]
%
726
{
\iffirstargument
727
\tabl_x_set_checked
{
#
settings
}
%
728
\fi
}
729 730
\unexpanded
\def
\startxrowgroup
731
{
\begingroup
732
\dosingleempty
\tabl_x_start_row_group
}
733 734
\unexpanded
\def
\stopxrowgroup
735
{
\dostoptagged
736
\endgroup
}
737 738
\unexpanded
\def
\tabl_x_start_row_group
[
#
settings
]
%
739
{
\iffirstargument
740
\tabl_x_set_checked
{
#
settings
}
%
741
\fi
}
742 743
% \def\tabl_x_set_checked#settings
744
% {\doifassignmentelse{#settings}
745
% {\setupcurrentxtable[#settings]}
746
% {\ifcsname\namedxtablehash{#settings}\s!parent\endcsname
747
% \edef\currentxtable{#settings}%
748
% \fi}}
749 750
\unexpanded
\def
\tabl_x_set_checked
#
settings
%
751
{
\ifcsname
\namedxtablehash
{
#
settings
}
\s!parent
\endcsname
752
\edef
\currentxtable
{
#
settings
}
%
753
\else
754
\setupcurrentxtable
[
#
settings
]
%
755
\fi
}
756 757
\unexpanded
\def
\startxtablehead
{
\begingroup
\c_tabl_x_mode
\plusone
\dosingleempty
\tabl_x_start_partition
}
758
\unexpanded
\def
\startxtablefoot
{
\begingroup
\c_tabl_x_mode
\plustwo
\dosingleempty
\tabl_x_start_partition
}
759
\unexpanded
\def
\startxtablenext
{
\begingroup
\c_tabl_x_mode
\plusthree
\dosingleempty
\tabl_x_start_partition
}
760
\unexpanded
\def
\startxtablebody
{
\begingroup
\c_tabl_x_mode
\plusfour
\dosingleempty
\tabl_x_start_partition
}
761 762
\unexpanded
\def
\tabl_x_start_partition
[
#
settings
]
%
763
{
\iffirstargument
764
\tabl_x_set_checked
{
#
settings
}
%
765
\fi
}
766 767
\unexpanded
\def
\tabl_x_stop_partition
768
{
\endgroup
}
769 770
\let
\stopxtablehead
\tabl_x_stop_partition
771
\let
\stopxtablefoot
\tabl_x_stop_partition
772
\let
\stopxtablenext
\tabl_x_stop_partition
773
\let
\stopxtablebody
\tabl_x_stop_partition
774 775
%D This is an experiment! Beware: you can create loops by using nested
776
%D references to already chained settings.
777
%D
778
%D \startbuffer
779
%D \setupxtable[suffix][align=middle,foregroundcolor=red]
780
%D \setupxtable[blabla][foregroundstyle=slanted]
781
%D \setupxtable[crap] [foregroundcolor=blue]
782
%D \setupxtable[bold] [crap][foregroundstyle=bold]
783
%D
784
%D \startxtable[frame=off]
785
%D \startxtablehead
786
%D \startxrow[bold]
787
%D \startxcell[suffix] a 0 \stopxcell
788
%D \startxcell[blabla] a 1 \stopxcell
789
%D \startxcell a 2 \stopxcell
790
%D \stopxrow
791
%D \stopxtablehead
792
%D \startxtablebody
793
%D \startxrow \startxcell[suffix][ny=2] a 1 \stopxcell \startxcell b 1 \stopxcell \startxcell c 1 \stopxcell \stopxrow
794
%D \startxrow \startxcell b 2 \stopxcell \startxcell c 2 \stopxcell \stopxrow
795
%D \startxrow \startxcell[suffix] a 3 \stopxcell \startxcell b 3 \stopxcell \startxcell c 3 \stopxcell \stopxrow
796
%D \startxrow \startxcell[suffix] a 4 \stopxcell \startxcell b 4 \stopxcell \startxcell c 4 \stopxcell \stopxrow
797
%D \startxrow \startxcell[suffix] a 5 \stopxcell \startxcell b 5 \stopxcell \startxcell c 5 \stopxcell \stopxrow
798
%D \stopxtablebody
799
%D \stopxtable
800
%D \stopbuffer
801
%D
802
%D \typebuffer \placetable{}{\getbuffer}
803 804
\appendtoks
805
\letvalue
{
\??xtablecheck
\currentxtable
}
\relax
% faster than checking parent
806
\to
\everysetupxtable
807 808
% \definefontfamily[newtimes][serif][TeX Gyre Termes]
809
% \setupxtable[newtimes][foregroundstyle=\newtimes]
810
% \startxcell[newtimes] ...\stopxcell
811
% \startxcell[foregroundstyle=\newtimes] ...\stopxcell
812 813
% % \ifcsname\namedxtablehash{#tag}\s!parent\endcsname
814
% % \ifcsname\??xtablecheck#tag\endcsname
815
% \ifcsname\??xtablecheck\detokenize\expandafter{\normalexpanded{#tag}}\endcsname % two times slower on keywords
816
% \expandafter\whatever % but more tolerant for tricky key=value
817
% \else
818
% \expandafter\whatever
819
% \fi[#tag]
820 821
% groups
822 823
\unexpanded
\def
\startxgroup
824
{
\begingroup
825
\doifelsenextoptionalcs
\tabl_x_start_group_delayed_one
\relax
}
826 827
\unexpanded
\def
\stopxgroup
828
{
\endgroup
}
829 830
\unexpanded
\def
\tabl_x_start_group_delayed_one
[
#
tag
]
%
831
{
\ifcsname
\??xtablecheck
\detokenize
\expandafter
{
\normalexpanded
{
#
tag
}
}
\endcsname
832
\expandafter
\tabl_x_start_group_delayed_two
833
\else
834
\expandafter
\setupcurrentxtable
835
\fi
[
#
tag
]
}
836 837
\unexpanded
\def
\tabl_x_start_group_delayed_two
[
#
tag
]
%
838
{
\ifx
\currentxtable
\empty
\else
839
\chaintocurrentxtable
{
#
tag
}
%
840
\fi
841
\edef
\currentxtable
{
#
tag
}
%
842
\doifelsenextoptionalcs
\setupcurrentxtable
\relax
}
843 844
\let
\startxrowgroup
\startxgroup
845
\let
\stopxrowgroup
\stopxgroup
846
\let
\startxcellgroup
\startxgroup
847
\let
\stopxcellgroup
\stopxgroup
848 849
% cells (maybe also check for 1 etc but it becomes messy)
850 851
\unexpanded
\def
\startxcell
852
{
\begingroup
853
\doifelsenextoptionalcs
\tabl_x_start_cell_delayed_one
\tabl_x_start_cell_nop
}
854 855
\unexpanded
\def
\tabl_x_start_cell_delayed_one
[
#
tag
]
%
856
{
\ifcsname
\??xtablecheck
\detokenize
\expandafter
{
\normalexpanded
{
#
tag
}
}
\endcsname
857
\expandafter
\tabl_x_start_cell_delayed_two
858
\else
859
\expandafter
\tabl_x_start_cell_yes
860
\fi
[
#
tag
]
}
861 862
\unexpanded
\def
\tabl_x_start_cell_delayed_two
[
#
tag
]
%
863
{
\ifx
\currentxtable
\empty
\else
864
\chaintocurrentxtable
{
#
tag
}
%
865
\fi
866
\edef
\currentxtable
{
#
tag
}
%
867
\doifelsenextoptionalcs
\tabl_x_start_cell_yes
\tabl_x_start_cell_nop
}
868 869
\unexpanded
\def
\stopxcell
870
{
\tabl_x_stop_cell
871
\endgroup
}
872 873
% rows
874 875
\unexpanded
\def
\startxrow
876
{
\begingroup
877
\doifelsenextoptionalcs
\tabl_x_start_row_delayed_one
\tabl_x_start_row_nop
}
878 879
\unexpanded
\def
\tabl_x_start_row_delayed_one
[
#
tag
]
%
880
{
\ifcsname
\??xtablecheck
\detokenize
\expandafter
{
\normalexpanded
{
#
tag
}
}
\endcsname
881
\expandafter
\tabl_x_start_row_delayed_two
882
\else
883
\expandafter
\tabl_x_start_row_yes
884
\fi
[
#
tag
]
}
885 886
\unexpanded
\def
\tabl_x_start_row_delayed_two
[
#
tag
]
%
887
{
\ifx
\currentxtable
\empty
\else
888
\chaintocurrentxtable
{
#
tag
}
%
889
\fi
890
\edef
\currentxtable
{
#
tag
}
%
891
\doifelsenextoptionalcs
\tabl_x_start_row_yes
\tabl_x_start_row_nop
}
892 893
\unexpanded
\def
\stopxrow
894
{
\tabl_x_stop_row
895
\endgroup
}
896 897
%D A bonus, not advertised but some like it this way:
898 899
\unexpanded
\def
\tabl_x_nc
900
{
\startxrow
901
\let
\NC
\tabl_x_nc_next
902
\let
\NR
\tabl_x_nr
903
\startxcell
}
904 905
\unexpanded
\def
\tabl_x_nc_next
906
{
\stopxcell
907
\startxcell
}
908 909
\unexpanded
\def
\tabl_x_nr
910
{
\stopxcell
911
\stopxrow
912
\let
\NC
\tabl_x_nc
}
913 914
\appendtoks
915
\let
\NC
\tabl_x_nc
916
\let
\NR
\tabl_x_nr
917
\to
\everypreparextable
918 919
%D Another bonus, suggested by Taco at the 2018 \CONTEXT\ meeting.
920 921
\unexpanded
\def
\tabl_x_c_cell_start
#
settings
%
922
{
\begingroup
923
\tabl_x_set_checked
{
#
settings
}
%
924
\doifelsenextoptionalcs
\tabl_x_start_cell_yes
\tabl_x_start_cell_nop
}
925 926
\unexpanded
\def
\tabl_x_c_cell_stop
927
{
\tabl_x_stop_cell
928
\endgroup
}
929 930
% \unexpanded\def\dummyxcell
931
% {\tabl_x_start_cell_nop
932
% \tabl_x_stop_cell}
933 934
\def
\tabl_x_flush_swapped
935
{
\dorecurse
\c_tabl_x_swapped_max
936
{
\expandafter
937
\startxrow
938
\the
\csname
\??xtableswap
#
#
1
\endcsname
\relax
939
\stopxrow
}
}
940 941
\def
\tabl_x_collect_allocate
942
{
\expandafter
\newtoks
\csname
\??xtableswap
\number
\c_tabl_x_swapped
\endcsname
943
\expandafter
\let
\expandafter
\t_tabl_x_swapped
\csname
\??xtableswap
\number
\c_tabl_x_swapped
\endcsname
}
944 945
\def
\tabl_x_collect_advance
946
{
\global
\advance
\c_tabl_x_swapped
\plusone
947
\ifnum
\c_tabl_x_swapped
>
\c_tabl_x_swapped_max
948
\global
\c_tabl_x_swapped_max
\c_tabl_x_swapped
949
\fi
950
\expandafter
\let
\expandafter
\t_tabl_x_swapped
\csname
\??xtableswap
\number
\c_tabl_x_swapped
\endcsname
951
\ifx
\t_tabl_x_swapped
\relax
952
\tabl_x_collect_allocate
953
\fi
}
954 955
\unexpanded
\def
\tabl_x_collect_cell_start
956
{
\doifelsenextoptionalcs
957
\tabl_x_collect_cell_start_yes
958
\tabl_x_collect_cell_start_nop
}
959 960
\def
\tabl_x_collect_cell_start_nop
#
content
\stopxcell
961
{
\tabl_x_collect_advance
962
\ifx
\m_tabl_x_swapped_settings
\empty
963
\gtoksapp
\t_tabl_x_swapped
{
\tabl_x_c_cell_start
{
}
#
content
\tabl_x_c_cell_stop
}
%
964
\else
965
\gtoksapp
\t_tabl_x_swapped
\expandafter
{
\expandafter
\tabl_x_c_cell_start
\expandafter
{
\m_tabl_x_swapped_settings
}
#
content
\tabl_x_c_cell_stop
}
%
966
\fi
}
967 968
\def
\tabl_x_collect_cell_start_yes
[
#
settings
]
#
content
\stopxcell
969
{
\tabl_x_collect_advance
970
\ifx
\m_tabl_x_swapped_settings
\empty
971
\gtoksapp
\t_tabl_x_swapped
{
\tabl_x_c_cell_start
{
}
[
#
settings
]
#
content
\tabl_x_c_cell_stop
}
%
972
\else
973
\gtoksapp
\t_tabl_x_swapped
\expandafter
{
\expandafter
\tabl_x_c_cell_start
\expandafter
{
\m_tabl_x_swapped_settings
}
[
#
settings
]
#
content
\tabl_x_c_cell_stop
}
%
974
\fi
975
\getdummyparameters
[
\c!ny
=
1
,
#
settings
]
%
976
\scratchcounter
\numexpr
\dummyparameter
\c!ny
-
\plusone
\relax
977
\ifcase
\scratchcounter
\else
978
\dorecurse
\scratchcounter
\tabl_x_collect_advance
979
\fi
}
980 981
\unexpanded
\def
\startxcolumn
% todo: arguments
982
{
\begingroup
983
\global
\c_tabl_x_swapped
\zerocount
984
\let
\startxcell
\tabl_x_collect_cell_start
985
\let
\stopxcell
\relax
986
\doifelsenextoptionalcs
\tabl_x_start_column_yes
\tabl_x_start_column_nop
}
987 988
\def
\tabl_x_start_column_yes
[
#
1
]
%
989
{
\xdef
\m_tabl_x_swapped_settings
{
#
1
}
}
990 991
\def
\tabl_x_start_column_nop
992
{
\glet
\m_tabl_x_swapped_settings
\empty
}
993 994
\unexpanded
\def
\stopxcolumn
995
{
\endgroup
}
996 997
\appendtoks
998
\dorecurse
\c_tabl_x_swapped_max
999
{
\global
\csname
\??xtableswap
\number
#
1
\endcsname
\emptytoks
}
%
1000
\to
\t_table_x_cleanup
1001 1002
%D \stopbuffer
1003
%D \setupxtable[one][foregroundcolor=red]
1004
%D \setupxtable[two][foregroundcolor=blue]
1005
%D
1006
%D \startlinecorrection
1007
%D \startxtable
1008
%D \startxrow[one]
1009
%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell
1010
%D \startxcell Row 1, Column 2 \stopxcell
1011
%D \startxcell Row 1, Column 3 \stopxcell
1012
%D \stopxrow
1013
%D \startxrow[two]
1014
%D \startxcell Row 2, Column 1 \stopxcell
1015
%D \startxcell Row 2, Column 2 \stopxcell
1016
%D \startxcell Row 2, Column 3 \stopxcell
1017
%D \stopxrow
1018
%D \stopxtable
1019
%D \stoplinecorrection
1020
%D
1021
%D \startlinecorrection
1022
%D \startxtable
1023
%D \startxcolumn[one]
1024
%D \startxcell[width=5cm] Row 1, Column 1 \stopxcell
1025
%D \startxcell Row 1, Column 2 \stopxcell
1026
%D \startxcell Row 1, Column 3 \stopxcell
1027
%D \stopxcolumn
1028
%D \startxcolumn[two]
1029
%D \startxcell Row 2, Column 1 \stopxcell
1030
%D \startxcell Row 2, Column 2 \stopxcell
1031
%D \startxcell Row 2, Column 3 \stopxcell
1032
%D \stopxcolumn
1033
%D \stopxtable
1034
%D \stoplinecorrection
1035
%D \stopbuffer
1036
%D
1037
%D \typebuffer \getbuffer
1038 1039
\protect
\endinput
1040