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