Remove no longer needed catman periodic via 'make upgrade'.
[dragonfly.git] / contrib / groff / contrib / hdtbl / hdtbl.tmac
1 .\"     -*- roff -*-
2 .ig
3
4 hdtbl.tmac
5
6 This file is part of groff, the GNU roff type-setting system.
7
8 Copyright (C) 2005, 2006, 2009 Free Software Foundation, Inc.
9 written by Joachim Walsdorff <Joachim.Walsdorff@urz.uni-heidelberg.de>.
10
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 3 of the License, or
14 (at your option) any later version.
15
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.
20
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
23
24 ..
25 .
26 .
27 .\"     *****************************************************************
28 .\"     *               hdtbl - Heidelberger table macros               *
29 .\"     *                       Vers. 0.91 December 2005                *
30 .\"     *****************************************************************
31 .
32 .if d TBL \
33 .  nx
34 .
35 .mso hdmisc.tmac
36 .mso 62bit.tmac
37 .
38 .wh 0 HM        \"      comment this out if a page header macro exists
39 .wh -1i BM      \"      comment this out if a bottom margin macro exists
40 .
41 .\" replace `HM' with the name of your pageheader macro, e.g., `pg@top' for MS
42 .am HM
43 .  t*hm
44 ..
45 .
46 .
47 .\"     *****************************************************************
48 .\"     *               default values for some arguments               *
49 .\"     *****************************************************************
50 .
51 .ds t*hl s\"
52 .ds t*vl s\"
53 .ds t*tal l\"
54 .ds t*hal b\"
55 .ds t*val t\"
56 .ds t*ff \\n[.fam]\"
57 .ds t*fst \\n[.f]\"
58 .ds t*fsz 1 1\"
59 .ds t*fgc red4\"
60 .ds t*bgc bisque\"
61 .ds t*bc red4\"
62 .nr t*cpd .5n
63 .nr t*csp .5n
64 .nr t*b .1n
65 .nr t*cols 1
66 .
67 .
68 .\"                     defaults for table captions
69 .nr t*cptn 0 1
70 .ds t*cptn "".sp .4" \
71             ".pv 1.4 1.4" \
72             ".ad l" \
73             "\m[\\*[t*fgc]]Table \\n+[t*cptn]:\0\c\k*"\"
74 .
75 .
76 .\"                     Running title, running footer
77 .ds t*HM //arbitrary text for pageheader, except on the first page//\"
78 .ds t*BM //arbitrary text for pagefooter, except on the last page/\\n[%]/\"
79 .
80 .
81 .\" %beginstrip%
82 .
83 .\" for better error messages
84 .ds nth-1 st\"
85 .ds nth-2 nd\"
86 .ds nth-3 rd\"
87 .
88 .\" initialization of various registers
89 .nr t*# 0       \"      table nesting level
90 .nr t*numb 0 1  \"      held table diversion #
91 .
92 .ds *#trc*
93 .
94 .
95 .\"     *****************************************************************
96 .\"     *       The four base macros and the two optional macros        *
97 .\"     *****************************************************************
98 .
99 .ie n \
100 .  ds g tty:\"
101 .el \
102 .  ds g ps: exec\"
103 .
104 .\"     TBL:    table start
105 .\"             predecessor:    text, TD or ETB
106 .\"             successor:      CPTN or TR
107 .de TBL
108 .  ds t*m\\n[t*#] \\n[.m]\"
109 .  ie \\n[t*#] \
110 .    br
111 .  el \{\
112 .    ds * \\n[.ev]\"
113 .    ev t*tbl
114 .    evc \\*[*]
115 .    di t*tbl0
116 .    sp .4                              \" XXX: hard-coded value
117 .    nr t*i \\n[.i]
118 .    ll -\\n[.i]u
119 .    in 0
120 .  \}
121 .  nr t*# +1
122 .
123 .  getarg cols \\$@\"   from here string `args' contains the rest of \\$@
124 .  ie "\\*[cols]"" \
125 .    nr t*cols\\n[t*#] \\n[t*cols]
126 .  el \{\
127 .    ie \B\a\\*[cols]\a \
128 .      nr t*cols\\n[t*#] \\*[cols]
129 .    el \
130 .      tm \\n[.F]:\\n[.c]: Invalid number of columns value `\\*[cols]'.
131 .  \}
132 .
133 .  getarg cpd \\*[args]                 \"      cell padding
134 .  ie "\\*[cpd]"" \
135 .    nr t*cpd\\n[t*#] \\n[t*cpd]
136 .  el \{\
137 .    ie \B\a\\*[cpd]\a \
138 .      nr t*cpd\\n[t*#] \\*[cpd]
139 .    el \
140 .      tm \\n[.F]:\\n[.c]: Invalid cell padding value `\\*[cpd]'.
141 .  \}
142 .
143 .  getarg csp \\*[args]                 \"      cell spacing
144 .  ie "\\*[csp]"" \
145 .    nr t*csp\\n[t*#] \\n[t*csp]
146 .  el \{\
147 .    ie \B\a\\*[csp]\a \
148 .      nr t*csp\\n[t*#] \\*[csp]
149 .    el \
150 .      tm \\n[.F]:\\n[.c]: Invalid cell spacing value `\\*[csp]'.
151 .  \}
152 .
153 .  getarg border \\*[args]              \"      border thickness
154 .  ie "\\*[border]"=" \
155 .    nr t*b\\n[t*#] 0-1
156 .  el \{\
157 .    ie "\\*[border]"" \
158 .      nr t*b\\n[t*#] \\n[t*b]
159 .    el \{\
160 .      ie \B\a\\*[border]\a \
161 .        nr t*b\\n[t*#] \\*[border]
162 .      el \
163 .        tm \\n[.F]:\\n[.c]: Invalid border thickness value `\\*[border]'.
164 .  \}\}
165 .
166 .  getarg bc \\*[args]                  \"      border color
167 .  ds t*bc\\n[t*#] \\*[t*bc]\"
168 .  if !"\\*[bc]"" \{\
169 .    ie m\\*[bc] \
170 .      ds t*bc\\n[t*#] \\*[bc]\"
171 .    el \{\
172 .      ie "\\*[bc]"=" \
173 .        ds t*bc\\n[t*#] =\"
174 .      el \
175 .        tm \\n[.F]:\\n[.c]: Invalid border color `\\*[bc]'.
176 .  \}\}
177 .  ie "\\*[bc]"=" \
178 .    ds t*bc\\n[t*#]
179 .  el \{\
180 .    ie "\\*[bc]"" \
181 .      ds t*bc\\n[t*#] \\*[t*bc]\"
182 .    el \
183 .      ds t*bc\\n[t*#] \\*[bc]\"
184 .  \}
185 .
186 .  getarg width \\*[args]               \"      table/col widths
187 .  if "\\*[width]"=" \
188 .    ds width
189 .
190 .  nr b/2\\n[t*#] (\\n[t*b\\n[t*#]] / 2)\"      shortcut
191 .  nr cscp\\n[t*#] (\\n[t*csp\\n[t*#]] + \\n[t*cpd\\n[t*#]])\"  aux. register
192 .
193 .  getarg height \\*[args]              \"      table outline height
194 .  ie "\\*[height]"" \
195 .    nr t*height\\n[t*#] 0
196 .  el \{\
197 .    ie \B\a\\*[height]\a \
198 .      nr t*height\\n[t*#] (\\*[height] \
199                             - ((2 * \\n[cscp\\n[t*#]]) \
200                                 + (3 * \\n[b/2\\n[t*#]])))
201 .    el \
202 .      tm \\n[.F]:\\n[.c]: Invalid height value `\\*[height]'.
203 .  \}
204 .
205 .  t*cl \\*[width]                      \"      get cell widths and offsets
206 .  t*args \\n[t*#]                      \"      look for common arguments
207 .
208 .  getarg tal \\*[args]                 \"      table horizontal alignment
209 .  if "\\*[tal]"" \
210 .    ds tal \\*[t*tal]\"
211 .  ie "\\*[tal]"l" \
212 .    nr in\\n[t*#] \\n[.i]
213 .  el \{\
214 .    ie "\\*[tal]"c" \
215 .      nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]]/2 + \\n[.i])
216 .    el \{\
217 .      ie "\\*[tal]"r" \
218 .        nr in\\n[t*#] (\\n[.l] - \\n[ll\\n[t*#]] + \\n[.i])
219 .      el \{\
220 .        tmc \\n[.F]:\\n[.c]: Invalid horizontal table alignment `\\*[tal]':
221 .        tm1 " must be `l', `c' or `r'.
222 .  \}\}\}
223 .
224 .  nr t*r#\\n[t*#] 0                    \"      initialize row index
225 .  mk toptbl\\n[t*#]
226 .
227 .  P1 \\*[args]
228 ..
229 .
230 .
231 .\"     CPTN:   optional table caption
232 .\"             predecessor:    TBL
233 .\"             successor:      TR
234 .de CPTN
235 .  ft 1
236 .
237 .  if "\\$0"CPTN" \
238 .    if \\n[t*r#\\n[t*#]] \{\
239 .      tmc \\n[.F]:\\n[.c]: Invalid placement of `.CPTN';
240 .      tm1 " must be called immediately after `.TBL'.
241 .      return
242 .    \}
243 .
244 .  getarg val \\$@
245 .  ds args\\n[t*#] "\\*[args]\"
246 .
247 .  index "\\*[args]" .TR
248 .  ie \\n[index] \{\
249 .    ds *a\\n[t*#] "\\*[args]\"
250 .    substring args\\n[t*#] 0 \\n[index]
251 .    substring *a\\n[t*#] \\n[index]-2 -1
252 .  \}
253 .  el \
254 .    ds *a\\n[t*#]
255 .
256 .  ie "\\*[val]"b" \{\
257 .    de t*cptn\\n[t*#]
258 .      *CPTN \\*[args\\n[t*#]]
259 .      rm t*cptn\\n[t*#]
260 \\..
261 .  \}
262 .  el \{\
263 .    ll (\\n[ll\\n[t*#]]u + \\n[in\\n[t*#]]u)
264 .    in \\n[in\\n[t*#]]u
265 .    P1 \\*[t*cptn]
266 '    in +\\n[*]u
267 .    P1 \\*[args\\n[t*#]]
268 .    pv 1 1
269 .    in
270 .    mk toptbl\\n[t*#]
271 .  \}
272 .
273 .  P1 \\*[*a\\n[t*#]]
274 ..
275 .
276 .als *CPTN CPTN
277 .
278 .
279 .\"     TR:     table row
280 .\"             predecessor:    TBL, CPTN, text, TD or ETB
281 .\"             successor:      TD
282 .de TR
283 .  ft 1
284 .  if !\\n[t*#] \{\
285 .    tm \\n[.F]:\\n[.c]: Table row (.TR) without preceding table start (.TBL).
286 .    return
287 .  \}
288 .
289 .  \" finish previous data cell, if any
290 .  if \\n[t*r#\\n[t*#]] \
291 .    t*dntr 1 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
292 .
293 .  nr t*r#\\n[t*#] +1                   \"      row number in this table
294 .  ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\"         table row identifier
295 .                                       \"      (<level>*<row>)
296 .  nr c#\\*[#t#r] 0 1                   \"      clear cell counter
297 .  nr dntr\\*[#t#r] 0 1                 \"      clear accumulated row height
298 .
299 .  getarg height \\$@
300 .  ie "\\*[height]"" \
301 .    nr t*height\\*[#t#r] 0
302 .  el \{\
303 .    ie \B\a\\*[height]\a \
304 .      nr t*height\\*[#t#r] \\*[height]
305 .    el \
306 .      tm \\n[.F]:\\n[.c]: Invalid table row height `\\*[height]'.
307 .  \}
308 .
309 .  \"   If there is a TR with height `height', the total height of the table
310 .  \"   is too high by 3/2 b, independent of the number of TR with `height'.
311 .  t*args \\*[#t#r] \\n[t*#]            \"      look for common arguments
312 .
313 .  P1 \\*[args]
314 ..
315 .
316 .
317 .\"     TH:     optional table header cell
318 .\"             predecessor:    text, TD or TR
319 .\"             successor:      text, TD, TR, TBL or ETB
320 .\"                                                             
321 .\"             cell content bolded and horizontally and vertically centered,
322 .\"             else like .TD
323 .de TH
324 .  ft 1
325 .  getarg hal \\$@
326 .  if "\\*[hal]"" \
327 .    ds hal c\"
328 .
329 .  getarg val \\*[args]
330 .  if "\\*[val]"" \
331 .    ds val m\"
332 .
333 .  getarg fst \\*[args]
334 .  if "\\*[fst]"" \
335 .    ds fst B\"
336 .
337 .  TD hal=\\*[hal] val=\\*[val] fst=\\*[fst] \\*[args]
338 ..
339 .
340 .
341 .\"     TD:     table data cell
342 .\"             predecessor:    text, TD or TR
343 .\"             successor:      text, TD, TR, TBL or ETB
344 .de TD
345 .  ft 1
346 .  \" finish previous data cell -- note the use of \E
347 .  t*dntr 0 \\n[c#\\*[#t#r]]-1 \En[c#\\*[#t#r]] \\*[*#trc*]
348 .
349 .  ds *#trc* \\*[#t#r]*\\n[c#\\*[#t#r]]\"       table cell identifier
350 .                                       \"      (<level>*<row>*<column>)
351 .
352 .  getarg rowspan \\$@
353 .  nr rowspan 1
354 .  if !"\\*[rowspan]"" \{\
355 .    ie \B\a\\*[rowspan]\a \{\
356 .      nr rowspan (\\*[rowspan] >? 1)
357 .      nr *rsp*\\*[*#trc*] (\\n[rowspan] - 1)
358 .    \}
359 .    el \
360 .      tm \\n[.F]:\\n[.c]: Invalid value of `rowspan' keyword.
361 .  \}
362 .
363 .  getarg colspan \\*[args]
364 .  nr colspan 1
365 .  if !"\\*[colspan]"" \{\
366 .    ie \B\a\\*[colspan]\a \
367 .      nr colspan (\\*[colspan] >? 1)
368 .    el \
369 .      tm \\n[.F]:\\n[.c]: Invalid value of `colspan' keyword.
370 .  \}
371 .
372 .  t*args \\*[#trc] \\*[#t#r]           \"  look for common arguments
373 .
374 .  nr in\\*[#trc] \\n[in\\n[t*#]*\\n[c#\\*[#t#r]]]
375 .  nr *cl \\n[cll\\n[t*#]*\\n[c#\\*[#t#r]]]
376 .  nr * 0 1
377 .  nr *r \\n[t*r#\\n[t*#]]
378 .
379 .  if (\\n[rowspan] - 1) \
380 .    while (\\n+[*] <= \\n[rowspan]) \{\
381 .      nr rspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
382 .      if (\\n[*] > 1) \
383 .        nr cspan\\n[t*#]*\\n[*r]*\\n[c#\\*[#t#r]] \\n[colspan]
384 .      nr *r +1
385 .    \}
386 .
387 .  nr * 1 1
388 .  nr *c \\n[c#\\*[#t#r]]
389 .
390 .  if (\\n[colspan] - 1) \{\
391 .    nr vline\\*[*#trc*] 0-1            \"      set `no vl' flag
392 .
393 .    while (\\n+[*] <= \\n[colspan]) \{\
394 .      nr *c +1
395 .      nr *cl +(2 * \\n[cscp\\n[t*#]] \
396                 + \\n[b/2\\n[t*#]] \
397                 + \\n[cll\\n[t*#]*\\n[*c]])
398 .      nr c#\\*[#t#r] +1
399 .    \}
400 .  \}
401 .
402 .  if (\\n[c#\\n[t*#]*\\n[t*r#\\n[t*#]]] > \\n[t*cols\\n[t*#]]) \{\
403 .    ds * are\"
404 .    ds ** columns\"
405 .    if (\\n[c#\\*[#t#r]] == 1) \{\
406 .      ds * is\"
407 .      ds ** column\"
408 .    \}
409 .    tmc \\n[.F]:\\n[.c]: There \\*[*] \\n[c#\\*[#t#r]] table \\*[**] (.TD)
410 .
411 .    ds * are\"
412 .    if (\\n[t*cols\\n[t*#]] == 1) \
413 .      ds * is\"
414 .    tm1 " but only \\n[t*cols\\n[t*#]] \\*[*] expected.
415 .
416 .    ds *
417 .    length * \\n[.F]:\\n[.c]:
418 .
419 .    while \\n-[*] \
420 .      ds * " \\*[*]\"
421 .
422 .    tm1 "\\*[*] Remaining .TDs and its contents are ignored.
423 .
424 .    di *t*dummy*                \"     bypass superfluous input
425 .    return
426 .  \}
427 .
428 .  di t*\\*[#trc]                \"     open cell diversion and set locals
429 .  in 0
430 .  nr cll\\*[#trc] \\n[*cl]
431 .  ll \\n[*cl]u
432 .  nr *cl\\n[t*#] \\n[.l]
433 .  gcolor \\*[t*fgc\\*[#trc]]
434 .  ad \\*[t*hal\\*[#trc]]
435 .  fam \\*[t*ff\\*[#trc]]
436 .  ft \\*[t*fst\\*[#trc]]
437 .  pv \\*[t*fsz\\*[#trc]]
438 .
439 .  P1 \\*[args]
440 ..
441 .
442 .
443 .\"     ETB:    end of table
444 .\"             predecessor:    text, TD or ETB
445 .\"             successor:      text, TD, TR or TBL
446 .de ETB
447 .  ie \\n[t*#] \
448 .    if !\\n[t*r#\\n[t*#]] \{\
449 .      tmc \\n[.F]:\\n[.c]: Each table (.TBL)
450 .      tm1 " should contain at least one table row (.TR)!
451 .    \}
452 .  el \{\
453 .    tmc \\n[.F]:\\n[.c]: Table end (.ETB)
454 .    tm1 " without corresponding table start (.TBL)!
455 .  \}
456 .
457 .  ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\"         refresh table row identifier
458 .  t*dntr 2 \\n[c#\\*[#t#r]] \\n[t*cols\\n[t*#]] \\*[*#trc*]
459 .
460 .  t*divs                        \"     print this table
461 .
462 .  sp \\n[b/2\\n[t*#]]u
463 .  t*cptn\\n[t*#]
464 .  nr t*# -1
465 .
466 .  ll \\n[*cl\\n[t*#]]u          \"     restore ll outside this table
467 .  in 0                          \"     reset indent
468 .  gcolor \\*[t*m\\n[t*#]]       \"     reset previous fgc
469 .
470 .  getarg hold \\$@
471 .  if !\\n[t*#] \{\
472 .    sp .5
473 .    di
474 .    in \\n[t*i]u
475 .    ie "\\*[hold]"" \{\
476 .      ie (\\n[.t] - \\n[dn]) \
477 .        DI t*tbl0
478 .      el \{\
479 .        rn t*tbl0 t*tbl\\n[t*numb]
480 .        ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[dn]\"
481 .      \}
482 .    \}
483 .    el \{\
484 .      rn t*tbl0 t*hold\\n+[t*numb]
485 .      tm \\n[.F]:\\n[.c]: Table t*hold\\n[t*numb] held.
486 .      ds t*held \\*[t*held] t*hold\\n[t*numb] \\n[dn]\"
487 .    \}
488 .
489 .    ev                         \"      restore previous environment
490 .  \}
491 .
492 .  P1 \\*[args]
493 ..
494 .
495 .
496 .\"     *****************************************************************
497 .\"     *       Following the definition of five utility macros         *
498 .\"     *       special to hdtbl.                                       *
499 .\"     *       Other utility macros common to hdtbl and hdgroff        *
500 .\"     *       are defined in the file hdmisc.tmac.                    *
501 .\"     *****************************************************************
502 .
503 .
504 .\"     .t*free [n]
505 .\"             print the next [n] held table[s].
506 .\"             Don't call it within a table!
507 .\"             If the table is higher than the remaining space
508 .\"             on the page, the table is printed on the next page.
509 .de t*free
510 .  if "\\$0"CPTN" \
511 .    if \\n[t*r#\\n[t*#]] \{\
512 .      tmc \\n[.F]:\\n[.c]: Invalid placement of `.t*free' within a table;
513 .      tm1 " it must be called outside of any table.
514 .      return
515 .    \}
516 .
517 .  if "\\*[t*held]"" \{\
518 .    tm \\n[.F]:\\n[.c]: No held tables.
519 .    return
520 .  \}
521 .
522 .  nr ** (\\$1 >? 1)
523 .  while !""\\*[t*held]" \{\
524 .    pops * t*held
525 .    popr * t*held
526 .
527 .    ie (\\n[.t] - \\n[*]) \{\
528 .      ev t*tbl
529 .      DI \\*[*]
530 .      ev
531 .    \}
532 .    el \{\
533 .      rn \\*[*] t*tbl\\n+[t*numb]
534 .      ds t*kept \\*[t*kept] t*tbl\\n[t*numb] \\n[*]\"
535 .    \}
536 .
537 .    if !(\\n-[**] - 1) \
538 .      return
539 .  \}
540 ..
541 .
542 .
543 .\"     The main utility macro for tables:
544 .\"             If a table is closed by ETB, this macro is called.  It
545 .\"             processes one complete table, i.e., all the table cell
546 .\"             diversions, paints the cell backgrounds, draws
547 .\"             horizontal and vertical table lines and the table border.
548 .\"
549 .\"             Nested tables are processed from inside to outside.
550 .
551 .de t*divs
552 .  ll (\\n[l]u + 1c)                    \"      avoid warning `can't break line'
553 .  nf
554 .
555 .  nr b/2 \\n[b/2\\n[t*#]]              \"      some abbreviations
556 .  nr cscp \\n[cscp\\n[t*#]]
557 .  nr cscpb (\\n[b/2] + \\n[cscp])
558 .
559 .  nr topdiv (\\n[.d] + \\n[b/2] - \\n[cscp])\" top of cell diversion
560 .  nr cscpb2 (\\n[b/2] / 2 + \\n[cscp])
561 .
562 .  nr #r 0 1
563 .  \" outer loop for rows
564 .  while (\\n+[#r] <= \\n[t*r#\\n[t*#]]) \{\
565 .    \" TODO: insert code here for multipage tables
566 .    nr * (\\n[#r] - 1)
567 .    nr topdiv +(\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
568 .
569 .    \" if table still smaller than specified table height, increase it
570 .    if ((\\n[#r] == \\n[t*r#\\n[t*#]]) & \\n[t*height\\n[t*#]]) \
571 .      nr dntr\\n[t*#]*\\n[#r] (\\n[cscpb] \
572                                 + \\n[toptbl\\n[t*#]] \
573                                 + \\n[t*height\\n[t*#]] \
574                                 - (\\n[topdiv] >? \\n[dntr\\n[t*#]*\\n[#r]]))
575 .
576 .    nr #c 0 1
577 .    \" inner loop for cells
578 .    while (\\n+[#c] <= \\n[t*cols\\n[t*#]]) \{\
579 .      ds #trc \\n[t*#]*\\n[#r]*\\n[#c]\"
580 .      \" continue if the diversion is empty
581 .      if !d t*\\*[#trc] \
582 .        continue
583 .
584 .      sp |\\n[topdiv]u
585 .      in (\\n[in\\n[t*#]]u + \\n[in\\*[#trc]]u)\"      cell offset
586 .      nr $1 \\n[dntr\\n[t*#]*\\n[#r]]  \"      cell height
587 .
588 .      \" if we have spanned rows, calculate resulting row height
589 .      \" and position of lower horizontal line
590 .      if \\n[*rsp*\\*[#trc]] \{\
591 .        nr * \\n[#r] 1
592 .        nr rspan\\*[#trc] 0-1          \"      set `no hl' flag
593 .        nr corr (\\n[dn\\*[#trc]] - \\n[dntr\\n[t*#]*\\n[#r]])
594 .
595 .        \" clear row span flags in following rows and update row height
596 .        while \\n[*rsp*\\*[#trc]] \{\
597 .          nr *rsp*\\*[#trc] -1
598 .          nr rspan\\n[t*#]*\\n+[*]*\\n[#c] 0
599 .          nr ** (\\n[dntr\\n[t*#]*\\n[*]] + \\n[cscp] + \\n[cscpb])
600 .          nr corr -\\n[**]
601 .          nr $1 +\\n[**]
602 .        \}
603 .
604 .        if (\\n-[*] == \\n[t*r#\\n[t*#]]) \
605 .          nr $1 ((\\n[t*height\\n[t*#]] \
606                    - \\n[.d] \
607                    + \\n[toptbl\\n[t*#]] \
608                    + \\n[cscpb]) \
609                      >? \\n[$1])
610 .        nr dntr\\n[t*#]*\\n[*] +(\\n[corr] >? 0)
611 .      \}
612 .
613 .      \" paint cell background
614 .      nr * (2 * \\n[t*cpd\\n[t*#]] + \\n[cll\\*[#trc]])\"      background width
615 .      nr $1 (\\n[$1] >? \\n[dn\\*[#trc]])\"    cell height
616 .
617 .      if !"\\*[t*bgc\\*[#trc]]"=" \{\
618 .        nop \h'\\n[t*csp\\n[t*#]]u'\
619 \M[\\*[t*bgc\\*[#trc]]]\
620 \v'(-.67v - \\n[t*cpd\\n[t*#]]u)'\
621 \D'P \\n[*]u 0 \
622      0 (2u * \\n[t*cpd\\n[t*#]]u + \\n[$1]u) \
623      -\\n[*]u 0'\
624 \M[]
625 .        sp -1
626 .      \}
627 .
628 .      \" ***   horizontal and vertical single or double lines   ***
629 .      \" double and single lines have the same thickness;
630 .      \" the double lines' distance is the line thickness.
631 .      \"
632 .      \" `border=x': horizontal/vertical lines x/2 thick, minimum .1n
633 .      \" `border=0': no border; horizontal/vertical lines .1n thick
634 .      \" `border=': neither border nor horizontal/vertical lines
635 .
636 .      nr *t (.1n >? \\n[b/2])          \"      thickness of hl/vl; min. .1n
637 .      in +\\n[cscp]u
638 .
639 .      \" check for vertical and horizontal lines
640 .      if (1 + \\n[t*b\\n[t*#]]) \{\
641 .        if !"\\*[t*bc\\n[t*#]]"=" \{\
642 .          \" draw horizontal line between this cell and the one below
643 .          if (\\n[t*r#\\n[t*#]] - \\n[#r] + \\n[rspan\\*[#trc]]) \{\
644 .            if !"\\*[t*hl\\*[#trc]]"=" \{\
645 .              sp \\n[$1]u
646 .              nr * (\\n[cscp] + \\n[cscpb] + \\n[cll\\*[#trc]])
647 .              nop \X'\*[g] 1 setlinecap'\
648 \h'(-\\n[cscpb2]u - \\n[*t]u)'\
649 \v'(\\n[cscpb2]u - .67v)'\
650 \m[\\*[t*bc\\n[t*#]]]\
651 \D't \\n[*t]u'\c
652 .
653 .              ie "\\*[t*hl\\*[#trc]]"d" \
654 .                nop \v'-\\n[*t]u'\
655 \D'l \\n[*]u 0'\
656 \v'(2u * \\n[*t]u)'\
657 \D'l -\\n[*]u 0'\
658 \D't 0'
659 .              el \
660 .                nop \D'l \\n[*]u 0'\
661 \D't 0'
662 .
663 .              sp (-\\n[$1]u - 1v)
664 .          \}\}
665 .
666 .          nr rspan\\*[#trc] 0
667 .
668 .          \" draw vertical line between this cell and the one to the right
669 .          if (\\n[t*cols\\n[t*#]] - \\n[#c] + \\n[vline\\*[#trc]]) \{\
670 .            if !"\\*[t*vl\\*[#trc]]"=" \{\
671 .              nop \X'\*[g] 1 setlinecap'\
672 \v'(-\\n[cscpb2]u - .67v)'\
673 \m[\\*[t*bc\\n[t*#]]]\
674 \h'(\\n[cscpb2]u - \\n[*t]u + \\n[cll\\*[#trc]]u)'\c
675 .
676 .              ie "\\*[t*vl\\*[#trc]]"d" \
677 .                nop \h'-\\n[*t]u'\
678 \D't \\n[*t]u'\
679 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
680 \h'(2u * \\n[*t]u)'\
681 \D'l 0 -(2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
682 \D't 0'
683 .              el \
684 .                nop \D't \\n[*t]u'\
685 \D'l 0 (2u * \\n[cscp]u + \\n[$1]u + (\\n[*t]u / 2u))'\
686 \D't 0'
687 .              sp -1
688 .      \}\}\}\}
689 .
690 .      nr vline\\*[#trc] 0
691 .
692 .      \" vert. cell content alignment
693 .      nr ** 0
694 .
695 .      ie "\\*[t*val\\*[#trc]]"m" \
696 .        nr ** ((\\n[$1] - \\n[dn\\*[#trc]]) / 2)\"     val=m
697 .      el \
698 .        if "\\*[t*val\\*[#trc]]"b" \
699 .          nr ** (\\n[$1] - \\n[dn\\*[#trc]])\" val=b
700 .
701 .      sp \\n[**]u                      \"      vertical content position
702 .
703 .      \" finally output the diversion
704 .      t*\\*[#trc]
705 .      rm t*\\*[#trc]
706 .    \}
707 .  \}
708 .
709 .  \" draw the box border
710 .  in \\n[in\\n[t*#]]u
711 .  nr ** (\\n[topdiv] + \\n[dntr\\n[t*#]*\\n-[#r]])
712 .
713 .  if \\n[t*b\\n[t*#]] \{\
714 .    sp |(\\n[toptbl\\n[t*#]]u + \\n[b/2]u)
715 .    nr $1 (\\n[toptbl\\n[t*#]] - \\n[**] - \\n[cscp])
716 .    nr * (\\n[ll\\n[t*#]] - \\n[t*b\\n[t*#]])
717 .
718 .    if !"\\*[t*bc\\n[t*#]]"=" \
719 .      nop \X'\*[g] 0 setlinejoin 2 setlinecap'\
720 \v'-.67v'\
721 \h'-\\n[b/2]u'\
722 \m[\\*[t*bc\\n[t*#]]]\
723 \D't \\n[t*b\\n[t*#]]u'\
724 \D'l \\n[*]u 0'\
725 \D'l 0 -\\n[$1]u'\
726 \D'l -\\n[*]u 0'\
727 \D'l 0 \\n[$1]u'\
728 \D't 0'
729 .  \}
730 .
731 .  sp |(\\n[**]u + \\n[cscpb]u)
732 .  fi
733 ..
734 .
735 .
736 .\"     Utility macro:  .t*cl [width1 [width2 [...]]]
737 .\"
738 .\"             Calculate cell widths, table width, and cell offsets.
739 .de t*cl
740 .  nr t*cols\\n[t*#] (\\n[.$] >? \\n[t*cols\\n[t*#]])
741 .  nr ll\\n[t*#] 0                      \"      accumulated cell widths
742 .  nr ** (\\n[.l] / \\n[t*cols\\n[t*#]])\"      width for remaining cells
743 .  nr * 0 1                             \"      counter
744 .
745 .  \" while-loop: Parse user arguments to get each cell's width.
746 .  while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
747 .    nr $\\n[*] \\n[**]
748 .    if !"\\$[\\n[*]]"" \{\
749 .      \" check for `%' pseudo scaling indicator
750 .      ds * \\$\\n[*]\"
751 .      substring * -1 -1
752 .      ie "\\*[*]"%" \{\
753 .        ds ** \\$[\\n[*]]\"
754 .        substring ** 0 -2
755 .        ie \B\a\\*[**]\a \
756 .          nr $\\n[*] (\\*[**] * \\n[.l] / 100)
757 .        el \
758 .          tm \\n[.F]:\\n[.c]: Invalid relative cell width `\\*[**]%'.
759 .      \}
760 .      el \{\
761 .        ie \B\a\\$[\\n[*]]\a \
762 .          nr $\\n[*] \\$[\\n[*]]
763 .        el \
764 .          tm \\n[.F]:\\n[.c]: Invalid cell width `\\$[\\n[*]]'.
765 .    \}\}
766 .
767 .    nr ll\\n[t*#] +\\n[$\\n[*]]
768 .    nr ** \\n[$\\n[*]]
769 .  \}
770 .
771 .  if (\\n[ll\\n[t*#]] > \\n[.l]) \
772 .    tm \\n[.F]:\\n[.c]: Table width larger than column width.
773 .
774 .  nr ** (0 >? \\n[t*b\\n[t*#]])
775 .  nr * 0 1
776 .
777 .  \" second while loop: Compute final cell widths.
778 .  while (\\n[t*cols\\n[t*#]] >= \\n+[*]) \{\
779 .    \" Remove border width, if any.
780 .    if \\n[t*b\\n[t*#]] \{\
781 .      \" cell_width := cell_width * (length - 1.5*border) / length
782 .      nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
783 .      nr *** (\\n[ll\\n[t*#]] / 2)
784 .      \" avoid multiplication overflow
785 .      mult31by31 $\\n[*] #* ****
786 .      add31to62 *** **** ****
787 .      div62by31 **** ll\\n[t*#] $\\n[*]
788 .    \}
789 .
790 .    \" Get cell widths without padding, spacing, and separator line.
791 .    nr cll\\n[t*#]*\\n[*] (\\n[$\\n[*]] \
792                             - (2 * \\n[cscp\\n[t*#]]) \
793                             - \\n[b/2\\n[t*#]])
794 .
795 .    \" Check whether value is non-positive.
796 .    if !\\n[cll\\n[t*#]*\\n[*]] \{\
797 .      nr #* (\\n[ll\\n[t*#]] - (3 * \\n[t*b\\n[t*#]] / 2))
798 .      nr *** (\\n[#*] / 2)
799 .      nr *h (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])
800 .      mult31by31 *h ll\\n[t*#] ****
801 .      add31to62 *** **** ****
802 .      div62by31 **** #* *h
803 .      ds * \\n[*]th\"
804 .      nr *** (\\n[*] % 10)
805 .      if d nth-\\n[***] \
806 .        ds * \\n[*]\\*[nth-\\n[***]]\"
807 .      tmc \\n[.F]:\\n[.c]: The \\*[*] width value (\\$\\n[*]) is too small.
808 .      tm1 " It should be greater than \\n[*h].
809 .    \}
810 .
811 .    nr in\\n[t*#]*\\n[*] \\n[**]       \"      cell offset
812 .    nr ** +\\n[$\\n[*]]
813 .  \}
814 ..
815 .
816 .
817 .\"     Utility macro:  .t*dntr <origin> <cell position> ? <cell ID>
818 .\"
819 .\"             Close TD diversion, make some calculations, and set
820 .\"             some help strings and registers.  <origin> is 0, 1,
821 .\"             or 2 if the call of .t*dntr occurs in .TD, .TR, or
822 .\"             .ETB, respectively.
823 .de t*dntr
824 .  nr dn 0                              \"      reset diversion height
825 .  br                                   \"      finish cell data
826 .
827 .  if "\\n[.z]"*t*dummy*" \
828 .    return
829 .
830 .  ds #t#r \\n[t*#]*\\n[t*r#\\n[t*#]]\"         refresh table row identifier
831 .
832 .  if \\n[c#\\*[#t#r]] \{\
833 .    di                                 \"      close diversion
834 .    nr dn\\$4 \\n[dn]                  \"      save height of this cell
835 .    if !\\n[rspan\\*[#trc]] \{\
836 .      \" update row height if not in a row span
837 .      nr dntr\\*[#t#r] (\\n[dntr\\*[#t#r]] >? \\n[dn])
838 .      if \\$2 \
839 .        nr dntr\\*[#t#r] ((\\n[t*height\\*[#t#r]] \
840                             - (2 * \\n[cscp\\n[t*#]] + \\n[b/2\\n[t*#]])) \
841                             >? \\n[dntr\\*[#t#r]])
842 .  \}\}
843 .
844 .  nr c#\\*[#t#r] +1
845 .  nr * \\$2
846 .
847 .  \" update column span registers
848 .  while (\\n+[*] <= \\$3) \{\
849 .    if r cspan\\*[#t#r]*\\n[*] \
850 .      nr c#\\*[#t#r] +\\n[cspan\\*[#t#r]*\\n[*]]
851 .    nr cspan\\*[#t#r]*\\n[*] 0
852 .  \}
853 .
854 .  ds #trc \\*[#t#r]*\\n[c#\\*[#t#r]]\"
855 .
856 .  \" only check for cell underflow if called by .TR or .ETB
857 .  if (\\$1 & (\\n[c#\\*[#t#r]] <= \\n[t*cols\\n[t*#]])) \{\
858 .    ds * are\"
859 .    ds ** columns\"
860 .    if (\\n-[c#\\*[#t#r]] == 1) \{\
861 .      ds * is\"
862 .      ds ** column\"
863 .    \}
864 .    tmc \\n[.F]:\\n[.c]: There \\*[*] only \\n[c#\\*[#t#r]] \\*[**]
865 .
866 .    nr * \\n[t*r#\\n[t*#]]
867 .    ds * \\n[*]th\"
868 .    nr *** (\\n[*] % 10)
869 .    if d nth-\\n[***] \
870 .      ds * \\n[*]\\*[nth-\\n[***]]\"
871 .    tmc " in the \\*[*] row
872 .
873 .    ds * are\"
874 .    if (\\n[t*cols\\n[t*#]] == 1) \
875 .      ds * is\"
876 .    tm1 " but \\n[t*cols\\n[t*#]] \\*[*] expected.
877 .  \}
878 ..
879 .
880 .
881 .\"     Utility-macro:  .t*args level_1 [level_2]
882 .\"
883 .\"             Get the arguments common to TBL, TR, and TD for the level
884 .\"             in argument 1, using default values from the level in
885 .\"             argument 2.  If argument 2 is missing, use the global
886 .\"             default values.
887 .\"
888 .de t*args
889 .  ds t*bgc\\$1 \\*[t*bgc\\$2]\"
890 .  ds t*fgc\\$1 \\*[t*fgc\\$2]\"
891 .  ds t*hl\\$1 \\*[t*hl\\$2]\"
892 .  ds t*vl\\$1 \\*[t*vl\\$2]\"
893 .  ds t*hal\\$1 \\*[t*hal\\$2]\"
894 .  ds t*val\\$1 \\*[t*val\\$2]\"
895 .  ds t*ff\\$1 \\*[t*ff\\$2]\"
896 .  ds t*fst\\$1 \\*[t*fst\\$2]\"
897 .  ds t*fsz\\$1 \\*[t*fsz\\$2]\"
898 .
899 .  if "\\*[args]"" \
900 .    return
901 .
902 .  getarg bgc \\*[args]         \"      background color
903 .  if !"\\*[bgc]"" \{\
904 .    ie m\\*[bgc] \
905 .      ds t*bgc\\$1 \\*[bgc]\"
906 .    el \{\
907 .      ie "\\*[bgc]"=" \
908 .        ds t*bgc\\$1 =\"
909 .      el \
910 .        tm \\n[.F]:\\n[.c]: Invalid background color `\\*[bgc]'.
911 .  \}\}
912 .  if "\\*[args]"" \
913 .    return
914 .
915 .  getarg fgc \\*[args]         \"      foreground color
916 .  if !"\\*[fgc]"" \{\
917 .    ie m\\*[fgc] \
918 .      ds t*fgc\\$1 \\*[fgc]\"
919 .    el \{\
920 .      ie "\\*[fgc]"=" \
921 .        ds t*fgc\\$1 =\"
922 .      el \
923 .        tm \\n[.F]:\\n[.c]: Invalid foreground color `\\*[fgc]'.
924 .  \}\}
925 .  if "\\*[args]"" \
926 .    return
927 .
928 .  getarg hl \\*[args]          \"      horizontal line between cells
929 .  if !"\\*[hl]"" \
930 .    ds t*hl\\$1 \\*[hl]\"
931 .  if "\\*[args]"" \
932 .    return
933 .
934 .  getarg vl \\*[args]          \"      vertical line between cells
935 .  if !"\\*[vl]"" \
936 .    ds t*vl\\$1 \\*[vl]\"
937 .  if "\\*[args]"" \
938 .    return
939 .
940 .  getarg hal \\*[args]         \"      horizontal table cell alignment
941 .  if !"\\*[hal]"" \{\
942 .    index bcrl \\*[hal]
943 .    ie \\n[index] \
944 .      ds t*hal\\$1 \\*[hal]\"
945 .    el \{\
946 .      tmc \\n[.F]:\\n[.c]: Invalid horizontal alignment `\\*[hal]':
947 .      tm1 " must be `b', `c', `l' or `r'.
948 .  \}\}
949 .  if "\\*[args]"" \
950 .    return
951 .
952 .  getarg val \\*[args]         \"      vertical table cell alignment
953 .  if !"\\*[val]"" \{\
954 .    index tmb \\*[val]
955 .    ie \\n[index] \
956 .      ds t*val\\$1 \\*[val]\"
957 .    el \{\
958 .      tmc \\n[.F]:\\n[.c]: Invalid vertical alignment `\\*[val]':
959 .      tm1 " must be `t', `m' or `b'.
960 .  \}\}
961 .  if "\\*[args]"" \
962 .    return
963 .
964 .  getarg ff \\*[args]          \"      font family
965 .  if !"\\*[ff]"" \
966 .    ds t*ff\\$1 \\*[ff]\"
967 .  if "\\*[args]"" \
968 .    return
969 .
970 .  getarg fst \\*[args]         \"      font style
971 .  if !"\\*[fst]"" \
972 .    ds t*fst\\$1 \\*[fst]\"
973 .  if "\\*[args]"" \
974 .    return
975 .
976 .  getarg fsz \\*[args]         \"      font size and spacing factor
977 .  if !"\\*[fsz]"" \
978 .    ds t*fsz\\$1 \\*[fsz]\"
979 ..
980 .
981 .
982 .de t*hm
983 .  ev t*tbl
984 .  nr ** \\n[.t]
985 .  while !""\\*[t*kept]" \{\
986 .    pops * t*kept
987 .    popr * t*kept
988 .    if (\\n[*] - \\n[**]) \{\
989 .      tm \\n[.F]:\\n[.c]: Table \\*[*] higher than page -- ignored!
990 .      break
991 .    \}
992 .
993 .    if (\\n[*] - \\n[.t]) \{\
994 .      ds t*kept \\n[*] \\*[t*kept]\"
995 .      ds t*kept \\*[*] \\*[t*kept]\"
996 .      tmc \\n[.F]:\\n[.c]: Remaining table(s),
997 .      tm1 " because not all fit onto this page.
998 .      break
999 .    \}
1000 .
1001 .    DI \\*[*]
1002 .  \}
1003 .  ev
1004 ..
1005 .
1006 .\" EOF