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