4 Copyright (c) 2014 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
6 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
7 written by Joachim Walsdorff <Joachim.Walsdorff@urz.uni-heidelberg.de>.
9 This is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
14 This is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with groff; see the file COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA
26 .\" *****************************************************************
27 .\" * hdtbl - Heidelberger table macros *
28 .\" * Vers. 0.91 December 2005 *
29 .\" *****************************************************************
37 .wh 0 HM \" comment this out if a page header macro exists
38 .wh -1i BM \" comment this out if a bottom margin macro exists
40 .\" replace `HM' with the name of your pageheader macro, e.g., `pg@top' for MS
46 .\" *****************************************************************
47 .\" * default values for some arguments *
48 .\" *****************************************************************
67 .\" defaults for table captions
69 .ds t*cptn "".sp .4" \
72 "\m[\\*[t*fgc]]Table \\n+[t*cptn]:\0\c\k*"\"
75 .\" Running title, running footer
76 .ds t*HM //arbitrary text for pageheader, except on the first page//\"
77 .ds t*BM //arbitrary text for pagefooter, except on the last page/\\n[%]/\"
82 .\" for better error messages
87 .\" initialization of various registers
88 .nr t*# 0 \" table nesting level
89 .nr t*numb 0 1 \" held table diversion #
94 .\" *****************************************************************
95 .\" * The four base macros and the two optional macros *
96 .\" *****************************************************************
104 .\" predecessor: text, TD or ETB
105 .\" successor: CPTN or TR
107 . ds t*m\\n[t*#] \\n[.m]\"
115 . sp .4 \" XXX: hard-coded value
122 . getarg cols \\$@\" from here string `args' contains the rest of \\$@
124 . nr t*cols\\n[t*#] \\n[t*cols]
126 . ie \B
\a\\*[cols]
\a \
127 . nr t*cols\\n[t*#] \\*[cols]
129 . tm \\n[.F]:\\n[.c]: Invalid number of columns value `\\*[cols]'.
132 . getarg cpd \\*[args] \" cell padding
134 . nr t*cpd\\n[t*#] \\n[t*cpd]
136 . ie \B
\a\\*[cpd]
\a \
137 . nr t*cpd\\n[t*#] \\*[cpd]
139 . tm \\n[.F]:\\n[.c]: Invalid cell padding value `\\*[cpd]'.
142 . getarg csp \\*[args] \" cell spacing
144 . nr t*csp\\n[t*#] \\n[t*csp]
146 . ie \B
\a\\*[csp]
\a \
147 . nr t*csp\\n[t*#] \\*[csp]
149 . tm \\n[.F]:\\n[.c]: Invalid cell spacing value `\\*[csp]'.
152 . getarg border \\*[args] \" border thickness
153 . ie "\\*[border]"=" \
156 . ie "\\*[border]"" \
157 . nr t*b\\n[t*#] \\n[t*b]
159 . ie \B
\a\\*[border]
\a \
160 . nr t*b\\n[t*#] \\*[border]
162 . tm \\n[.F]:\\n[.c]: Invalid border thickness value `\\*[border]'.
165 . getarg bc \\*[args] \" border color
166 . ds t*bc\\n[t*#] \\*[t*bc]\"
169 . ds t*bc\\n[t*#] \\*[bc]\"
172 . ds t*bc\\n[t*#] =\"
174 . tm \\n[.F]:\\n[.c]: Invalid border color `\\*[bc]'.
180 . ds t*bc\\n[t*#] \\*[t*bc]\"
182 . ds t*bc\\n[t*#] \\*[bc]\"
185 . getarg width \\*[args] \" table/col widths
186 . if "\\*[width]"=" \
189 . nr b/2\\n[t*#] (\\n[t*b\\n[t*#]] / 2)\" shortcut
190 . nr cscp\\n[t*#] (\\n[t*csp\\n[t*#]] + \\n[t*cpd\\n[t*#]])\" aux. register
192 . getarg height \\*[args] \" table outline height
193 . ie "\\*[height]"" \
194 . nr t*height\\n[t*#] 0
196 . ie \B
\a\\*[height]
\a \
197 . nr t*height\\n[t*#] (\\*[height] \
198 - ((2 * \\n[cscp\\n[t*#]]) \
199 + (3 * \\n[b/2\\n[t*#]])))
201 . tm \\n[.F]:\\n[.c]: Invalid height value `\\*[height]'.
204 . t*cl \\*[width] \" get cell widths and offsets
205 . t*args \\n[t*#] \" look for common arguments
207 . getarg tal \\*[args] \" table horizontal alignment
209 . ds tal \\*[t*tal]\"
211 . nr in\\n[t*#] \\n[.i]
214 . nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]]/2 + \\n[.i])
217 . nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]] + \\n[.i])
219 . tmc \\n[.F]:\\n[.c]: Invalid horizontal table alignment `\\*[tal]':
220 . tm1 " must be `l', `c' or `r'.
223 . nr t*r#\\n[t*#] 0 \" initialize row index
230 .\" CPTN: optional table caption
237 . if \\n[t*r#\\n[t*#]] \{\
238 . tmc \\n[.F]:\\n[.c]: Invalid placement of `.CPTN';
239 . tm1 " must be called immediately after `.TBL'.
244 . ds args\\n[t*#] "\\*[args]\"
246 . index "\\*[args]" .TR
248 . ds *a\\n[t*#] "\\*[args]\"
249 . substring args\\n[t*#] 0 \\n[index]
250 . substring *a\\n[t*#] \\n[index]-2 -1
255 . ie "\\*[val]"b" \{\
257 . *CPTN \\*[args\\n[t*#]]
262 . ll (\\n[ll\\n[t*#]]u + \\n[in\\n[t*#]]u)
263 . in \\n[in\\n[t*#]]u
266 . P1 \\*[args\\n[t*#]]
279 .\" predecessor: TBL, CPTN, text, TD or ETB
284 . tm \\n[.F]:\\n[.c]: Table row (.TR) without preceding table start (.TBL).
288 . \" finish previous data cell, if any
289 . if \\n[t*r#\\n[t*#]] \
290 . t*dntr 1 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
292 . nr t*r#\\n[t*#] +1 \" row number in this table
293 . ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" table row identifier
295 . nr c#\\*[#t#r] 0 1 \" clear cell counter
296 . nr dntr\\*[#t#r] 0 1 \" clear accumulated row height
299 . ie "\\*[height]"" \
300 . nr t*height\\*[#t#r] 0
302 . ie \B
\a\\*[height]
\a \
303 . nr t*height\\*[#t#r] \\*[height]
305 . tm \\n[.F]:\\n[.c]: Invalid table row height `\\*[height]'.
308 . \" If there is a TR with height `height', the total height of the table
309 . \" is too high by 3/2 b, independent of the number of TR with `height'.
310 . t*args \\*[#t#r] \\n[t*#] \" look for common arguments
316 .\" TH: optional table header cell
317 .\" predecessor: text, TD or TR
318 .\" successor: text, TD, TR, TBL or ETB
320 .\" cell content bolded and horizontally and vertically centered,
328 . getarg val \\*[args]
332 . getarg fst \\*[args]
336 . TD hal=\\*[hal] val=\\*[val] fst=\\*[fst] \\*[args]
340 .\" TD: table data cell
341 .\" predecessor: text, TD or TR
342 .\" successor: text, TD, TR, TBL or ETB
345 . \" finish previous data cell -- note the use of \E
346 . t*dntr 0 \\n[c#\\*[#t#r]]-1 \En[c#\\*[#t#r]] \\*[*#trc*]
348 . ds *#trc* \\*[#t#r]*\\n[c#\\*[#t#r]]\" table cell identifier
349 . \" (<level>*<row>*<column>)
351 . getarg rowspan \\$@
353 . if !"\\*[rowspan]"" \{\
354 . ie \B
\a\\*[rowspan]
\a \{\
355 . nr rowspan (\\*[rowspan] >? 1)
356 . nr *rsp*\\*[*#trc*] (\\n[rowspan] - 1)
359 . tm \\n[.F]:\\n[.c]: Invalid value of `rowspan' keyword.
362 . getarg colspan \\*[args]
364 . if !"\\*[colspan]"" \{\
365 . ie \B
\a\\*[colspan]
\a \
366 . nr colspan (\\*[colspan] >? 1)
368 . tm \\n[.F]:\\n[.c]: Invalid value of `colspan' keyword.
371 . t*args \\*[#trc] \\*[#t#r] \" look for common arguments
373 . nr in\\*[#trc] \\n[in\\n[t*#]*\\n[c#\\*[#t#r]]]
374 . nr *cl \\n[cll\\n[t*#]*\\n[c#\\*[#t#r]]]
376 . nr *r \\n[t*r#\\n[t*#]]
378 . if (\\n[rowspan] - 1) \
379 . while (\\n+[*] <= \\n[rowspan]) \{\
380 . nr rspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
382 . nr cspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
387 . nr *c \\n[c#\\*[#t#r]]
389 . if (\\n[colspan] - 1) \{\
390 . nr vline\\*[*#trc*] 0-1 \" set `no vl' flag
392 . while (\\n+[*] <= \\n[colspan]) \{\
394 . nr *cl +(2 * \\n[cscp\\n[t*#]] \
396 + \\n[cll\\n[t*#]*\\n[*c]])
401 . if (\\n[c#\\n[t*#]*\\n[t*r#\\n[t*#]]] > \\n[t*cols\\n[t*#]]) \{\
404 . if (\\n[c#\\*[#t#r]] == 1) \{\
408 . tmc \\n[.F]:\\n[.c]: There \\*[*] \\n[c#\\*[#t#r]] table \\*[**] (.TD)
411 . if (\\n[t*cols\\n[t*#]] == 1) \
413 . tm1 " but only \\n[t*cols\\n[t*#]] \\*[*] expected.
416 . length * \\n[.F]:\\n[.c]:
421 . tm1 "\\*[*] Remaining .TDs and its contents are ignored.
423 . di *t*dummy* \" bypass superfluous input
427 . di t*\\*[#trc] \" open cell diversion and set locals
429 . nr cll\\*[#trc] \\n[*cl]
431 . nr *cl\\n[t*#] \\n[.l]
432 . gcolor \\*[t*fgc\\*[#trc]]
433 . ad \\*[t*hal\\*[#trc]]
434 . fam \\*[t*ff\\*[#trc]]
435 . ft \\*[t*fst\\*[#trc]]
436 . pv \\*[t*fsz\\*[#trc]]
442 .\" ETB: end of table
443 .\" predecessor: text, TD or ETB
444 .\" successor: text, TD, TR or TBL
447 . if !\\n[t*r#\\n[t*#]] \{\
448 . tmc \\n[.F]:\\n[.c]: Each table (.TBL)
449 . tm1 " should contain at least one table row (.TR)!
452 . tmc \\n[.F]:\\n[.c]: Table end (.ETB)
453 . tm1 " without corresponding table start (.TBL)!
456 . ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" refresh table row identifier
457 . t*dntr 2 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
459 . t*divs \" print this table
461 . sp \\n[b/2\\n[t*#]]u
465 . ll \\n[*cl\\n[t*#]]u \" restore ll outside this table
466 . in 0 \" reset indent
467 . gcolor \\*[t*m\\n[t*#]] \" reset previous fgc
474 . ie "\\*[hold]"" \{\
475 . ie (\\n[.t] - \\n[dn]) \
478 . rn t*tbl0 t*tbl\\n[t*numb]
479 . ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[dn]\"
483 . rn t*tbl0 t*hold\\n+[t*numb]
484 . tm \\n[.F]:\\n[.c]: Table t*hold\\n[t*numb] held.
485 . ds t*held \\*[t*held] t*hold\\n[t*numb] \\n[dn]\"
488 . ev \" restore previous environment
495 .\" *****************************************************************
496 .\" * Following the definition of five utility macros *
497 .\" * special to hdtbl. *
498 .\" * Other utility macros common to hdtbl and hdgroff *
499 .\" * are defined in the file hdmisc.tmac. *
500 .\" *****************************************************************
504 .\" print the next [n] held table[s].
505 .\" Don't call it within a table!
506 .\" If the table is higher than the remaining space
507 .\" on the page, the table is printed on the next page.
510 . if \\n[t*r#\\n[t*#]] \{\
511 . tmc \\n[.F]:\\n[.c]: Invalid placement of `.t*free' within a table;
512 . tm1 " it must be called outside of any table.
516 . if "\\*[t*held]"" \{\
517 . tm \\n[.F]:\\n[.c]: No held tables.
522 . while !""\\*[t*held]" \{\
526 . ie (\\n[.t] - \\n[*]) \{\
532 . rn \\*[*] t*tbl\\n+[t*numb]
533 . ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[*]\"
536 . if !(\\n-[**] - 1) \
542 .\" The main utility macro for tables:
543 .\" If a table is closed by ETB, this macro is called. It
544 .\" processes one complete table, i.e., all the table cell
545 .\" diversions, paints the cell backgrounds, draws
546 .\" horizontal and vertical table lines and the table border.
548 .\" Nested tables are processed from inside to outside.
551 . ll (\\n[l]u + 1c) \" avoid warning `can't break line'
554 . nr b/2 \\n[b/2\\n[t*#]] \" some abbreviations
555 . nr cscp \\n[cscp\\n[t*#]]
556 . nr cscpb (\\n[b/2] + \\n[cscp])
558 . nr topdiv (\\n[.d] + \\n[b/2] - \\n[cscp])\" top of cell diversion
559 . nr cscpb2 (\\n[b/2] / 2 + \\n[cscp])
562 . \" outer loop for rows
563 . while (\\n+[#r] <= \\n[t*r#\\n[t*#]]) \{\
564 . \" TODO: insert code here for multipage tables
566 . nr topdiv +(\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
568 . \" if table still smaller than specified table height, increase it
569 . if ((\\n[#r] == \\n[t*r#\\n[t*#]]) & \\n[t*height\\n[t*#]]) \
570 . nr dntr\\n[t*#]*\\n[#r] (\\n[cscpb] \
571 + \\n[toptbl\\n[t*#]] \
572 + \\n[t*height\\n[t*#]] \
573 - (\\n[topdiv] >? \\n[dntr\\n[t*#]*\\n[#r]]))
576 . \" inner loop for cells
577 . while (\\n+[#c] <= \\n[t*cols\\n[t*#]]) \{\
578 . ds #trc \\n[t*#]*\\n[#r]*\\n[#c]\"
579 . \" continue if the diversion is empty
580 . if !d t*\\*[#trc] \
584 . in (\\n[in\\n[t*#]]u + \\n[in\\*[#trc]]u)\" cell offset
585 . nr $1 \\n[dntr\\n[t*#]*\\n[#r]] \" cell height
587 . \" if we have spanned rows, calculate resulting row height
588 . \" and position of lower horizontal line
589 . if \\n[*rsp*\\*[#trc]] \{\
591 . nr rspan\\*[#trc] 0-1 \" set `no hl' flag
592 . nr corr (\\n[dn\\*[#trc]] - \\n[dntr\\n[t*#]*\\n[#r]])
594 . \" clear row span flags in following rows and update row height
595 . while \\n[*rsp*\\*[#trc]] \{\
596 . nr *rsp*\\*[#trc] -1
597 . nr rspan\\n[t*#]*\\n+[*]*\\n[#c] 0
598 . nr ** (\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
603 . if (\\n-[*] == \\n[t*r#\\n[t*#]]) \
604 . nr $1 ((\\n[t*height\\n[t*#]] \
606 + \\n[toptbl\\n[t*#]] \
609 . nr dntr\\n[t*#]*\\n[*] +(\\n[corr] >? 0)
612 . \" paint cell background
613 . nr * (2 * \\n[t*cpd\\n[t*#]] + \\n[cll\\*[#trc]])\" background width
614 . nr $1 (\\n[$1] >? \\n[dn\\*[#trc]])\" cell height
616 . if !"\\*[t*bgc\\*[#trc]]"=" \{\
617 . nop \h'\\n[t*csp\\n[t*#]]u'\
618 \M[\\*[t*bgc\\*[#trc]]]\
619 \v'(-.67v - \\n[t*cpd\\n[t*#]]u)'\
621 0 (2u * \\n[t*cpd\\n[t*#]]u + \\n[$1]u) \
627 . \" *** horizontal and vertical single or double lines ***
628 . \" double and single lines have the same thickness;
629 . \" the double lines' distance is the line thickness.
631 . \" `border=x': horizontal/vertical lines x/2 thick, minimum .1n
632 . \" `border=0': no border; horizontal/vertical lines .1n thick
633 . \" `border=': neither border nor horizontal/vertical lines
635 . nr *t (.1n >? \\n[b/2]) \" thickness of hl/vl; min. .1n
638 . \" check for vertical and horizontal lines
639 . if (1 + \\n[t*b\\n[t*#]]) \{\
640 . if !"\\*[t*bc\\n[t*#]]"=" \{\
641 . \" draw horizontal line between this cell and the one below
642 . if (\\n[t*r#\\n[t*#]] - \\n[#r] + \\n[rspan\\*[#trc]]) \{\
643 . if !"\\*[t*hl\\*[#trc]]"=" \{\
645 . nr * (\\n[cscp] + \\n[cscpb] + \\n[cll\\*[#trc]])
646 . nop \X'\*[g] 1 setlinecap'\
647 \h'(-\\n[cscpb2]u - \\n[*t]u)'\
648 \v'(\\n[cscpb2]u - .67v)'\
649 \m[\\*[t*bc\\n[t*#]]]\
652 . ie "\\*[t*hl\\*[#trc]]"d" \
659 . nop \D'l \\n[*]u 0'\
662 . sp (-\\n[$1]u - 1v)
665 . nr rspan\\*[#trc] 0
667 . \" draw vertical line between this cell and the one to the right
668 . if (\\n[t*cols\\n[t*#]] - \\n[#c] + \\n[vline\\*[#trc]]) \{\
669 . if !"\\*[t*vl\\*[#trc]]"=" \{\
670 . nop \X'\*[g] 1 setlinecap'\
671 \v'(-\\n[cscpb2]u - .67v)'\
672 \m[\\*[t*bc\\n[t*#]]]\
673 \h'(\\n[cscpb2]u - \\n[*t]u + \\n[cll\\*[#trc]]u)'\c
675 . ie "\\*[t*vl\\*[#trc]]"d" \
678 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
680 \D'l 0 -(2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
683 . nop \D't \\n[*t]u'\
684 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
689 . nr vline\\*[#trc] 0
691 . \" vert. cell content alignment
694 . ie "\\*[t*val\\*[#trc]]"m" \
695 . nr ** ((\\n[$1] - \\n[dn\\*[#trc]]) / 2)\" val=m
697 . if "\\*[t*val\\*[#trc]]"b" \
698 . nr ** (\\n[$1] - \\n[dn\\*[#trc]])\" val=b
700 . sp \\n[**]u \" vertical content position
702 . \" finally output the diversion
708 . \" draw the box border
709 . in \\n[in\\n[t*#]]u
710 . nr ** (\\n[topdiv] + \\n[dntr\\n[t*#]*\\n-[#r]])
712 . if \\n[t*b\\n[t*#]] \{\
713 . sp |(\\n[toptbl\\n[t*#]]u + \\n[b/2]u)
714 . nr $1 (\\n[toptbl\\n[t*#]] - \\n[**] - \\n[cscp])
715 . nr * (\\n[ll\\n[t*#]] - \\n[t*b\\n[t*#]])
717 . if !"\\*[t*bc\\n[t*#]]"=" \
718 . nop \X'\*[g] 0 setlinejoin 2 setlinecap'\
721 \m[\\*[t*bc\\n[t*#]]]\
722 \D't \\n[t*b\\n[t*#]]u'\
730 . sp |(\\n[**]u + \\n[cscpb]u)
735 .\" Utility macro: .t*cl [width1 [width2 [...]]]
737 .\" Calculate cell widths, table width, and cell offsets.
739 . nr t*cols\\n[t*#] (\\n[.$] >? \\n[t*cols\\n[t*#]])
740 . nr ll\\n[t*#] 0 \" accumulated cell widths
741 . nr ** (\\n[.l] / \\n[t*cols\\n[t*#]])\" width for remaining cells
742 . nr * 0 1 \" counter
744 . \" while-loop: Parse user arguments to get each cell's width.
745 . while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
747 . if !"\\$[\\n[*]]"" \{\
748 . \" check for `%' pseudo scaling indicator
752 . ds ** \\$[\\n[*]]\"
755 . nr $\\n[*] (\\*[**] * \\n[.l] / 100)
757 . tm \\n[.F]:\\n[.c]: Invalid relative cell width `\\*[**]%'.
760 . ie \B
\a\\$[\\n[*]]
\a \
761 . nr $\\n[*] \\$[\\n[*]]
763 . tm \\n[.F]:\\n[.c]: Invalid cell width `\\$[\\n[*]]'.
766 . nr ll\\n[t*#] +\\n[$\\n[*]]
770 . if (\\n[ll\\n[t*#]] > \\n[.l]) \
771 . tm \\n[.F]:\\n[.c]: Table width larger than column width.
773 . nr ** (0 >? \\n[t*b\\n[t*#]])
776 . \" second while loop: Compute final cell widths.
777 . while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
778 . \" Remove border width, if any.
779 . if \\n[t*b\\n[t*#]] \{\
780 . \" cell_width := cell_width * (length - 1.5*border) / length
781 . nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
782 . nr *** (\\n[ll\\n[t*#]] / 2)
783 . \" avoid multiplication overflow
784 . mult31by31 $\\n[*] #* ****
785 . add31to62 *** **** ****
786 . div62by31 **** ll\\n[t*#] $\\n[*]
789 . \" Get cell widths without padding, spacing, and separator line.
790 . nr cll\\n[t*#]*\\n[*] (\\n[$\\n[*]] \
791 - (2 * \\n[cscp\\n[t*#]]) \
794 . \" Check whether value is non-positive.
795 . if !\\n[cll\\n[t*#]*\\n[*]] \{\
796 . nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
797 . nr *** (\\n[#*] / 2)
798 . nr *h (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])
799 . mult31by31 *h ll\\n[t*#] ****
800 . add31to62 *** **** ****
801 . div62by31 **** #* *h
803 . nr *** (\\n[*] % 10)
804 . if d nth-\\n[***] \
805 . ds * \\n[*]\\*[nth-\\n[***]]\"
806 . tmc \\n[.F]:\\n[.c]: The \\*[*] width value (\\$\\n[*]) is too small.
807 . tm1 " It should be greater than \\n[*h].
810 . nr in\\n[t*#]*\\n[*] \\n[**] \" cell offset
811 . nr ** +\\n[$\\n[*]]
816 .\" Utility macro: .t*dntr <origin> <cell position> ? <cell ID>
818 .\" Close TD diversion, make some calculations, and set
819 .\" some help strings and registers. <origin> is 0, 1,
820 .\" or 2 if the call of .t*dntr occurs in .TD, .TR, or
821 .\" .ETB, respectively.
823 . nr dn 0 \" reset diversion height
824 . br \" finish cell data
826 . if "\\n[.z]"*t*dummy*" \
829 . ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" refresh table row identifier
831 . if \\n[c#\\*[#t#r]] \{\
832 . di \" close diversion
833 . nr dn\\$4 \\n[dn] \" save height of this cell
834 . if !\\n[rspan\\*[#trc]] \{\
835 . \" update row height if not in a row span
836 . nr dntr\\*[#t#r] (\\n[dntr\\*[#t#r]] >? \\n[dn])
838 . nr dntr\\*[#t#r] ((\\n[t*height\\*[#t#r]] \
839 - (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])) \
840 >? \\n[dntr\\*[#t#r]])
846 . \" update column span registers
847 . while (\\n+[*] <= \\$3) \{\
848 . if r cspan\\*[#t#r]*\\n[*] \
849 . nr c#\\*[#t#r] +\\n[cspan\\*[#t#r]*\\n[*]]
850 . nr cspan\\*[#t#r]*\\n[*] 0
853 . ds #trc \\*[#t#r]*\\n[c#\\*[#t#r]]\"
855 . \" only check for cell underflow if called by .TR or .ETB
856 . if (\\$1 & (\\n[c#\\*[#t#r]] <= \\n[t*cols\\n[t*#]])) \{\
859 . if (\\n-[c#\\*[#t#r]] == 1) \{\
863 . tmc \\n[.F]:\\n[.c]: There \\*[*] only \\n[c#\\*[#t#r]] \\*[**]
865 . nr * \\n[t*r#\\n[t*#]]
867 . nr *** (\\n[*] % 10)
868 . if d nth-\\n[***] \
869 . ds * \\n[*]\\*[nth-\\n[***]]\"
870 . tmc " in the \\*[*] row
873 . if (\\n[t*cols\\n[t*#]] == 1) \
875 . tm1 " but \\n[t*cols\\n[t*#]] \\*[*] expected.
880 .\" Utility-macro: .t*args level_1 [level_2]
882 .\" Get the arguments common to TBL, TR, and TD for the level
883 .\" in argument 1, using default values from the level in
884 .\" argument 2. If argument 2 is missing, use the global
888 . ds t*bgc\\$1 \\*[t*bgc\\$2]\"
889 . ds t*fgc\\$1 \\*[t*fgc\\$2]\"
890 . ds t*hl\\$1 \\*[t*hl\\$2]\"
891 . ds t*vl\\$1 \\*[t*vl\\$2]\"
892 . ds t*hal\\$1 \\*[t*hal\\$2]\"
893 . ds t*val\\$1 \\*[t*val\\$2]\"
894 . ds t*ff\\$1 \\*[t*ff\\$2]\"
895 . ds t*fst\\$1 \\*[t*fst\\$2]\"
896 . ds t*fsz\\$1 \\*[t*fsz\\$2]\"
901 . getarg bgc \\*[args] \" background color
902 . if !"\\*[bgc]"" \{\
904 . ds t*bgc\\$1 \\*[bgc]\"
909 . tm \\n[.F]:\\n[.c]: Invalid background color `\\*[bgc]'.
914 . getarg fgc \\*[args] \" foreground color
915 . if !"\\*[fgc]"" \{\
917 . ds t*fgc\\$1 \\*[fgc]\"
922 . tm \\n[.F]:\\n[.c]: Invalid foreground color `\\*[fgc]'.
927 . getarg hl \\*[args] \" horizontal line between cells
929 . ds t*hl\\$1 \\*[hl]\"
933 . getarg vl \\*[args] \" vertical line between cells
935 . ds t*vl\\$1 \\*[vl]\"
939 . getarg hal \\*[args] \" horizontal table cell alignment
940 . if !"\\*[hal]"" \{\
941 . index bcrl \\*[hal]
943 . ds t*hal\\$1 \\*[hal]\"
945 . tmc \\n[.F]:\\n[.c]: Invalid horizontal alignment `\\*[hal]':
946 . tm1 " must be `b', `c', `l' or `r'.
951 . getarg val \\*[args] \" vertical table cell alignment
952 . if !"\\*[val]"" \{\
955 . ds t*val\\$1 \\*[val]\"
957 . tmc \\n[.F]:\\n[.c]: Invalid vertical alignment `\\*[val]':
958 . tm1 " must be `t', `m' or `b'.
963 . getarg ff \\*[args] \" font family
965 . ds t*ff\\$1 \\*[ff]\"
969 . getarg fst \\*[args] \" font style
971 . ds t*fst\\$1 \\*[fst]\"
975 . getarg fsz \\*[args] \" font size and spacing factor
977 . ds t*fsz\\$1 \\*[fsz]\"
984 . while !""\\*[t*kept]" \{\
987 . if (\\n[*] - \\n[**]) \{\
988 . tm \\n[.F]:\\n[.c]: Table \\*[*] higher than page -- ignored!
992 . if (\\n[*] - \\n[.t]) \{\
993 . ds t*kept \\n[*] \\*[t*kept]\"
994 . ds t*kept \\*[*] \\*[t*kept]\"
995 . tmc \\n[.F]:\\n[.c]: Remaining table(s),
996 . tm1 " because not all fit onto this page.