* font/devps/generate/textmap: Add Greek letters and some more.
[s-roff.git] / contrib / hdtbl / hdtbl.tmac
blobb59a5d009c017cf82c247af819b856eef71ff0d9
1 .\"     -*- roff -*-
2 .ig
4 hdtbl.tmac
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
14 version.
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
19 for more details.
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
24 02110-1301, USA.
29 .\"     *****************************************************************
30 .\"     *               hdtbl - Heidelberger table macros               *
31 .\"     *                       Vers. 0.91 December 2005                *
32 .\"     *****************************************************************
34 .if d TBL \
35 .  nx
37 .mso hdmisc.tmac
38 .mso 62bit.tmac
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
44 .am HM
45 .  t*hm
49 .\"     *****************************************************************
50 .\"     *               default values for some arguments               *
51 .\"     *****************************************************************
53 .ds t*hl s\"
54 .ds t*vl s\"
55 .ds t*tal l\"
56 .ds t*hal b\"
57 .ds t*val t\"
58 .ds t*ff \\n[.fam]\"
59 .ds t*fst \\n[.f]\"
60 .ds t*fsz 1 1\"
61 .ds t*fgc red4\"
62 .ds t*bgc bisque\"
63 .ds t*bc red4\"
64 .nr t*cpd .5n
65 .nr t*csp .5n
66 .nr t*b .1n
67 .nr t*cols 1
70 .\"                     defaults for table captions
71 .nr t*cptn 0 1
72 .ds t*cptn "".sp .4" \
73             ".pv 1.4 1.4" \
74             ".ad l" \
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[%]/\"
83 .\" %beginstrip%
85 .\" for better error messages
86 .ds nth-1 st\"
87 .ds nth-2 nd\"
88 .ds nth-3 rd\"
90 .\" initialization of various registers
91 .nr t*# 0       \"      table nesting level
92 .nr t*numb 0 1  \"      held table diversion #
94 .ds *#trc*
97 .\"     *****************************************************************
98 .\"     *       The four base macros and the two optional macros        *
99 .\"     *****************************************************************
101 .ie n \
102 .  ds g tty:\"
103 .el \
104 .  ds g ps: exec\"
106 .\"     TBL:    table start
107 .\"             predecessor:    text, TD or ETB
108 .\"             successor:      CPTN or TR
109 .de TBL
110 .  ds t*m\\n[t*#] \\n[.m]\"
111 .  ie \\n[t*#] \
112 .    br
113 .  el \{\
114 .    ds * \\n[.ev]\"
115 .    ev t*tbl
116 .    evc \\*[*]
117 .    di t*tbl0
118 .    sp .4                              \" XXX: hard-coded value
119 .    nr t*i \\n[.i]
120 .    ll -\\n[.i]u
121 .    in 0
122 .  \}
123 .  nr t*# +1
125 .  getarg cols \\$@\"   from here string `args' contains the rest of \\$@
126 .  ie "\\*[cols]"" \
127 .    nr t*cols\\n[t*#] \\n[t*cols]
128 .  el \{\
129 .    ie \B\a\\*[cols]\a \
130 .      nr t*cols\\n[t*#] \\*[cols]
131 .    el \
132 .      tm \\n[.F]:\\n[.c]: Invalid number of columns value `\\*[cols]'.
133 .  \}
135 .  getarg cpd \\*[args]                 \"      cell padding
136 .  ie "\\*[cpd]"" \
137 .    nr t*cpd\\n[t*#] \\n[t*cpd]
138 .  el \{\
139 .    ie \B\a\\*[cpd]\a \
140 .      nr t*cpd\\n[t*#] \\*[cpd]
141 .    el \
142 .      tm \\n[.F]:\\n[.c]: Invalid cell padding value `\\*[cpd]'.
143 .  \}
145 .  getarg csp \\*[args]                 \"      cell spacing
146 .  ie "\\*[csp]"" \
147 .    nr t*csp\\n[t*#] \\n[t*csp]
148 .  el \{\
149 .    ie \B\a\\*[csp]\a \
150 .      nr t*csp\\n[t*#] \\*[csp]
151 .    el \
152 .      tm \\n[.F]:\\n[.c]: Invalid cell spacing value `\\*[csp]'.
153 .  \}
155 .  getarg border \\*[args]              \"      border thickness
156 .  ie "\\*[border]"=" \
157 .    nr t*b\\n[t*#] 0-1
158 .  el \{\
159 .    ie "\\*[border]"" \
160 .      nr t*b\\n[t*#] \\n[t*b]
161 .    el \{\
162 .      ie \B\a\\*[border]\a \
163 .        nr t*b\\n[t*#] \\*[border]
164 .      el \
165 .        tm \\n[.F]:\\n[.c]: Invalid border thickness value `\\*[border]'.
166 .  \}\}
168 .  getarg bc \\*[args]                  \"      border color
169 .  ds t*bc\\n[t*#] \\*[t*bc]\"
170 .  if !"\\*[bc]"" \{\
171 .    ie m\\*[bc] \
172 .      ds t*bc\\n[t*#] \\*[bc]\"
173 .    el \{\
174 .      ie "\\*[bc]"=" \
175 .        ds t*bc\\n[t*#] =\"
176 .      el \
177 .        tm \\n[.F]:\\n[.c]: Invalid border color `\\*[bc]'.
178 .  \}\}
179 .  ie "\\*[bc]"=" \
180 .    ds t*bc\\n[t*#]
181 .  el \{\
182 .    ie "\\*[bc]"" \
183 .      ds t*bc\\n[t*#] \\*[t*bc]\"
184 .    el \
185 .      ds t*bc\\n[t*#] \\*[bc]\"
186 .  \}
188 .  getarg width \\*[args]               \"      table/col widths
189 .  if "\\*[width]"=" \
190 .    ds 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
198 .  el \{\
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*#]])))
203 .    el \
204 .      tm \\n[.F]:\\n[.c]: Invalid height value `\\*[height]'.
205 .  \}
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
211 .  if "\\*[tal]"" \
212 .    ds tal \\*[t*tal]\"
213 .  ie "\\*[tal]"l" \
214 .    nr in\\n[t*#] \\n[.i]
215 .  el \{\
216 .    ie "\\*[tal]"c" \
217 .      nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]]/2 + \\n[.i])
218 .    el \{\
219 .      ie "\\*[tal]"r" \
220 .        nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]] + \\n[.i])
221 .      el \{\
222 .        tmc \\n[.F]:\\n[.c]: Invalid horizontal table alignment `\\*[tal]':
223 .        tm1 " must be `l', `c' or `r'.
224 .  \}\}\}
226 .  nr t*r#\\n[t*#] 0                    \"      initialize row index
227 .  mk toptbl\\n[t*#]
229 .  P1 \\*[args]
233 .\"     CPTN:   optional table caption
234 .\"             predecessor:    TBL
235 .\"             successor:      TR
236 .de CPTN
237 .  ft 1
239 .  if "\\$0"CPTN" \
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'.
243 .      return
244 .    \}
246 .  getarg val \\$@
247 .  ds args\\n[t*#] "\\*[args]\"
249 .  index "\\*[args]" .TR
250 .  ie \\n[index] \{\
251 .    ds *a\\n[t*#] "\\*[args]\"
252 .    substring args\\n[t*#] 0 \\n[index]
253 .    substring *a\\n[t*#] \\n[index]-2 -1
254 .  \}
255 .  el \
256 .    ds *a\\n[t*#]
258 .  ie "\\*[val]"b" \{\
259 .    de t*cptn\\n[t*#]
260 .      *CPTN \\*[args\\n[t*#]]
261 .      rm t*cptn\\n[t*#]
262 \\..
263 .  \}
264 .  el \{\
265 .    ll (\\n[ll\\n[t*#]]u + \\n[in\\n[t*#]]u)
266 .    in \\n[in\\n[t*#]]u
267 .    P1 \\*[t*cptn]
268 '    in +\\n[*]u
269 .    P1 \\*[args\\n[t*#]]
270 .    pv 1 1
271 .    in
272 .    mk toptbl\\n[t*#]
273 .  \}
275 .  P1 \\*[*a\\n[t*#]]
278 .als *CPTN CPTN
281 .\"     TR:     table row
282 .\"             predecessor:    TBL, CPTN, text, TD or ETB
283 .\"             successor:      TD
284 .de TR
285 .  ft 1
286 .  if !\\n[t*#] \{\
287 .    tm \\n[.F]:\\n[.c]: Table row (.TR) without preceding table start (.TBL).
288 .    return
289 .  \}
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
297 .                                       \"      (<level>*<row>)
298 .  nr c#\\*[#t#r] 0 1                   \"      clear cell counter
299 .  nr dntr\\*[#t#r] 0 1                 \"      clear accumulated row height
301 .  getarg height \\$@
302 .  ie "\\*[height]"" \
303 .    nr t*height\\*[#t#r] 0
304 .  el \{\
305 .    ie \B\a\\*[height]\a \
306 .      nr t*height\\*[#t#r] \\*[height]
307 .    el \
308 .      tm \\n[.F]:\\n[.c]: Invalid table row height `\\*[height]'.
309 .  \}
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
315 .  P1 \\*[args]
319 .\"     TH:     optional table header cell
320 .\"             predecessor:    text, TD or TR
321 .\"             successor:      text, TD, TR, TBL or ETB
322 .\"                                                             
323 .\"             cell content bolded and horizontally and vertically centered,
324 .\"             else like .TD
325 .de TH
326 .  ft 1
327 .  getarg hal \\$@
328 .  if "\\*[hal]"" \
329 .    ds hal c\"
331 .  getarg val \\*[args]
332 .  if "\\*[val]"" \
333 .    ds val m\"
335 .  getarg fst \\*[args]
336 .  if "\\*[fst]"" \
337 .    ds fst B\"
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
346 .de TD
347 .  ft 1
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 \\$@
355 .  nr rowspan 1
356 .  if !"\\*[rowspan]"" \{\
357 .    ie \B\a\\*[rowspan]\a \{\
358 .      nr rowspan (\\*[rowspan] >? 1)
359 .      nr *rsp*\\*[*#trc*] (\\n[rowspan] - 1)
360 .    \}
361 .    el \
362 .      tm \\n[.F]:\\n[.c]: Invalid value of `rowspan' keyword.
363 .  \}
365 .  getarg colspan \\*[args]
366 .  nr colspan 1
367 .  if !"\\*[colspan]"" \{\
368 .    ie \B\a\\*[colspan]\a \
369 .      nr colspan (\\*[colspan] >? 1)
370 .    el \
371 .      tm \\n[.F]:\\n[.c]: Invalid value of `colspan' keyword.
372 .  \}
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]]]
378 .  nr * 0 1
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]
384 .      if (\\n[*] > 1) \
385 .        nr cspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
386 .      nr *r +1
387 .    \}
389 .  nr * 1 1
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]) \{\
396 .      nr *c +1
397 .      nr *cl +(2 * \\n[cscp\\n[t*#]] \
398                 + \\n[b/2\\n[t*#]] \
399                 + \\n[cll\\n[t*#]*\\n[*c]])
400 .      nr c#\\*[#t#r] +1
401 .    \}
402 .  \}
404 .  if (\\n[c#\\n[t*#]*\\n[t*r#\\n[t*#]]] > \\n[t*cols\\n[t*#]]) \{\
405 .    ds * are\"
406 .    ds ** columns\"
407 .    if (\\n[c#\\*[#t#r]] == 1) \{\
408 .      ds * is\"
409 .      ds ** column\"
410 .    \}
411 .    tmc \\n[.F]:\\n[.c]: There \\*[*] \\n[c#\\*[#t#r]] table \\*[**] (.TD)
413 .    ds * are\"
414 .    if (\\n[t*cols\\n[t*#]] == 1) \
415 .      ds * is\"
416 .    tm1 " but only \\n[t*cols\\n[t*#]] \\*[*] expected.
418 .    ds *
419 .    length * \\n[.F]:\\n[.c]:
421 .    while \\n-[*] \
422 .      ds * " \\*[*]\"
424 .    tm1 "\\*[*] Remaining .TDs and its contents are ignored.
426 .    di *t*dummy*                \"     bypass superfluous input
427 .    return
428 .  \}
430 .  di t*\\*[#trc]                \"     open cell diversion and set locals
431 .  in 0
432 .  nr cll\\*[#trc] \\n[*cl]
433 .  ll \\n[*cl]u
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]]
441 .  P1 \\*[args]
445 .\"     ETB:    end of table
446 .\"             predecessor:    text, TD or ETB
447 .\"             successor:      text, TD, TR or TBL
448 .de ETB
449 .  ie \\n[t*#] \
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)!
453 .    \}
454 .  el \{\
455 .    tmc \\n[.F]:\\n[.c]: Table end (.ETB)
456 .    tm1 " without corresponding table start (.TBL)!
457 .  \}
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
465 .  t*cptn\\n[t*#]
466 .  nr t*# -1
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
472 .  getarg hold \\$@
473 .  if !\\n[t*#] \{\
474 .    sp .5
475 .    di
476 .    in \\n[t*i]u
477 .    ie "\\*[hold]"" \{\
478 .      ie (\\n[.t] - \\n[dn]) \
479 .        DI t*tbl0
480 .      el \{\
481 .        rn t*tbl0 t*tbl\\n[t*numb]
482 .        ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[dn]\"
483 .      \}
484 .    \}
485 .    el \{\
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]\"
489 .    \}
491 .    ev                         \"      restore previous environment
492 .  \}
494 .  P1 \\*[args]
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 .\"     *****************************************************************
506 .\"     .t*free [n]
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.
511 .de t*free
512 .  if "\\$0"CPTN" \
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.
516 .      return
517 .    \}
519 .  if "\\*[t*held]"" \{\
520 .    tm \\n[.F]:\\n[.c]: No held tables.
521 .    return
522 .  \}
524 .  nr ** (\\$1 >? 1)
525 .  while !""\\*[t*held]" \{\
526 .    pops * t*held
527 .    popr * t*held
529 .    ie (\\n[.t] - \\n[*]) \{\
530 .      ev t*tbl
531 .      DI \\*[*]
532 .      ev
533 .    \}
534 .    el \{\
535 .      rn \\*[*] t*tbl\\n+[t*numb]
536 .      ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[*]\"
537 .    \}
539 .    if !(\\n-[**] - 1) \
540 .      return
541 .  \}
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.
553 .de t*divs
554 .  ll (\\n[l]u + 1c)                    \"      avoid warning `can't break line'
555 .  nf
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])
564 .  nr #r 0 1
565 .  \" outer loop for rows
566 .  while (\\n+[#r] <= \\n[t*r#\\n[t*#]]) \{\
567 .    \" TODO: insert code here for multipage tables
568 .    nr * (\\n[#r] - 1)
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]]))
578 .    nr #c 0 1
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] \
584 .        continue
586 .      sp |\\n[topdiv]u
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]] \{\
593 .        nr * \\n[#r] 1
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])
602 .          nr corr -\\n[**]
603 .          nr $1 +\\n[**]
604 .        \}
606 .        if (\\n-[*] == \\n[t*r#\\n[t*#]]) \
607 .          nr $1 ((\\n[t*height\\n[t*#]] \
608                    - \\n[.d] \
609                    + \\n[toptbl\\n[t*#]] \
610                    + \\n[cscpb]) \
611                      >? \\n[$1])
612 .        nr dntr\\n[t*#]*\\n[*] +(\\n[corr] >? 0)
613 .      \}
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)'\
623 \D'P \\n[*]u 0 \
624      0 (2u * \\n[t*cpd\\n[t*#]]u + \\n[$1]u) \
625      -\\n[*]u 0'\
626 \M[]
627 .        sp -1
628 .      \}
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.
633 .      \"
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
639 .      in +\\n[cscp]u
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]]"=" \{\
647 .              sp \\n[$1]u
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*#]]]\
653 \D't \\n[*t]u'\c
655 .              ie "\\*[t*hl\\*[#trc]]"d" \
656 .                nop \v'-\\n[*t]u'\
657 \D'l \\n[*]u 0'\
658 \v'(2u * \\n[*t]u)'\
659 \D'l -\\n[*]u 0'\
660 \D't 0'
661 .              el \
662 .                nop \D'l \\n[*]u 0'\
663 \D't 0'
665 .              sp (-\\n[$1]u - 1v)
666 .          \}\}
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" \
679 .                nop \h'-\\n[*t]u'\
680 \D't \\n[*t]u'\
681 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
682 \h'(2u * \\n[*t]u)'\
683 \D'l 0 -(2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
684 \D't 0'
685 .              el \
686 .                nop \D't \\n[*t]u'\
687 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
688 \D't 0'
689 .              sp -1
690 .      \}\}\}\}
692 .      nr vline\\*[#trc] 0
694 .      \" vert. cell content alignment
695 .      nr ** 0
697 .      ie "\\*[t*val\\*[#trc]]"m" \
698 .        nr ** ((\\n[$1] - \\n[dn\\*[#trc]]) / 2)\"     val=m
699 .      el \
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
706 .      t*\\*[#trc]
707 .      rm t*\\*[#trc]
708 .    \}
709 .  \}
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'\
722 \v'-.67v'\
723 \h'-\\n[b/2]u'\
724 \m[\\*[t*bc\\n[t*#]]]\
725 \D't \\n[t*b\\n[t*#]]u'\
726 \D'l \\n[*]u 0'\
727 \D'l 0 -\\n[$1]u'\
728 \D'l -\\n[*]u 0'\
729 \D'l 0 \\n[$1]u'\
730 \D't 0'
731 .  \}
733 .  sp |(\\n[**]u + \\n[cscpb]u)
734 .  fi
738 .\"     Utility macro:  .t*cl [width1 [width2 [...]]]
740 .\"             Calculate cell widths, table width, and cell offsets.
741 .de t*cl
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+[*]) \{\
749 .    nr $\\n[*] \\n[**]
750 .    if !"\\$[\\n[*]]"" \{\
751 .      \" check for `%' pseudo scaling indicator
752 .      ds * \\$\\n[*]\"
753 .      substring * -1 -1
754 .      ie "\\*[*]"%" \{\
755 .        ds ** \\$[\\n[*]]\"
756 .        substring ** 0 -2
757 .        ie \B\a\\*[**]\a \
758 .          nr $\\n[*] (\\*[**] * \\n[.l] / 100)
759 .        el \
760 .          tm \\n[.F]:\\n[.c]: Invalid relative cell width `\\*[**]%'.
761 .      \}
762 .      el \{\
763 .        ie \B\a\\$[\\n[*]]\a \
764 .          nr $\\n[*] \\$[\\n[*]]
765 .        el \
766 .          tm \\n[.F]:\\n[.c]: Invalid cell width `\\$[\\n[*]]'.
767 .    \}\}
769 .    nr ll\\n[t*#] +\\n[$\\n[*]]
770 .    nr ** \\n[$\\n[*]]
771 .  \}
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*#]])
777 .  nr * 0 1
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[*]
790 .    \}
792 .    \" Get cell widths without padding, spacing, and separator line.
793 .    nr cll\\n[t*#]*\\n[*] (\\n[$\\n[*]] \
794                             - (2 * \\n[cscp\\n[t*#]]) \
795                             - \\n[b/2\\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
805 .      ds * \\n[*]th\"
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].
811 .    \}
813 .    nr in\\n[t*#]*\\n[*] \\n[**]       \"      cell offset
814 .    nr ** +\\n[$\\n[*]]
815 .  \}
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.
825 .de t*dntr
826 .  nr dn 0                              \"      reset diversion height
827 .  br                                   \"      finish cell data
829 .  if "\\n[.z]"*t*dummy*" \
830 .    return
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])
840 .      if \\$2 \
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]])
844 .  \}\}
846 .  nr c#\\*[#t#r] +1
847 .  nr * \\$2
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
854 .  \}
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*#]])) \{\
860 .    ds * are\"
861 .    ds ** columns\"
862 .    if (\\n-[c#\\*[#t#r]] == 1) \{\
863 .      ds * is\"
864 .      ds ** column\"
865 .    \}
866 .    tmc \\n[.F]:\\n[.c]: There \\*[*] only \\n[c#\\*[#t#r]] \\*[**]
868 .    nr * \\n[t*r#\\n[t*#]]
869 .    ds * \\n[*]th\"
870 .    nr *** (\\n[*] % 10)
871 .    if d nth-\\n[***] \
872 .      ds * \\n[*]\\*[nth-\\n[***]]\"
873 .    tmc " in the \\*[*] row
875 .    ds * are\"
876 .    if (\\n[t*cols\\n[t*#]] == 1) \
877 .      ds * is\"
878 .    tm1 " but \\n[t*cols\\n[t*#]] \\*[*] expected.
879 .  \}
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
888 .\"             default values.
890 .de t*args
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]\"
901 .  if "\\*[args]"" \
902 .    return
904 .  getarg bgc \\*[args]         \"      background color
905 .  if !"\\*[bgc]"" \{\
906 .    ie m\\*[bgc] \
907 .      ds t*bgc\\$1 \\*[bgc]\"
908 .    el \{\
909 .      ie "\\*[bgc]"=" \
910 .        ds t*bgc\\$1 =\"
911 .      el \
912 .        tm \\n[.F]:\\n[.c]: Invalid background color `\\*[bgc]'.
913 .  \}\}
914 .  if "\\*[args]"" \
915 .    return
917 .  getarg fgc \\*[args]         \"      foreground color
918 .  if !"\\*[fgc]"" \{\
919 .    ie m\\*[fgc] \
920 .      ds t*fgc\\$1 \\*[fgc]\"
921 .    el \{\
922 .      ie "\\*[fgc]"=" \
923 .        ds t*fgc\\$1 =\"
924 .      el \
925 .        tm \\n[.F]:\\n[.c]: Invalid foreground color `\\*[fgc]'.
926 .  \}\}
927 .  if "\\*[args]"" \
928 .    return
930 .  getarg hl \\*[args]          \"      horizontal line between cells
931 .  if !"\\*[hl]"" \
932 .    ds t*hl\\$1 \\*[hl]\"
933 .  if "\\*[args]"" \
934 .    return
936 .  getarg vl \\*[args]          \"      vertical line between cells
937 .  if !"\\*[vl]"" \
938 .    ds t*vl\\$1 \\*[vl]\"
939 .  if "\\*[args]"" \
940 .    return
942 .  getarg hal \\*[args]         \"      horizontal table cell alignment
943 .  if !"\\*[hal]"" \{\
944 .    index bcrl \\*[hal]
945 .    ie \\n[index] \
946 .      ds t*hal\\$1 \\*[hal]\"
947 .    el \{\
948 .      tmc \\n[.F]:\\n[.c]: Invalid horizontal alignment `\\*[hal]':
949 .      tm1 " must be `b', `c', `l' or `r'.
950 .  \}\}
951 .  if "\\*[args]"" \
952 .    return
954 .  getarg val \\*[args]         \"      vertical table cell alignment
955 .  if !"\\*[val]"" \{\
956 .    index tmb \\*[val]
957 .    ie \\n[index] \
958 .      ds t*val\\$1 \\*[val]\"
959 .    el \{\
960 .      tmc \\n[.F]:\\n[.c]: Invalid vertical alignment `\\*[val]':
961 .      tm1 " must be `t', `m' or `b'.
962 .  \}\}
963 .  if "\\*[args]"" \
964 .    return
966 .  getarg ff \\*[args]          \"      font family
967 .  if !"\\*[ff]"" \
968 .    ds t*ff\\$1 \\*[ff]\"
969 .  if "\\*[args]"" \
970 .    return
972 .  getarg fst \\*[args]         \"      font style
973 .  if !"\\*[fst]"" \
974 .    ds t*fst\\$1 \\*[fst]\"
975 .  if "\\*[args]"" \
976 .    return
978 .  getarg fsz \\*[args]         \"      font size and spacing factor
979 .  if !"\\*[fsz]"" \
980 .    ds t*fsz\\$1 \\*[fsz]\"
984 .de t*hm
985 .  ev t*tbl
986 .  nr ** \\n[.t]
987 .  while !""\\*[t*kept]" \{\
988 .    pops * t*kept
989 .    popr * t*kept
990 .    if (\\n[*] - \\n[**]) \{\
991 .      tm \\n[.F]:\\n[.c]: Table \\*[*] higher than page -- ignored!
992 .      break
993 .    \}
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.
1000 .      break
1001 .    \}
1003 .    DI \\*[*]
1004 .  \}
1005 .  ev
1008 .\" EOF