6 This file is part of groff, the GNU roff type-setting system.
8 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
9 written by Joachim Walsdorff <Joachim.Walsdorff@urz.uni-heidelberg.de>.
11 groff is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 2, or (at your option) any later
16 groff is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with groff; see the file COPYING. If not, write to the Free
23 Software Foundation, 51 Franklin St - Fifth Floor, Boston, MA
29 .\" *****************************************************************
30 .\" * hdtbl - Heidelberger table macros *
31 .\" * Vers. 0.91 December 2005 *
32 .\" *****************************************************************
40 .wh 0 HM \" comment this out if a page header macro exists
41 .wh -1i BM \" comment this out if a bottom margin macro exists
43 .\" replace `HM' with the name of your pageheader macro, e.g., `pg@top' for MS
49 .\" *****************************************************************
50 .\" * default values for some arguments *
51 .\" *****************************************************************
70 .\" defaults for table captions
72 .ds t*cptn "".sp .4" \
75 "\m[\\*[t*fgc]]Table \\n+[t*cptn]:\0\c\k*"\"
78 .\" Running title, running footer
79 .ds t*HM //arbitrary text for pageheader, except on the first page//\"
80 .ds t*BM //arbitrary text for pagefooter, except on the last page/\\n[%]/\"
85 .\" for better error messages
90 .\" initialization of various registers
91 .nr t*# 0 \" table nesting level
92 .nr t*numb 0 1 \" held table diversion #
97 .\" *****************************************************************
98 .\" * The four base macros and the two optional macros *
99 .\" *****************************************************************
107 .\" predecessor: text, TD or ETB
108 .\" successor: CPTN or TR
110 . ds t*m\\n[t*#] \\n[.m]\"
118 . sp .4 \" XXX: hard-coded value
125 . getarg cols \\$@\" from here string `args' contains the rest of \\$@
127 . nr t*cols\\n[t*#] \\n[t*cols]
129 . ie \B
\a\\*[cols]
\a \
130 . nr t*cols\\n[t*#] \\*[cols]
132 . tm \\n[.F]:\\n[.c]: Invalid number of columns value `\\*[cols]'.
135 . getarg cpd \\*[args] \" cell padding
137 . nr t*cpd\\n[t*#] \\n[t*cpd]
139 . ie \B
\a\\*[cpd]
\a \
140 . nr t*cpd\\n[t*#] \\*[cpd]
142 . tm \\n[.F]:\\n[.c]: Invalid cell padding value `\\*[cpd]'.
145 . getarg csp \\*[args] \" cell spacing
147 . nr t*csp\\n[t*#] \\n[t*csp]
149 . ie \B
\a\\*[csp]
\a \
150 . nr t*csp\\n[t*#] \\*[csp]
152 . tm \\n[.F]:\\n[.c]: Invalid cell spacing value `\\*[csp]'.
155 . getarg border \\*[args] \" border thickness
156 . ie "\\*[border]"=" \
159 . ie "\\*[border]"" \
160 . nr t*b\\n[t*#] \\n[t*b]
162 . ie \B
\a\\*[border]
\a \
163 . nr t*b\\n[t*#] \\*[border]
165 . tm \\n[.F]:\\n[.c]: Invalid border thickness value `\\*[border]'.
168 . getarg bc \\*[args] \" border color
169 . ds t*bc\\n[t*#] \\*[t*bc]\"
172 . ds t*bc\\n[t*#] \\*[bc]\"
175 . ds t*bc\\n[t*#] =\"
177 . tm \\n[.F]:\\n[.c]: Invalid border color `\\*[bc]'.
183 . ds t*bc\\n[t*#] \\*[t*bc]\"
185 . ds t*bc\\n[t*#] \\*[bc]\"
188 . getarg width \\*[args] \" table/col widths
189 . if "\\*[width]"=" \
192 . nr b/2\\n[t*#] (\\n[t*b\\n[t*#]] / 2)\" shortcut
193 . nr cscp\\n[t*#] (\\n[t*csp\\n[t*#]] + \\n[t*cpd\\n[t*#]])\" aux. register
195 . getarg height \\*[args] \" table outline height
196 . ie "\\*[height]"" \
197 . nr t*height\\n[t*#] 0
199 . ie \B
\a\\*[height]
\a \
200 . nr t*height\\n[t*#] (\\*[height] \
201 - ((2 * \\n[cscp\\n[t*#]]) \
202 + (3 * \\n[b/2\\n[t*#]])))
204 . tm \\n[.F]:\\n[.c]: Invalid height value `\\*[height]'.
207 . t*cl \\*[width] \" get cell widths and offsets
208 . t*args \\n[t*#] \" look for common arguments
210 . getarg tal \\*[args] \" table horizontal alignment
212 . ds tal \\*[t*tal]\"
214 . nr in\\n[t*#] \\n[.i]
217 . nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]]/2 + \\n[.i])
220 . nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]] + \\n[.i])
222 . tmc \\n[.F]:\\n[.c]: Invalid horizontal table alignment `\\*[tal]':
223 . tm1 " must be `l', `c' or `r'.
226 . nr t*r#\\n[t*#] 0 \" initialize row index
233 .\" CPTN: optional table caption
240 . if \\n[t*r#\\n[t*#]] \{\
241 . tmc \\n[.F]:\\n[.c]: Invalid placement of `.CPTN';
242 . tm1 " must be called immediately after `.TBL'.
247 . ds args\\n[t*#] "\\*[args]\"
249 . index "\\*[args]" .TR
251 . ds *a\\n[t*#] "\\*[args]\"
252 . substring args\\n[t*#] 0 \\n[index]
253 . substring *a\\n[t*#] \\n[index]-2 -1
258 . ie "\\*[val]"b" \{\
260 . *CPTN \\*[args\\n[t*#]]
265 . ll (\\n[ll\\n[t*#]]u + \\n[in\\n[t*#]]u)
266 . in \\n[in\\n[t*#]]u
269 . P1 \\*[args\\n[t*#]]
282 .\" predecessor: TBL, CPTN, text, TD or ETB
287 . tm \\n[.F]:\\n[.c]: Table row (.TR) without preceding table start (.TBL).
291 . \" finish previous data cell, if any
292 . if \\n[t*r#\\n[t*#]] \
293 . t*dntr 1 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
295 . nr t*r#\\n[t*#] +1 \" row number in this table
296 . ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" table row identifier
298 . nr c#\\*[#t#r] 0 1 \" clear cell counter
299 . nr dntr\\*[#t#r] 0 1 \" clear accumulated row height
302 . ie "\\*[height]"" \
303 . nr t*height\\*[#t#r] 0
305 . ie \B
\a\\*[height]
\a \
306 . nr t*height\\*[#t#r] \\*[height]
308 . tm \\n[.F]:\\n[.c]: Invalid table row height `\\*[height]'.
311 . \" If there is a TR with height `height', the total height of the table
312 . \" is too high by 3/2 b, independent of the number of TR with `height'.
313 . t*args \\*[#t#r] \\n[t*#] \" look for common arguments
319 .\" TH: optional table header cell
320 .\" predecessor: text, TD or TR
321 .\" successor: text, TD, TR, TBL or ETB
323 .\" cell content bolded and horizontally and vertically centered,
331 . getarg val \\*[args]
335 . getarg fst \\*[args]
339 . TD hal=\\*[hal] val=\\*[val] fst=\\*[fst] \\*[args]
343 .\" TD: table data cell
344 .\" predecessor: text, TD or TR
345 .\" successor: text, TD, TR, TBL or ETB
348 . \" finish previous data cell -- note the use of \E
349 . t*dntr 0 \\n[c#\\*[#t#r]]-1 \En[c#\\*[#t#r]] \\*[*#trc*]
351 . ds *#trc* \\*[#t#r]*\\n[c#\\*[#t#r]]\" table cell identifier
352 . \" (<level>*<row>*<column>)
354 . getarg rowspan \\$@
356 . if !"\\*[rowspan]"" \{\
357 . ie \B
\a\\*[rowspan]
\a \{\
358 . nr rowspan (\\*[rowspan] >? 1)
359 . nr *rsp*\\*[*#trc*] (\\n[rowspan] - 1)
362 . tm \\n[.F]:\\n[.c]: Invalid value of `rowspan' keyword.
365 . getarg colspan \\*[args]
367 . if !"\\*[colspan]"" \{\
368 . ie \B
\a\\*[colspan]
\a \
369 . nr colspan (\\*[colspan] >? 1)
371 . tm \\n[.F]:\\n[.c]: Invalid value of `colspan' keyword.
374 . t*args \\*[#trc] \\*[#t#r] \" look for common arguments
376 . nr in\\*[#trc] \\n[in\\n[t*#]*\\n[c#\\*[#t#r]]]
377 . nr *cl \\n[cll\\n[t*#]*\\n[c#\\*[#t#r]]]
379 . nr *r \\n[t*r#\\n[t*#]]
381 . if (\\n[rowspan] - 1) \
382 . while (\\n+[*] <= \\n[rowspan]) \{\
383 . nr rspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
385 . nr cspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
390 . nr *c \\n[c#\\*[#t#r]]
392 . if (\\n[colspan] - 1) \{\
393 . nr vline\\*[*#trc*] 0-1 \" set `no vl' flag
395 . while (\\n+[*] <= \\n[colspan]) \{\
397 . nr *cl +(2 * \\n[cscp\\n[t*#]] \
399 + \\n[cll\\n[t*#]*\\n[*c]])
404 . if (\\n[c#\\n[t*#]*\\n[t*r#\\n[t*#]]] > \\n[t*cols\\n[t*#]]) \{\
407 . if (\\n[c#\\*[#t#r]] == 1) \{\
411 . tmc \\n[.F]:\\n[.c]: There \\*[*] \\n[c#\\*[#t#r]] table \\*[**] (.TD)
414 . if (\\n[t*cols\\n[t*#]] == 1) \
416 . tm1 " but only \\n[t*cols\\n[t*#]] \\*[*] expected.
419 . length * \\n[.F]:\\n[.c]:
424 . tm1 "\\*[*] Remaining .TDs and its contents are ignored.
426 . di *t*dummy* \" bypass superfluous input
430 . di t*\\*[#trc] \" open cell diversion and set locals
432 . nr cll\\*[#trc] \\n[*cl]
434 . nr *cl\\n[t*#] \\n[.l]
435 . gcolor \\*[t*fgc\\*[#trc]]
436 . ad \\*[t*hal\\*[#trc]]
437 . fam \\*[t*ff\\*[#trc]]
438 . ft \\*[t*fst\\*[#trc]]
439 . pv \\*[t*fsz\\*[#trc]]
445 .\" ETB: end of table
446 .\" predecessor: text, TD or ETB
447 .\" successor: text, TD, TR or TBL
450 . if !\\n[t*r#\\n[t*#]] \{\
451 . tmc \\n[.F]:\\n[.c]: Each table (.TBL)
452 . tm1 " should contain at least one table row (.TR)!
455 . tmc \\n[.F]:\\n[.c]: Table end (.ETB)
456 . tm1 " without corresponding table start (.TBL)!
459 . ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" refresh table row identifier
460 . t*dntr 2 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
462 . t*divs \" print this table
464 . sp \\n[b/2\\n[t*#]]u
468 . ll \\n[*cl\\n[t*#]]u \" restore ll outside this table
469 . in 0 \" reset indent
470 . gcolor \\*[t*m\\n[t*#]] \" reset previous fgc
477 . ie "\\*[hold]"" \{\
478 . ie (\\n[.t] - \\n[dn]) \
481 . rn t*tbl0 t*tbl\\n[t*numb]
482 . ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[dn]\"
486 . rn t*tbl0 t*hold\\n+[t*numb]
487 . tm \\n[.F]:\\n[.c]: Table t*hold\\n[t*numb] held.
488 . ds t*held \\*[t*held] t*hold\\n[t*numb] \\n[dn]\"
491 . ev \" restore previous environment
498 .\" *****************************************************************
499 .\" * Following the definition of five utility macros *
500 .\" * special to hdtbl. *
501 .\" * Other utility macros common to hdtbl and hdgroff *
502 .\" * are defined in the file hdmisc.tmac. *
503 .\" *****************************************************************
507 .\" print the next [n] held table[s].
508 .\" Don't call it within a table!
509 .\" If the table is higher than the remaining space
510 .\" on the page, the table is printed on the next page.
513 . if \\n[t*r#\\n[t*#]] \{\
514 . tmc \\n[.F]:\\n[.c]: Invalid placement of `.t*free' within a table;
515 . tm1 " it must be called outside of any table.
519 . if "\\*[t*held]"" \{\
520 . tm \\n[.F]:\\n[.c]: No held tables.
525 . while !""\\*[t*held]" \{\
529 . ie (\\n[.t] - \\n[*]) \{\
535 . rn \\*[*] t*tbl\\n+[t*numb]
536 . ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[*]\"
539 . if !(\\n-[**] - 1) \
545 .\" The main utility macro for tables:
546 .\" If a table is closed by ETB, this macro is called. It
547 .\" processes one complete table, i.e., all the table cell
548 .\" diversions, paints the cell backgrounds, draws
549 .\" horizontal and vertical table lines and the table border.
551 .\" Nested tables are processed from inside to outside.
554 . ll (\\n[l]u + 1c) \" avoid warning `can't break line'
557 . nr b/2 \\n[b/2\\n[t*#]] \" some abbreviations
558 . nr cscp \\n[cscp\\n[t*#]]
559 . nr cscpb (\\n[b/2] + \\n[cscp])
561 . nr topdiv (\\n[.d] + \\n[b/2] - \\n[cscp])\" top of cell diversion
562 . nr cscpb2 (\\n[b/2] / 2 + \\n[cscp])
565 . \" outer loop for rows
566 . while (\\n+[#r] <= \\n[t*r#\\n[t*#]]) \{\
567 . \" TODO: insert code here for multipage tables
569 . nr topdiv +(\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
571 . \" if table still smaller than specified table height, increase it
572 . if ((\\n[#r] == \\n[t*r#\\n[t*#]]) & \\n[t*height\\n[t*#]]) \
573 . nr dntr\\n[t*#]*\\n[#r] (\\n[cscpb] \
574 + \\n[toptbl\\n[t*#]] \
575 + \\n[t*height\\n[t*#]] \
576 - (\\n[topdiv] >? \\n[dntr\\n[t*#]*\\n[#r]]))
579 . \" inner loop for cells
580 . while (\\n+[#c] <= \\n[t*cols\\n[t*#]]) \{\
581 . ds #trc \\n[t*#]*\\n[#r]*\\n[#c]\"
582 . \" continue if the diversion is empty
583 . if !d t*\\*[#trc] \
587 . in (\\n[in\\n[t*#]]u + \\n[in\\*[#trc]]u)\" cell offset
588 . nr $1 \\n[dntr\\n[t*#]*\\n[#r]] \" cell height
590 . \" if we have spanned rows, calculate resulting row height
591 . \" and position of lower horizontal line
592 . if \\n[*rsp*\\*[#trc]] \{\
594 . nr rspan\\*[#trc] 0-1 \" set `no hl' flag
595 . nr corr (\\n[dn\\*[#trc]] - \\n[dntr\\n[t*#]*\\n[#r]])
597 . \" clear row span flags in following rows and update row height
598 . while \\n[*rsp*\\*[#trc]] \{\
599 . nr *rsp*\\*[#trc] -1
600 . nr rspan\\n[t*#]*\\n+[*]*\\n[#c] 0
601 . nr ** (\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
606 . if (\\n-[*] == \\n[t*r#\\n[t*#]]) \
607 . nr $1 ((\\n[t*height\\n[t*#]] \
609 + \\n[toptbl\\n[t*#]] \
612 . nr dntr\\n[t*#]*\\n[*] +(\\n[corr] >? 0)
615 . \" paint cell background
616 . nr * (2 * \\n[t*cpd\\n[t*#]] + \\n[cll\\*[#trc]])\" background width
617 . nr $1 (\\n[$1] >? \\n[dn\\*[#trc]])\" cell height
619 . if !"\\*[t*bgc\\*[#trc]]"=" \{\
620 . nop \h'\\n[t*csp\\n[t*#]]u'\
621 \M[\\*[t*bgc\\*[#trc]]]\
622 \v'(-.67v - \\n[t*cpd\\n[t*#]]u)'\
624 0 (2u * \\n[t*cpd\\n[t*#]]u + \\n[$1]u) \
630 . \" *** horizontal and vertical single or double lines ***
631 . \" double and single lines have the same thickness;
632 . \" the double lines' distance is the line thickness.
634 . \" `border=x': horizontal/vertical lines x/2 thick, minimum .1n
635 . \" `border=0': no border; horizontal/vertical lines .1n thick
636 . \" `border=': neither border nor horizontal/vertical lines
638 . nr *t (.1n >? \\n[b/2]) \" thickness of hl/vl; min. .1n
641 . \" check for vertical and horizontal lines
642 . if (1 + \\n[t*b\\n[t*#]]) \{\
643 . if !"\\*[t*bc\\n[t*#]]"=" \{\
644 . \" draw horizontal line between this cell and the one below
645 . if (\\n[t*r#\\n[t*#]] - \\n[#r] + \\n[rspan\\*[#trc]]) \{\
646 . if !"\\*[t*hl\\*[#trc]]"=" \{\
648 . nr * (\\n[cscp] + \\n[cscpb] + \\n[cll\\*[#trc]])
649 . nop \X'\*[g] 1 setlinecap'\
650 \h'(-\\n[cscpb2]u - \\n[*t]u)'\
651 \v'(\\n[cscpb2]u - .67v)'\
652 \m[\\*[t*bc\\n[t*#]]]\
655 . ie "\\*[t*hl\\*[#trc]]"d" \
662 . nop \D'l \\n[*]u 0'\
665 . sp (-\\n[$1]u - 1v)
668 . nr rspan\\*[#trc] 0
670 . \" draw vertical line between this cell and the one to the right
671 . if (\\n[t*cols\\n[t*#]] - \\n[#c] + \\n[vline\\*[#trc]]) \{\
672 . if !"\\*[t*vl\\*[#trc]]"=" \{\
673 . nop \X'\*[g] 1 setlinecap'\
674 \v'(-\\n[cscpb2]u - .67v)'\
675 \m[\\*[t*bc\\n[t*#]]]\
676 \h'(\\n[cscpb2]u - \\n[*t]u + \\n[cll\\*[#trc]]u)'\c
678 . ie "\\*[t*vl\\*[#trc]]"d" \
681 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
683 \D'l 0 -(2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
686 . nop \D't \\n[*t]u'\
687 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
692 . nr vline\\*[#trc] 0
694 . \" vert. cell content alignment
697 . ie "\\*[t*val\\*[#trc]]"m" \
698 . nr ** ((\\n[$1] - \\n[dn\\*[#trc]]) / 2)\" val=m
700 . if "\\*[t*val\\*[#trc]]"b" \
701 . nr ** (\\n[$1] - \\n[dn\\*[#trc]])\" val=b
703 . sp \\n[**]u \" vertical content position
705 . \" finally output the diversion
711 . \" draw the box border
712 . in \\n[in\\n[t*#]]u
713 . nr ** (\\n[topdiv] + \\n[dntr\\n[t*#]*\\n-[#r]])
715 . if \\n[t*b\\n[t*#]] \{\
716 . sp |(\\n[toptbl\\n[t*#]]u + \\n[b/2]u)
717 . nr $1 (\\n[toptbl\\n[t*#]] - \\n[**] - \\n[cscp])
718 . nr * (\\n[ll\\n[t*#]] - \\n[t*b\\n[t*#]])
720 . if !"\\*[t*bc\\n[t*#]]"=" \
721 . nop \X'\*[g] 0 setlinejoin 2 setlinecap'\
724 \m[\\*[t*bc\\n[t*#]]]\
725 \D't \\n[t*b\\n[t*#]]u'\
733 . sp |(\\n[**]u + \\n[cscpb]u)
738 .\" Utility macro: .t*cl [width1 [width2 [...]]]
740 .\" Calculate cell widths, table width, and cell offsets.
742 . nr t*cols\\n[t*#] (\\n[.$] >? \\n[t*cols\\n[t*#]])
743 . nr ll\\n[t*#] 0 \" accumulated cell widths
744 . nr ** (\\n[.l] / \\n[t*cols\\n[t*#]])\" width for remaining cells
745 . nr * 0 1 \" counter
747 . \" while-loop: Parse user arguments to get each cell's width.
748 . while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
750 . if !"\\$[\\n[*]]"" \{\
751 . \" check for `%' pseudo scaling indicator
755 . ds ** \\$[\\n[*]]\"
758 . nr $\\n[*] (\\*[**] * \\n[.l] / 100)
760 . tm \\n[.F]:\\n[.c]: Invalid relative cell width `\\*[**]%'.
763 . ie \B
\a\\$[\\n[*]]
\a \
764 . nr $\\n[*] \\$[\\n[*]]
766 . tm \\n[.F]:\\n[.c]: Invalid cell width `\\$[\\n[*]]'.
769 . nr ll\\n[t*#] +\\n[$\\n[*]]
773 . if (\\n[ll\\n[t*#]] > \\n[.l]) \
774 . tm \\n[.F]:\\n[.c]: Table width larger than column width.
776 . nr ** (0 >? \\n[t*b\\n[t*#]])
779 . \" second while loop: Compute final cell widths.
780 . while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
781 . \" Remove border width, if any.
782 . if \\n[t*b\\n[t*#]] \{\
783 . \" cell_width := cell_width * (length - 1.5*border) / length
784 . nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
785 . nr *** (\\n[ll\\n[t*#]] / 2)
786 . \" avoid multiplication overflow
787 . mult31by31 $\\n[*] #* ****
788 . add31to62 *** **** ****
789 . div62by31 **** ll\\n[t*#] $\\n[*]
792 . \" Get cell widths without padding, spacing, and separator line.
793 . nr cll\\n[t*#]*\\n[*] (\\n[$\\n[*]] \
794 - (2 * \\n[cscp\\n[t*#]]) \
797 . \" Check whether value is non-positive.
798 . if !\\n[cll\\n[t*#]*\\n[*]] \{\
799 . nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
800 . nr *** (\\n[#*] / 2)
801 . nr *h (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])
802 . mult31by31 *h ll\\n[t*#] ****
803 . add31to62 *** **** ****
804 . div62by31 **** #* *h
806 . nr *** (\\n[*] % 10)
807 . if d nth-\\n[***] \
808 . ds * \\n[*]\\*[nth-\\n[***]]\"
809 . tmc \\n[.F]:\\n[.c]: The \\*[*] width value (\\$\\n[*]) is too small.
810 . tm1 " It should be greater than \\n[*h].
813 . nr in\\n[t*#]*\\n[*] \\n[**] \" cell offset
814 . nr ** +\\n[$\\n[*]]
819 .\" Utility macro: .t*dntr <origin> <cell position> ? <cell ID>
821 .\" Close TD diversion, make some calculations, and set
822 .\" some help strings and registers. <origin> is 0, 1,
823 .\" or 2 if the call of .t*dntr occurs in .TD, .TR, or
824 .\" .ETB, respectively.
826 . nr dn 0 \" reset diversion height
827 . br \" finish cell data
829 . if "\\n[.z]"*t*dummy*" \
832 . ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" refresh table row identifier
834 . if \\n[c#\\*[#t#r]] \{\
835 . di \" close diversion
836 . nr dn\\$4 \\n[dn] \" save height of this cell
837 . if !\\n[rspan\\*[#trc]] \{\
838 . \" update row height if not in a row span
839 . nr dntr\\*[#t#r] (\\n[dntr\\*[#t#r]] >? \\n[dn])
841 . nr dntr\\*[#t#r] ((\\n[t*height\\*[#t#r]] \
842 - (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])) \
843 >? \\n[dntr\\*[#t#r]])
849 . \" update column span registers
850 . while (\\n+[*] <= \\$3) \{\
851 . if r cspan\\*[#t#r]*\\n[*] \
852 . nr c#\\*[#t#r] +\\n[cspan\\*[#t#r]*\\n[*]]
853 . nr cspan\\*[#t#r]*\\n[*] 0
856 . ds #trc \\*[#t#r]*\\n[c#\\*[#t#r]]\"
858 . \" only check for cell underflow if called by .TR or .ETB
859 . if (\\$1 & (\\n[c#\\*[#t#r]] <= \\n[t*cols\\n[t*#]])) \{\
862 . if (\\n-[c#\\*[#t#r]] == 1) \{\
866 . tmc \\n[.F]:\\n[.c]: There \\*[*] only \\n[c#\\*[#t#r]] \\*[**]
868 . nr * \\n[t*r#\\n[t*#]]
870 . nr *** (\\n[*] % 10)
871 . if d nth-\\n[***] \
872 . ds * \\n[*]\\*[nth-\\n[***]]\"
873 . tmc " in the \\*[*] row
876 . if (\\n[t*cols\\n[t*#]] == 1) \
878 . tm1 " but \\n[t*cols\\n[t*#]] \\*[*] expected.
883 .\" Utility-macro: .t*args level_1 [level_2]
885 .\" Get the arguments common to TBL, TR, and TD for the level
886 .\" in argument 1, using default values from the level in
887 .\" argument 2. If argument 2 is missing, use the global
891 . ds t*bgc\\$1 \\*[t*bgc\\$2]\"
892 . ds t*fgc\\$1 \\*[t*fgc\\$2]\"
893 . ds t*hl\\$1 \\*[t*hl\\$2]\"
894 . ds t*vl\\$1 \\*[t*vl\\$2]\"
895 . ds t*hal\\$1 \\*[t*hal\\$2]\"
896 . ds t*val\\$1 \\*[t*val\\$2]\"
897 . ds t*ff\\$1 \\*[t*ff\\$2]\"
898 . ds t*fst\\$1 \\*[t*fst\\$2]\"
899 . ds t*fsz\\$1 \\*[t*fsz\\$2]\"
904 . getarg bgc \\*[args] \" background color
905 . if !"\\*[bgc]"" \{\
907 . ds t*bgc\\$1 \\*[bgc]\"
912 . tm \\n[.F]:\\n[.c]: Invalid background color `\\*[bgc]'.
917 . getarg fgc \\*[args] \" foreground color
918 . if !"\\*[fgc]"" \{\
920 . ds t*fgc\\$1 \\*[fgc]\"
925 . tm \\n[.F]:\\n[.c]: Invalid foreground color `\\*[fgc]'.
930 . getarg hl \\*[args] \" horizontal line between cells
932 . ds t*hl\\$1 \\*[hl]\"
936 . getarg vl \\*[args] \" vertical line between cells
938 . ds t*vl\\$1 \\*[vl]\"
942 . getarg hal \\*[args] \" horizontal table cell alignment
943 . if !"\\*[hal]"" \{\
944 . index bcrl \\*[hal]
946 . ds t*hal\\$1 \\*[hal]\"
948 . tmc \\n[.F]:\\n[.c]: Invalid horizontal alignment `\\*[hal]':
949 . tm1 " must be `b', `c', `l' or `r'.
954 . getarg val \\*[args] \" vertical table cell alignment
955 . if !"\\*[val]"" \{\
958 . ds t*val\\$1 \\*[val]\"
960 . tmc \\n[.F]:\\n[.c]: Invalid vertical alignment `\\*[val]':
961 . tm1 " must be `t', `m' or `b'.
966 . getarg ff \\*[args] \" font family
968 . ds t*ff\\$1 \\*[ff]\"
972 . getarg fst \\*[args] \" font style
974 . ds t*fst\\$1 \\*[fst]\"
978 . getarg fsz \\*[args] \" font size and spacing factor
980 . ds t*fsz\\$1 \\*[fsz]\"
987 . while !""\\*[t*kept]" \{\
990 . if (\\n[*] - \\n[**]) \{\
991 . tm \\n[.F]:\\n[.c]: Table \\*[*] higher than page -- ignored!
995 . if (\\n[*] - \\n[.t]) \{\
996 . ds t*kept \\n[*] \\*[t*kept]\"
997 . ds t*kept \\*[*] \\*[t*kept]\"
998 . tmc \\n[.F]:\\n[.c]: Remaining table(s),
999 . tm1 " because not all fit onto this page.