summaryrefslogtreecommitdiffstats
path: root/contrib/hdtbl/hdtbl.tmac
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/hdtbl/hdtbl.tmac')
-rw-r--r--contrib/hdtbl/hdtbl.tmac1003
1 files changed, 1003 insertions, 0 deletions
diff --git a/contrib/hdtbl/hdtbl.tmac b/contrib/hdtbl/hdtbl.tmac
new file mode 100644
index 0000000..422ede7
--- /dev/null
+++ b/contrib/hdtbl/hdtbl.tmac
@@ -0,0 +1,1003 @@
+.ig
+
+hdtbl.tmac
+
+This file is part of groff, the GNU roff type-setting system.
+
+Copyright (C) 2005-2020 Free Software Foundation, Inc.
+written by Joachim Walsdorff <Joachim.Walsdorff@urz.uni-heidelberg.de>.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+..
+.
+.
+.\" *****************************************************************
+.\" * hdtbl - Heidelberger table macros *
+.\" * Vers. 0.91 December 2005 *
+.\" *****************************************************************
+.
+.if d TBL \
+. nx
+.
+.mso hdmisc.tmac
+.mso 62bit.tmac
+.
+.
+.\" *****************************************************************
+.\" * default values for some arguments *
+.\" *****************************************************************
+.
+.ds t*hl s\"
+.ds t*vl s\"
+.ds t*tal l\"
+.ds t*hal b\"
+.ds t*val t\"
+.ds t*ff \\n[.fam]\"
+.ds t*fst \\n[.f]\"
+.ds t*fsz 1 1\"
+.ds t*fgc red4\"
+.ds t*bgc bisque\"
+.ds t*bc red4\"
+.nr t*cpd .5n
+.nr t*csp .5n
+.nr t*b .1n
+.nr t*cols 1
+.nr t*v \n[.v]
+.nr t*s \n[.ps]
+.nr t*hy \n[.hy]
+.nr t*l \n[.ll]
+.
+.
+.\" defaults for table captions
+.nr t*cptn 0 1
+.ds t*cptn "".sp .4" \
+ ".t*pv 1.0 1.0" \
+ ".ad l" \
+ "\m[\\*[t*fgc]]Table \\n+[t*cptn]:\0\k*\c"\"
+.
+.
+.\" for better error messages
+.ds nth-1 st\"
+.ds nth-2 nd\"
+.ds nth-3 rd\"
+.
+.\" initialization of various registers
+.nr t*# 0 \" table nesting level
+.nr t*numb 0 1 \" held table diversion #
+.
+.ds *#trc*
+.
+.
+.\" *****************************************************************
+.\" * The four base macros and the two optional macros *
+.\" *****************************************************************
+.
+.ie n \
+. ds g tty:\"
+.el \
+. ds g ps: exec\"
+.
+.\" TBL: table start
+.\" predecessor: text, TD or ETB
+.\" successor: CPTN or TR
+.de TBL
+. ds t*m\\n[t*#] \\n[.m]\"
+. ie \\n[t*#] \
+. br
+. el \{\
+. ds * \\n[.ev]\"
+. ev t*tbl
+. evc \\*[*]
+. di t*tbl0
+. sp .4 \" XXX: hard-coded value
+. nr t*i \\n[.i]
+. ll -\\n[.i]u
+. in 0
+. \}
+. nr t*# +1
+.
+. \" Save current location for error checking at end
+. ds t*FN \\[.F]\"
+. ds t*LN \\[.c]\"
+.
+. t*getarg cols \\$@\" from here string 'args' contains the rest of \\$@
+. ie "\\*[cols]"" \
+. nr t*cols\\n[t*#] \\n[t*cols]
+. el \{\
+. ie \B\\*[cols] \
+. nr t*cols\\n[t*#] \\*[cols]
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid number of columns value '\\*[cols]'.
+. \}
+.
+. t*getarg cpd \\*[args] \" cell padding
+. ie "\\*[cpd]"" \
+. nr t*cpd\\n[t*#] \\n[t*cpd]
+. el \{\
+. ie \B\\*[cpd] \
+. nr t*cpd\\n[t*#] \\*[cpd]
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid cell padding value '\\*[cpd]'.
+. \}
+.
+. t*getarg csp \\*[args] \" cell spacing
+. ie "\\*[csp]"" \
+. nr t*csp\\n[t*#] \\n[t*csp]
+. el \{\
+. ie \B\\*[csp] \
+. nr t*csp\\n[t*#] \\*[csp]
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid cell spacing value '\\*[csp]'.
+. \}
+.
+. t*getarg border \\*[args] \" border thickness
+. ie "\\*[border]"=" \
+. nr t*b\\n[t*#] 0-1
+. el \{\
+. ie "\\*[border]"" \
+. nr t*b\\n[t*#] \\n[t*b]
+. el \{\
+. ie \B\\*[border] \
+. nr t*b\\n[t*#] \\*[border]
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid border thickness value '\\*[border]'.
+. \}\}
+.
+. t*getarg bc \\*[args] \" border color
+. ds t*bc\\n[t*#] \\*[t*bc]\"
+. if !"\\*[bc]"" \{\
+. ie m\\*[bc] \
+. ds t*bc\\n[t*#] \\*[bc]\"
+. el \{\
+. ie "\\*[bc]"=" \
+. ds t*bc\\n[t*#] =\"
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid border color '\\*[bc]'.
+. \}\}
+. ie "\\*[bc]"=" \
+. ds t*bc\\n[t*#]
+. el \{\
+. ie "\\*[bc]"" \
+. ds t*bc\\n[t*#] \\*[t*bc]\"
+. el \
+. ds t*bc\\n[t*#] \\*[bc]\"
+. \}
+.
+. t*getarg width \\*[args] \" table/col widths
+. if "\\*[width]"=" \
+. ds width
+.
+. nr b/2\\n[t*#] (\\n[t*b\\n[t*#]] / 2)\" shortcut
+. nr cscp\\n[t*#] (\\n[t*csp\\n[t*#]] + \\n[t*cpd\\n[t*#]])\" aux. register
+.
+. t*getarg height \\*[args] \" table outline height
+. ie "\\*[height]"" \
+. nr t*height\\n[t*#] 0
+. el \{\
+. ie \B\\*[height] \
+. nr t*height\\n[t*#] (\\*[height] \
+ - ((2 * \\n[cscp\\n[t*#]]) \
+ + (3 * \\n[b/2\\n[t*#]])))
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid height value '\\*[height]'.
+. \}
+.
+. t*cl \\*[width] \" get cell widths and offsets
+. t*args \\n[t*#] \" look for common arguments
+.
+. t*getarg tal \\*[args] \" table horizontal alignment
+. if "\\*[tal]"" \
+. ds tal \\*[t*tal]\"
+. ie "\\*[tal]"l" \
+. nr in\\n[t*#] \\n[.i]
+. el \{\
+. ie "\\*[tal]"c" \
+. nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]]/2 + \\n[.i])
+. el \{\
+. ie "\\*[tal]"r" \
+. nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]] + \\n[.i])
+. el \{\
+. tmc \\n[.F]:\\n[.c]: Invalid horizontal table alignment '\\*[tal]':
+. tm1 " must be 'l', 'c' or 'r'.
+. \}\}\}
+.
+. nr t*r#\\n[t*#] 0 \" initialize row index
+. mk toptbl\\n[t*#]
+.
+. t*P1 \\*[args]
+..
+.
+.
+.\" CPTN: optional table caption
+.\" predecessor: TBL
+.\" successor: TR
+.de CPTN
+. ft 1
+.
+. if "\\$0"CPTN" \
+. if \\n[t*r#\\n[t*#]] \{\
+. tmc \\n[.F]:\\n[.c]: Invalid placement of '.CPTN';
+. tm1 " must be called immediately after '.TBL'.
+. return
+. \}
+.
+. t*getarg val \\$@
+. ds args\\n[t*#] "\\*[args]\"
+.
+. t*index "\\*[args]" .TR
+. ie \\n[t*index] \{\
+. ds *a\\n[t*#] "\\*[args]\"
+. substring args\\n[t*#] 0 \\n[t*index]
+. substring *a\\n[t*#] \\n[t*index]-2 -1
+. \}
+. el \
+. ds *a\\n[t*#]
+.
+. ie "\\*[val]"b" \{\
+. de t*cptn\\n[t*#]
+. *CPTN \\*[args\\n[t*#]]
+. rm t*cptn\\n[t*#]
+\\..
+. \}
+. el \{\
+. ll (\\n[ll\\n[t*#]]u + \\n[in\\n[t*#]]u)
+. in \\n[in\\n[t*#]]u
+. t*P1 \\*[t*cptn]
+' in +\\n[*]u
+. t*P1 \\*[args\\n[t*#]]
+. t*pv 1 1
+. in
+. mk toptbl\\n[t*#]
+. \}
+.
+. t*P1 \\*[*a\\n[t*#]]
+..
+.
+.als *CPTN CPTN
+.
+.
+.\" TR: table row
+.\" predecessor: TBL, CPTN, text, TD or ETB
+.\" successor: TD
+.de TR
+. ft 1
+. if !\\n[t*#] \{\
+. tm \\n[.F]:\\n[.c]: Table row (.TR) without preceding table start (.TBL).
+. return
+. \}
+.
+. \" finish previous data cell, if any
+. if \\n[t*r#\\n[t*#]] \
+. t*dntr 1 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
+.
+. nr t*r#\\n[t*#] +1 \" row number in this table
+. ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" table row identifier
+. \" (<level>*<row>)
+. nr c#\\*[#t#r] 0 1 \" clear cell counter
+. nr dntr\\*[#t#r] 0 1 \" clear accumulated row height
+.
+. t*getarg height \\$@
+. ie "\\*[height]"" \
+. nr t*height\\*[#t#r] 0
+. el \{\
+. ie \B\\*[height] \
+. nr t*height\\*[#t#r] \\*[height]
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid table row height '\\*[height]'.
+. \}
+.
+. \" If there is a TR with height 'height', the total height of the table
+. \" is too high by 3/2 b, independent of the number of TR with 'height'.
+. t*args \\*[#t#r] \\n[t*#] \" look for common arguments
+.
+. t*P1 \\*[args]
+..
+.
+.
+.\" TH: optional table header cell
+.\" predecessor: text, TD or TR
+.\" successor: text, TD, TR, TBL or ETB
+.\"
+.\" cell content bolded and horizontally and vertically centered,
+.\" else like .TD
+.de TH
+. ft 1
+. t*getarg hal \\$@
+. if "\\*[hal]"" \
+. ds hal c\"
+.
+. t*getarg val \\*[args]
+. if "\\*[val]"" \
+. ds val m\"
+.
+. t*getarg fst \\*[args]
+. if "\\*[fst]"" \
+. ds fst B\"
+.
+. TD hal=\\*[hal] val=\\*[val] fst=\\*[fst] \\*[args]
+..
+.
+.
+.\" TD: table data cell
+.\" predecessor: text, TD or TR
+.\" successor: text, TD, TR, TBL or ETB
+.de TD
+. ft 1
+. \" finish previous data cell -- note the use of \E
+. t*dntr 0 \\n[c#\\*[#t#r]]-1 \En[c#\\*[#t#r]] \\*[*#trc*]
+.
+. ds *#trc* \\*[#t#r]*\\n[c#\\*[#t#r]]\" table cell identifier
+. \" (<level>*<row>*<column>)
+.
+. t*getarg rowspan \\$@
+. nr rowspan 1
+. if !"\\*[rowspan]"" \{\
+. ie \B\\*[rowspan] \{\
+. nr rowspan (\\*[rowspan] >? 1)
+. nr *rsp*\\*[*#trc*] (\\n[rowspan] - 1)
+. \}
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid value of 'rowspan' keyword.
+. \}
+.
+. t*getarg colspan \\*[args]
+. nr colspan 1
+. if !"\\*[colspan]"" \{\
+. ie \B\\*[colspan] \
+. nr colspan (\\*[colspan] >? 1)
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid value of 'colspan' keyword.
+. \}
+.
+. t*args \\*[#trc] \\*[#t#r] \" look for common arguments
+.
+. nr in\\*[#trc] \\n[in\\n[t*#]*\\n[c#\\*[#t#r]]]
+. nr *cl \\n[cll\\n[t*#]*\\n[c#\\*[#t#r]]]
+. nr * 0 1
+. nr *r \\n[t*r#\\n[t*#]]
+.
+. if (\\n[rowspan] - 1) \
+. while (\\n+[*] <= \\n[rowspan]) \{\
+. nr rspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
+. if (\\n[*] > 1) \
+. nr cspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
+. nr *r +1
+. \}
+.
+. nr * 1 1
+. nr *c \\n[c#\\*[#t#r]]
+.
+. if (\\n[colspan] - 1) \{\
+. nr vline\\*[*#trc*] 0-1 \" set 'no vl' flag
+.
+. while (\\n+[*] <= \\n[colspan]) \{\
+. nr *c +1
+. nr *cl +(2 * \\n[cscp\\n[t*#]] \
+ + \\n[b/2\\n[t*#]] \
+ + \\n[cll\\n[t*#]*\\n[*c]])
+. nr c#\\*[#t#r] +1
+. \}
+. \}
+.
+. if (\\n[c#\\n[t*#]*\\n[t*r#\\n[t*#]]] > \\n[t*cols\\n[t*#]]) \{\
+. ds * are\"
+. ds ** columns\"
+. if (\\n[c#\\*[#t#r]] == 1) \{\
+. ds * is\"
+. ds ** column\"
+. \}
+. tmc \\n[.F]:\\n[.c]: There \\*[*] \\n[c#\\*[#t#r]] table \\*[**] (.TD)
+.
+. ds * are\"
+. if (\\n[t*cols\\n[t*#]] == 1) \
+. ds * is\"
+. tm1 " but only \\n[t*cols\\n[t*#]] \\*[*] expected.
+.
+. ds *
+. length * \\n[.F]:\\n[.c]:
+.
+. while \\n-[*] \
+. ds * " \\*[*]\"
+.
+. tm1 "\\*[*] Remaining .TDs and its contents are ignored.
+.
+. di *t*dummy* \" bypass superfluous input
+. return
+. \}
+.
+. di t*\\*[#trc] \" open cell diversion and set locals
+. in 0
+. nr cll\\*[#trc] \\n[*cl]
+. ll \\n[*cl]u
+. nr *cl\\n[t*#] \\n[.l]
+. gcolor \\*[t*fgc\\*[#trc]]
+. ad \\*[t*hal\\*[#trc]]
+. fam \\*[t*ff\\*[#trc]]
+. ft \\*[t*fst\\*[#trc]]
+. t*pv \\*[t*fsz\\*[#trc]]
+.
+. t*P1 \\*[args]
+..
+.
+.
+.\" ETB: end of table
+.\" predecessor: text, TD or ETB
+.\" successor: text, TD, TR or TBL
+.de ETB
+. ie \\n[t*#] \
+. if !\\n[t*r#\\n[t*#]] \{\
+. tmc \\n[.F]:\\n[.c]: Each table (.TBL)
+. tm1 " should contain at least one table row (.TR)!
+. \}
+. el \{\
+. tmc \\n[.F]:\\n[.c]: Table end (.ETB)
+. tm1 " without corresponding table start (.TBL)!
+. \}
+.
+. ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" refresh table row identifier
+. t*dntr 2 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
+.
+. t*divs \" print this table
+.
+. sp \\n[b/2\\n[t*#]]u
+. t*cptn\\n[t*#]
+. nr t*# -1
+.
+. ll \\n[*cl\\n[t*#]]u \" restore ll outside this table
+. in 0 \" reset indent
+. gcolor \\*[t*m\\n[t*#]] \" reset previous fgc
+.
+. t*getarg hold \\$@
+. if !\\n[t*#] \{\
+. sp .5
+. di
+. in \\n[t*i]u
+. ie "\\*[hold]"" \{\
+. ie (\\n[.t] - \\n[dn]) \
+. t*DI t*tbl0
+. el \{\
+. rn t*tbl0 t*tbl\\n+[t*numb]
+. ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[dn]\"
+. \}
+. \}
+. el \{\
+. rn t*tbl0 t*hold\\n+[t*numb]
+. tm \\n[.F]:\\n[.c]: Table t*hold\\n[t*numb] held.
+. ds t*held \\*[t*held] t*hold\\n[t*numb] \\n[dn]\"
+. \}
+.
+. ev \" restore previous environment
+. \}
+.
+. t*P1 \\*[args]
+..
+.
+.
+.\" *****************************************************************
+.\" * Following the definition of five utility macros *
+.\" * special to hdtbl. *
+.\" * Other utility macros common to hdtbl and hdgroff *
+.\" * are defined in the file hdmisc.tmac. *
+.\" *****************************************************************
+.
+.
+.\" .t*free [n]
+.\" print the next [n] held table[s].
+.\" Don't call it within a table!
+.\" If the table is higher than the remaining space
+.\" on the page, the table is printed on the next page.
+.de t*free
+. if "\\$0"CPTN" \
+. if \\n[t*r#\\n[t*#]] \{\
+. tmc \\n[.F]:\\n[.c]: Invalid placement of '.t*free' within a table;
+. tm1 " it must be called outside of any table.
+. return
+. \}
+.
+. if "\\*[t*held]"" \{\
+. tm \\n[.F]:\\n[.c]: No held tables.
+. return
+. \}
+.
+. nr ** (\\$1 >? 1) 1
+. while !""\\*[t*held]" \{\
+. pops * t*held
+. popr * t*held
+.
+. ie (\\n[.t] - \\n[*]) \{\
+. ev t*tbl
+. t*DI \\*[*]
+. ev
+. \}
+. el \{\
+. rn \\*[*] t*tbl\\n+[t*numb]
+. ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[*]\"
+. \}
+.
+. if !(\\n-[**] - 1) \
+. return
+. \}
+..
+.
+.
+.\" The main utility macro for tables:
+.\" If a table is closed by ETB, this macro is called. It
+.\" processes one complete table, i.e., all the table cell
+.\" diversions, paints the cell backgrounds, draws
+.\" horizontal and vertical table lines and the table border.
+.\"
+.\" Nested tables are processed from inside to outside.
+.
+.de t*divs
+. ll (\\n[t*l]u + 1c) \" avoid warning 'can't break line'
+. nf
+.
+. nr b/2 \\n[b/2\\n[t*#]] \" some abbreviations
+. nr cscp \\n[cscp\\n[t*#]]
+. nr cscpb (\\n[b/2] + \\n[cscp])
+.
+. nr topdiv (\\n[.d] + \\n[b/2] - \\n[cscp])\" top of cell diversion
+. nr cscpb2 (\\n[b/2] / 2 + \\n[cscp])
+.
+. nr #r 0 1
+. \" outer loop for rows
+. while (\\n+[#r] <= \\n[t*r#\\n[t*#]]) \{\
+. \" TODO: insert code here for multipage tables
+. nr * (\\n[#r] - 1)
+. nr topdiv +(\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
+.
+. \" if table still smaller than specified table height, increase it
+. if ((\\n[#r] == \\n[t*r#\\n[t*#]]) & \\n[t*height\\n[t*#]]) \
+. nr dntr\\n[t*#]*\\n[#r] (\\n[cscpb] \
+ + \\n[toptbl\\n[t*#]] \
+ + \\n[t*height\\n[t*#]] \
+ - (\\n[topdiv] >? \\n[dntr\\n[t*#]*\\n[#r]]))
+.
+. nr #c 0 1
+. \" inner loop for cells
+. while (\\n+[#c] <= \\n[t*cols\\n[t*#]]) \{\
+. ds #trc \\n[t*#]*\\n[#r]*\\n[#c]\"
+. \" continue if the diversion is empty
+. if !d t*\\*[#trc] \
+. continue
+.
+. sp |\\n[topdiv]u
+. in (\\n[in\\n[t*#]]u + \\n[in\\*[#trc]]u)\" cell offset
+. nr $1 \\n[dntr\\n[t*#]*\\n[#r]] \" cell height
+.
+. \" if we have spanned rows, calculate resulting row height
+. \" and position of lower horizontal line
+. if \\n[*rsp*\\*[#trc]] \{\
+. nr * \\n[#r] 1
+. nr rspan\\*[#trc] 0-1 \" set 'no hl' flag
+. nr corr (\\n[dn\\*[#trc]] - \\n[dntr\\n[t*#]*\\n[#r]])
+.
+. \" clear row span flags in following rows and update row height
+. while \\n[*rsp*\\*[#trc]] \{\
+. nr *rsp*\\*[#trc] -1
+. nr rspan\\n[t*#]*\\n+[*]*\\n[#c] 0
+. nr ** (\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
+. nr corr -\\n[**]
+. nr $1 +\\n[**]
+. \}
+.
+. if (\\n-[*] == \\n[t*r#\\n[t*#]]) \
+. nr $1 ((\\n[t*height\\n[t*#]] \
+ - \\n[.d] \
+ + \\n[toptbl\\n[t*#]] \
+ + \\n[cscpb]) \
+ >? \\n[$1])
+. nr dntr\\n[t*#]*\\n[*] +(\\n[corr] >? 0)
+. \}
+.
+. \" paint cell background
+. nr * (2 * \\n[t*cpd\\n[t*#]] + \\n[cll\\*[#trc]])\" background width
+. nr $1 (\\n[$1] >? \\n[dn\\*[#trc]])\" cell height
+.
+. if !"\\*[t*bgc\\*[#trc]]"=" \{\
+. nop \h'\\n[t*csp\\n[t*#]]u'\
+\M[\\*[t*bgc\\*[#trc]]]\
+\v'(-.67v - \\n[t*cpd\\n[t*#]]u)'\
+\D'P \\n[*]u 0 \
+ 0 (2u * \\n[t*cpd\\n[t*#]]u + \\n[$1]u) \
+ -\\n[*]u 0'\
+\M[]
+. sp -1
+. \}
+.
+. \" *** horizontal and vertical single or double lines ***
+. \" double and single lines have the same thickness;
+. \" the double lines' distance is the line thickness.
+. \"
+. \" 'border=x': horizontal/vertical lines x/2 thick, minimum .1n
+. \" 'border=0': no border; horizontal/vertical lines .1n thick
+. \" 'border=': neither border nor horizontal/vertical lines
+.
+. nr *t (.1n >? \\n[b/2]) \" thickness of hl/vl; min. .1n
+. in +\\n[cscp]u
+.
+. \" check for vertical and horizontal lines
+. if (1 + \\n[t*b\\n[t*#]]) \{\
+. if !"\\*[t*bc\\n[t*#]]"=" \{\
+. \" draw horizontal line between this cell and the one below
+. if (\\n[t*r#\\n[t*#]] - \\n[#r] + \\n[rspan\\*[#trc]]) \{\
+. if !"\\*[t*hl\\*[#trc]]"=" \{\
+. sp \\n[$1]u
+. nr * (\\n[cscp] + \\n[cscpb] + \\n[cll\\*[#trc]])
+. nop \X'\*[g] 1 setlinecap'\
+\h'(-\\n[cscpb2]u - \\n[*t]u)'\
+\v'(\\n[cscpb2]u - .67v)'\
+\m[\\*[t*bc\\n[t*#]]]\
+\D't \\n[*t]u'\c
+.
+. ie "\\*[t*hl\\*[#trc]]"d" \
+. nop \v'-\\n[*t]u'\
+\D'l \\n[*]u 0'\
+\v'(2u * \\n[*t]u)'\
+\D'l -\\n[*]u 0'\
+\D't 0'
+. el \
+. nop \D'l \\n[*]u 0'\
+\D't 0'
+.
+. sp (-\\n[$1]u - 1v)
+. \}\}
+.
+. nr rspan\\*[#trc] 0
+.
+. \" draw vertical line between this cell and the one to the right
+. if (\\n[t*cols\\n[t*#]] - \\n[#c] + \\n[vline\\*[#trc]]) \{\
+. if !"\\*[t*vl\\*[#trc]]"=" \{\
+. nop \X'\*[g] 1 setlinecap'\
+\v'(-\\n[cscpb2]u - .67v)'\
+\m[\\*[t*bc\\n[t*#]]]\
+\h'(\\n[cscpb2]u - \\n[*t]u + \\n[cll\\*[#trc]]u)'\c
+.
+. ie "\\*[t*vl\\*[#trc]]"d" \
+. nop \h'-\\n[*t]u'\
+\D't \\n[*t]u'\
+\D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
+\h'(2u * \\n[*t]u)'\
+\D'l 0 -(2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
+\D't 0'
+. el \
+. nop \D't \\n[*t]u'\
+\D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
+\D't 0'
+. sp -1
+. \}\}\}\}
+.
+. nr vline\\*[#trc] 0
+.
+. \" vert. cell content alignment
+. nr ** 0
+.
+. ie "\\*[t*val\\*[#trc]]"m" \
+. nr ** ((\\n[$1] - \\n[dn\\*[#trc]]) / 2)\" val=m
+. el \
+. if "\\*[t*val\\*[#trc]]"b" \
+. nr ** (\\n[$1] - \\n[dn\\*[#trc]])\" val=b
+.
+. sp \\n[**]u \" vertical content position
+.
+. \" finally output the diversion
+. t*\\*[#trc]
+. rm t*\\*[#trc]
+. \}
+. \}
+.
+. \" draw the box border
+. in \\n[in\\n[t*#]]u
+. nr ** (\\n[topdiv] + \\n[dntr\\n[t*#]*\\n-[#r]])
+.
+. if \\n[t*b\\n[t*#]] \{\
+. sp |(\\n[toptbl\\n[t*#]]u + \\n[b/2]u)
+. nr $1 (\\n[toptbl\\n[t*#]] - \\n[**] - \\n[cscp])
+. nr * (\\n[ll\\n[t*#]] - \\n[t*b\\n[t*#]])
+.
+. if !"\\*[t*bc\\n[t*#]]"=" \
+. nop \X'\*[g] 0 setlinejoin 2 setlinecap'\
+\v'-.67v'\
+\h'-\\n[b/2]u'\
+\m[\\*[t*bc\\n[t*#]]]\
+\D't \\n[t*b\\n[t*#]]u'\
+\D'l \\n[*]u 0'\
+\D'l 0 -\\n[$1]u'\
+\D'l -\\n[*]u 0'\
+\D'l 0 \\n[$1]u'\
+\D't 0'
+. \}
+.
+. sp |(\\n[**]u + \\n[cscpb]u)
+. fi
+..
+.
+.
+.\" Utility macro: .t*cl [width1 [width2 [...]]]
+.\"
+.\" Calculate cell widths, table width, and cell offsets.
+.de t*cl
+. nr t*cols\\n[t*#] (\\n[.$] >? \\n[t*cols\\n[t*#]])
+. nr ll\\n[t*#] 0 \" accumulated cell widths
+. nr ** (\\n[.l] / \\n[t*cols\\n[t*#]])\" width for remaining cells
+. nr * 0 1 \" counter
+.
+. \" while-loop: Parse user arguments to get each cell's width.
+. while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
+. nr $\\n[*] \\n[**]
+. if !"\\$[\\n[*]]"" \{\
+. \" check for '%' pseudo scaling indicator
+. ds * \\$\\n[*]\"
+. substring * -1 -1
+. ie "\\*[*]"%" \{\
+. ds ** \\$[\\n[*]]\"
+. substring ** 0 -2
+. ie \B\\*[**] \
+. nr $\\n[*] (\\*[**] * \\n[.l] / 100)
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid relative cell width '\\*[**]%'.
+. \}
+. el \{\
+. ie \B\\$[\\n[*]] \
+. nr $\\n[*] \\$[\\n[*]]
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid cell width '\\$[\\n[*]]'.
+. \}\}
+.
+. nr ll\\n[t*#] +\\n[$\\n[*]]
+. nr ** \\n[$\\n[*]]
+. \}
+.
+. if (\\n[ll\\n[t*#]] > \\n[.l]) \
+. tm \\n[.F]:\\n[.c]: Table width larger than column width.
+.
+. nr ** (0 >? \\n[t*b\\n[t*#]])
+. nr * 0 1
+.
+. \" second while loop: Compute final cell widths.
+. while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
+. \" Remove border width, if any.
+. if \\n[t*b\\n[t*#]] \{\
+. \" cell_width := cell_width * (length - 1.5*border) / length
+. nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
+. nr *** (\\n[ll\\n[t*#]] / 2)
+. \" avoid multiplication overflow
+. mult31by31 $\\n[*] #* ****
+. add31to62 *** **** ****
+. div62by31 **** ll\\n[t*#] $\\n[*]
+. \}
+.
+. \" Get cell widths without padding, spacing, and separator line.
+. nr cll\\n[t*#]*\\n[*] (\\n[$\\n[*]] \
+ - (2 * \\n[cscp\\n[t*#]]) \
+ - \\n[b/2\\n[t*#]])
+.
+. \" Check whether value is non-positive.
+. if !\\n[cll\\n[t*#]*\\n[*]] \{\
+. nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
+. nr *** (\\n[#*] / 2)
+. nr *h (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])
+. mult31by31 *h ll\\n[t*#] ****
+. add31to62 *** **** ****
+. div62by31 **** #* *h
+. ds * \\n[*]th\"
+. nr *** (\\n[*] % 10)
+. if d nth-\\n[***] \
+. ds * \\n[*]\\*[nth-\\n[***]]\"
+. tmc \\n[.F]:\\n[.c]: The \\*[*] width value (\\$\\n[*]) is too small.
+. tm1 " It should be greater than \\n[*h].
+. \}
+.
+. nr in\\n[t*#]*\\n[*] \\n[**] \" cell offset
+. nr ** +\\n[$\\n[*]]
+. \}
+..
+.
+.
+.\" Utility macro: .t*dntr <origin> <cell position> ? <cell ID>
+.\"
+.\" Close TD diversion, make some calculations, and set
+.\" some help strings and registers. <origin> is 0, 1,
+.\" or 2 if the call of .t*dntr occurs in .TD, .TR, or
+.\" .ETB, respectively.
+.de t*dntr
+. nr dn 0 \" reset diversion height
+. br \" finish cell data
+.
+. if "\\n[.z]"*t*dummy*" \
+. return
+.
+. ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\" refresh table row identifier
+.
+. if \\n[c#\\*[#t#r]] \{\
+. di \" close diversion
+. nr dn\\$4 \\n[dn] \" save height of this cell
+. if !\\n[rspan\\*[#trc]] \{\
+. \" update row height if not in a row span
+. nr dntr\\*[#t#r] (\\n[dntr\\*[#t#r]] >? \\n[dn])
+. if \\$2 \
+. nr dntr\\*[#t#r] ((\\n[t*height\\*[#t#r]] \
+ - (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])) \
+ >? \\n[dntr\\*[#t#r]])
+. \}\}
+.
+. nr c#\\*[#t#r] +1
+. nr * \\$2
+.
+. \" update column span registers
+. while (\\n+[*] <= \\$3) \{\
+. if r cspan\\*[#t#r]*\\n[*] \
+. nr c#\\*[#t#r] +\\n[cspan\\*[#t#r]*\\n[*]]
+. nr cspan\\*[#t#r]*\\n[*] 0
+. \}
+.
+. ds #trc \\*[#t#r]*\\n[c#\\*[#t#r]]\"
+.
+. \" only check for cell underflow if called by .TR or .ETB
+. if (\\$1 & (\\n[c#\\*[#t#r]] <= \\n[t*cols\\n[t*#]])) \{\
+. ds * are\"
+. ds ** columns\"
+. if (\\n-[c#\\*[#t#r]] == 1) \{\
+. ds * is\"
+. ds ** column\"
+. \}
+. tmc \\n[.F]:\\n[.c]: There \\*[*] only \\n[c#\\*[#t#r]] \\*[**]
+.
+. nr * \\n[t*r#\\n[t*#]]
+. ds * \\n[*]th\"
+. nr *** (\\n[*] % 10)
+. if d nth-\\n[***] \
+. ds * \\n[*]\\*[nth-\\n[***]]\"
+. tmc " in the \\*[*] row
+.
+. ds * are\"
+. if (\\n[t*cols\\n[t*#]] == 1) \
+. ds * is\"
+. tm1 " but \\n[t*cols\\n[t*#]] \\*[*] expected.
+. \}
+..
+.
+.
+.\" Utility-macro: .t*args level_1 [level_2]
+.\"
+.\" Get the arguments common to TBL, TR, and TD for the level
+.\" in argument 1, using default values from the level in
+.\" argument 2. If argument 2 is missing, use the global
+.\" default values.
+.\"
+.de t*args
+. ds t*bgc\\$1 \\*[t*bgc\\$2]\"
+. ds t*fgc\\$1 \\*[t*fgc\\$2]\"
+. ds t*hl\\$1 \\*[t*hl\\$2]\"
+. ds t*vl\\$1 \\*[t*vl\\$2]\"
+. ds t*hal\\$1 \\*[t*hal\\$2]\"
+. ds t*val\\$1 \\*[t*val\\$2]\"
+. ds t*ff\\$1 \\*[t*ff\\$2]\"
+. ds t*fst\\$1 \\*[t*fst\\$2]\"
+. ds t*fsz\\$1 \\*[t*fsz\\$2]\"
+.
+. if "\\*[args]"" \
+. return
+.
+. t*getarg bgc \\*[args] \" background color
+. if !"\\*[bgc]"" \{\
+. ie m\\*[bgc] \
+. ds t*bgc\\$1 \\*[bgc]\"
+. el \{\
+. ie "\\*[bgc]"=" \
+. ds t*bgc\\$1 =\"
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid background color '\\*[bgc]'.
+. \}\}
+. if "\\*[args]"" \
+. return
+.
+. t*getarg fgc \\*[args] \" foreground color
+. if !"\\*[fgc]"" \{\
+. ie m\\*[fgc] \
+. ds t*fgc\\$1 \\*[fgc]\"
+. el \{\
+. ie "\\*[fgc]"=" \
+. ds t*fgc\\$1 =\"
+. el \
+. tm \\n[.F]:\\n[.c]: Invalid foreground color '\\*[fgc]'.
+. \}\}
+. if "\\*[args]"" \
+. return
+.
+. t*getarg hl \\*[args] \" horizontal line between cells
+. if !"\\*[hl]"" \
+. ds t*hl\\$1 \\*[hl]\"
+. if "\\*[args]"" \
+. return
+.
+. t*getarg vl \\*[args] \" vertical line between cells
+. if !"\\*[vl]"" \
+. ds t*vl\\$1 \\*[vl]\"
+. if "\\*[args]"" \
+. return
+.
+. t*getarg hal \\*[args] \" horizontal table cell alignment
+. if !"\\*[hal]"" \{\
+. t*index bcrl \\*[hal]
+. ie \\n[t*index] \
+. ds t*hal\\$1 \\*[hal]\"
+. el \{\
+. tmc \\n[.F]:\\n[.c]: Invalid horizontal alignment '\\*[hal]':
+. tm1 " must be 'b', 'c', 'l' or 'r'.
+. \}\}
+. if "\\*[args]"" \
+. return
+.
+. t*getarg val \\*[args] \" vertical table cell alignment
+. if !"\\*[val]"" \{\
+. t*index tmb \\*[val]
+. ie \\n[t*index] \
+. ds t*val\\$1 \\*[val]\"
+. el \{\
+. tmc \\n[.F]:\\n[.c]: Invalid vertical alignment '\\*[val]':
+. tm1 " must be 't', 'm' or 'b'.
+. \}\}
+. if "\\*[args]"" \
+. return
+.
+. t*getarg ff \\*[args] \" font family
+. if !"\\*[ff]"" \
+. ds t*ff\\$1 \\*[ff]\"
+. if "\\*[args]"" \
+. return
+.
+. t*getarg fst \\*[args] \" font style
+. if !"\\*[fst]"" \
+. ds t*fst\\$1 \\*[fst]\"
+. if "\\*[args]"" \
+. return
+.
+. t*getarg fsz \\*[args] \" font size and spacing factor
+. if !"\\*[fsz]"" \
+. ds t*fsz\\$1 \\*[fsz]\"
+..
+.
+.
+.\" Append to your page header macro ('pg@top' for MS)
+.\" to enable tables to span pages.
+.de t*hm
+. ev t*tbl
+. nr ** \\n[.t]
+. while !""\\*[t*kept]" \{\
+. pops * t*kept
+. popr * t*kept
+. if (\\n[*] - \\n[**]) \{\
+. tm \\n[.F]:\\n[.c]: Table \\*[*] higher than page -- ignored!
+. break
+. \}
+.
+. if (\\n[*] - \\n[.t]) \{\
+. ds t*kept \\n[*] \\*[t*kept]\"
+. ds t*kept \\*[*] \\*[t*kept]\"
+. tmc \\n[.F]:\\n[.c]: Remaining table(s),
+. tm1 " because not all fit onto this page.
+. break
+. \}
+.
+. t*DI \\*[*]
+. \}
+. ev
+..
+.
+.\" Local Variables:
+.\" mode: nroff
+.\" End:
+.\" vim: filetype=groff: