Annotation of mandoc/man_term.c, Revision 1.55
1.55 ! kristaps 1: /* $Id: man_term.c,v 1.54 2009/11/12 08:21:05 kristaps Exp $ */
1.1 kristaps 2: /*
1.9 kristaps 3: * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
1.1 kristaps 4: *
5: * Permission to use, copy, modify, and distribute this software for any
1.8 kristaps 6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
1.1 kristaps 8: *
1.8 kristaps 9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.1 kristaps 16: */
1.55 ! kristaps 17: #ifdef HAVE_CONFIG_H
! 18: #include "config.h"
! 19: #endif
! 20:
1.28 kristaps 21: #include <sys/types.h>
22:
1.1 kristaps 23: #include <assert.h>
1.18 kristaps 24: #include <ctype.h>
1.1 kristaps 25: #include <stdio.h>
26: #include <stdlib.h>
27: #include <string.h>
28:
1.40 kristaps 29: #include "out.h"
1.36 kristaps 30: #include "man.h"
1.1 kristaps 31: #include "term.h"
1.36 kristaps 32: #include "chars.h"
33: #include "main.h"
1.1 kristaps 34:
1.18 kristaps 35: #define INDENT 7
36: #define HALFINDENT 3
37:
1.44 kristaps 38: /* FIXME: have PD set the default vspace width. */
39:
1.24 kristaps 40: struct mtermp {
41: int fl;
1.19 kristaps 42: #define MANT_LITERAL (1 << 0)
1.26 kristaps 43: /*
44: * Default amount to indent the left margin after leading text
45: * has been printed (e.g., `HP' left-indent, `TP' and `IP' body
46: * indent). This needs to be saved because `HP' and so on, if
47: * not having a specified value, must default.
48: *
49: * Note that this is the indentation AFTER the left offset, so
50: * the total offset is usually offset + lmargin.
51: */
52: size_t lmargin;
53: /*
54: * The default offset, i.e., the amount between any text and the
55: * page boundary.
56: */
57: size_t offset;
1.24 kristaps 58: };
1.19 kristaps 59:
1.1 kristaps 60: #define DECL_ARGS struct termp *p, \
1.24 kristaps 61: struct mtermp *mt, \
1.1 kristaps 62: const struct man_node *n, \
63: const struct man_meta *m
64:
65: struct termact {
66: int (*pre)(DECL_ARGS);
67: void (*post)(DECL_ARGS);
68: };
69:
1.45 kristaps 70: static int a2width(const struct man_node *);
71: static int a2height(const struct man_node *);
1.39 kristaps 72:
1.45 kristaps 73: static void print_man_head(struct termp *,
1.39 kristaps 74: const struct man_meta *);
1.52 kristaps 75: static void print_man_nodelist(DECL_ARGS);
1.45 kristaps 76: static void print_man_node(DECL_ARGS);
77: static void print_man_foot(struct termp *,
1.39 kristaps 78: const struct man_meta *);
79: static void print_bvspace(struct termp *,
80: const struct man_node *);
81:
1.1 kristaps 82: static int pre_B(DECL_ARGS);
1.3 kristaps 83: static int pre_BI(DECL_ARGS);
1.19 kristaps 84: static int pre_HP(DECL_ARGS);
1.1 kristaps 85: static int pre_I(DECL_ARGS);
1.4 kristaps 86: static int pre_IP(DECL_ARGS);
1.1 kristaps 87: static int pre_PP(DECL_ARGS);
1.3 kristaps 88: static int pre_RB(DECL_ARGS);
89: static int pre_RI(DECL_ARGS);
1.26 kristaps 90: static int pre_RS(DECL_ARGS);
1.1 kristaps 91: static int pre_SH(DECL_ARGS);
92: static int pre_SS(DECL_ARGS);
93: static int pre_TP(DECL_ARGS);
1.19 kristaps 94: static int pre_br(DECL_ARGS);
95: static int pre_fi(DECL_ARGS);
1.29 kristaps 96: static int pre_ign(DECL_ARGS);
1.19 kristaps 97: static int pre_nf(DECL_ARGS);
98: static int pre_sp(DECL_ARGS);
1.1 kristaps 99:
1.22 kristaps 100: static void post_IP(DECL_ARGS);
1.20 kristaps 101: static void post_HP(DECL_ARGS);
1.26 kristaps 102: static void post_RS(DECL_ARGS);
1.1 kristaps 103: static void post_SH(DECL_ARGS);
104: static void post_SS(DECL_ARGS);
1.21 kristaps 105: static void post_TP(DECL_ARGS);
1.1 kristaps 106:
1.32 kristaps 107: static const struct termact termacts[MAN_MAX] = {
1.15 kristaps 108: { pre_br, NULL }, /* br */
1.1 kristaps 109: { NULL, NULL }, /* TH */
110: { pre_SH, post_SH }, /* SH */
111: { pre_SS, post_SS }, /* SS */
1.21 kristaps 112: { pre_TP, post_TP }, /* TP */
1.1 kristaps 113: { pre_PP, NULL }, /* LP */
114: { pre_PP, NULL }, /* PP */
115: { pre_PP, NULL }, /* P */
1.22 kristaps 116: { pre_IP, post_IP }, /* IP */
1.20 kristaps 117: { pre_HP, post_HP }, /* HP */
1.1 kristaps 118: { NULL, NULL }, /* SM */
1.52 kristaps 119: { pre_B, NULL }, /* SB */
1.3 kristaps 120: { pre_BI, NULL }, /* BI */
1.35 kristaps 121: { pre_BI, NULL }, /* IB */
122: { pre_RB, NULL }, /* BR */
1.3 kristaps 123: { pre_RB, NULL }, /* RB */
1.1 kristaps 124: { NULL, NULL }, /* R */
1.52 kristaps 125: { pre_B, NULL }, /* B */
126: { pre_I, NULL }, /* I */
1.49 kristaps 127: { pre_RI, NULL }, /* IR */
1.3 kristaps 128: { pre_RI, NULL }, /* RI */
1.27 kristaps 129: { NULL, NULL }, /* na */
1.53 kristaps 130: { pre_I, NULL }, /* i */
1.19 kristaps 131: { pre_sp, NULL }, /* sp */
132: { pre_nf, NULL }, /* nf */
133: { pre_fi, NULL }, /* fi */
1.52 kristaps 134: { NULL, NULL }, /* r */
1.25 kristaps 135: { NULL, NULL }, /* RE */
1.26 kristaps 136: { pre_RS, post_RS }, /* RS */
1.29 kristaps 137: { pre_ign, NULL }, /* DT */
138: { pre_ign, NULL }, /* UC */
1.44 kristaps 139: { pre_ign, NULL }, /* PD */
1.1 kristaps 140: };
141:
142:
143:
1.31 kristaps 144: void
1.36 kristaps 145: terminal_man(void *arg, const struct man *man)
1.1 kristaps 146: {
1.36 kristaps 147: struct termp *p;
148: const struct man_node *n;
149: const struct man_meta *m;
150: struct mtermp mt;
151:
152: p = (struct termp *)arg;
153:
154: if (NULL == p->symtab)
155: switch (p->enc) {
156: case (TERMENC_ASCII):
157: p->symtab = chars_init(CHARS_ASCII);
158: break;
159: default:
160: abort();
161: /* NOTREACHED */
162: }
163:
164: n = man_node(man);
165: m = man_meta(man);
1.1 kristaps 166:
1.45 kristaps 167: print_man_head(p, m);
1.1 kristaps 168: p->flags |= TERMP_NOSPACE;
1.19 kristaps 169:
1.24 kristaps 170: mt.fl = 0;
171: mt.lmargin = INDENT;
1.26 kristaps 172: mt.offset = INDENT;
1.24 kristaps 173:
1.36 kristaps 174: if (n->child)
1.52 kristaps 175: print_man_nodelist(p, &mt, n->child, m);
1.45 kristaps 176: print_man_foot(p, m);
1.1 kristaps 177: }
178:
179:
1.39 kristaps 180: static int
1.45 kristaps 181: a2height(const struct man_node *n)
1.18 kristaps 182: {
1.40 kristaps 183: struct roffsu su;
1.18 kristaps 184:
1.39 kristaps 185: assert(MAN_TEXT == n->type);
186: assert(n->string);
1.40 kristaps 187: if ( ! a2roffsu(n->string, &su, SCALE_VS))
188: SCALE_VS_INIT(&su, strlen(n->string));
1.18 kristaps 189:
1.41 kristaps 190: return((int)term_vspan(&su));
1.18 kristaps 191: }
192:
193:
194: static int
1.45 kristaps 195: a2width(const struct man_node *n)
1.38 kristaps 196: {
1.40 kristaps 197: struct roffsu su;
1.38 kristaps 198:
1.39 kristaps 199: assert(MAN_TEXT == n->type);
200: assert(n->string);
1.40 kristaps 201: if ( ! a2roffsu(n->string, &su, SCALE_BU))
1.41 kristaps 202: return(-1);
1.40 kristaps 203:
1.41 kristaps 204: return((int)term_hspan(&su));
1.38 kristaps 205: }
206:
207:
1.39 kristaps 208: static void
209: print_bvspace(struct termp *p, const struct man_node *n)
1.18 kristaps 210: {
1.39 kristaps 211: term_newln(p);
1.18 kristaps 212:
1.39 kristaps 213: if (NULL == n->prev)
214: return;
1.18 kristaps 215:
1.39 kristaps 216: if (MAN_SS == n->prev->tok)
217: return;
218: if (MAN_SH == n->prev->tok)
219: return;
1.18 kristaps 220:
1.39 kristaps 221: term_vspace(p);
1.18 kristaps 222: }
223:
224:
1.3 kristaps 225: /* ARGSUSED */
1.1 kristaps 226: static int
1.29 kristaps 227: pre_ign(DECL_ARGS)
228: {
229:
230: return(0);
231: }
232:
233:
234: /* ARGSUSED */
235: static int
1.1 kristaps 236: pre_I(DECL_ARGS)
237: {
238:
1.52 kristaps 239: term_fontrepl(p, TERMFONT_UNDER);
1.19 kristaps 240: return(1);
241: }
242:
243:
244: /* ARGSUSED */
1.3 kristaps 245: static int
1.19 kristaps 246: pre_fi(DECL_ARGS)
247: {
248:
1.24 kristaps 249: mt->fl &= ~MANT_LITERAL;
1.19 kristaps 250: return(1);
251: }
252:
253:
254: /* ARGSUSED */
255: static int
256: pre_nf(DECL_ARGS)
257: {
258:
259: term_newln(p);
1.24 kristaps 260: mt->fl |= MANT_LITERAL;
1.19 kristaps 261: return(1);
262: }
263:
264:
265: /* ARGSUSED */
266: static int
1.35 kristaps 267: pre_RB(DECL_ARGS)
1.3 kristaps 268: {
269: const struct man_node *nn;
270: int i;
271:
272: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
1.35 kristaps 273: if (i % 2 && MAN_RB == n->tok)
1.52 kristaps 274: term_fontrepl(p, TERMFONT_BOLD);
1.35 kristaps 275: else if ( ! (i % 2) && MAN_RB != n->tok)
1.52 kristaps 276: term_fontrepl(p, TERMFONT_BOLD);
277: else
278: term_fontrepl(p, TERMFONT_NONE);
1.35 kristaps 279:
1.4 kristaps 280: if (i > 0)
281: p->flags |= TERMP_NOSPACE;
1.35 kristaps 282:
1.45 kristaps 283: print_man_node(p, mt, nn, m);
1.3 kristaps 284: }
285: return(0);
286: }
287:
288:
289: /* ARGSUSED */
290: static int
291: pre_RI(DECL_ARGS)
292: {
293: const struct man_node *nn;
294: int i;
295:
296: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
1.49 kristaps 297: if (i % 2 && MAN_RI == n->tok)
1.52 kristaps 298: term_fontrepl(p, TERMFONT_UNDER);
1.49 kristaps 299: else if ( ! (i % 2) && MAN_RI != n->tok)
1.52 kristaps 300: term_fontrepl(p, TERMFONT_UNDER);
301: else
302: term_fontrepl(p, TERMFONT_NONE);
1.49 kristaps 303:
1.4 kristaps 304: if (i > 0)
305: p->flags |= TERMP_NOSPACE;
1.52 kristaps 306:
1.45 kristaps 307: print_man_node(p, mt, nn, m);
1.3 kristaps 308: }
309: return(0);
310: }
311:
312:
313: /* ARGSUSED */
314: static int
315: pre_BI(DECL_ARGS)
316: {
1.35 kristaps 317: const struct man_node *nn;
318: int i;
1.3 kristaps 319:
320: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
1.35 kristaps 321: if (i % 2 && MAN_BI == n->tok)
1.52 kristaps 322: term_fontrepl(p, TERMFONT_UNDER);
1.35 kristaps 323: else if (i % 2)
1.52 kristaps 324: term_fontrepl(p, TERMFONT_BOLD);
1.35 kristaps 325: else if (MAN_BI == n->tok)
1.52 kristaps 326: term_fontrepl(p, TERMFONT_BOLD);
1.30 kristaps 327: else
1.52 kristaps 328: term_fontrepl(p, TERMFONT_UNDER);
1.35 kristaps 329:
330: if (i)
1.4 kristaps 331: p->flags |= TERMP_NOSPACE;
1.52 kristaps 332:
1.45 kristaps 333: print_man_node(p, mt, nn, m);
1.3 kristaps 334: }
335: return(0);
336: }
337:
338:
339: /* ARGSUSED */
1.1 kristaps 340: static int
341: pre_B(DECL_ARGS)
342: {
343:
1.52 kristaps 344: term_fontrepl(p, TERMFONT_BOLD);
1.1 kristaps 345: return(1);
346: }
347:
348:
1.3 kristaps 349: /* ARGSUSED */
1.1 kristaps 350: static int
1.19 kristaps 351: pre_sp(DECL_ARGS)
352: {
353: int i, len;
354:
1.45 kristaps 355: len = n->child ? a2height(n->child) : 1;
1.38 kristaps 356:
1.19 kristaps 357: if (0 == len)
358: term_newln(p);
359: for (i = 0; i < len; i++)
360: term_vspace(p);
361:
362: return(0);
363: }
364:
365:
366: /* ARGSUSED */
367: static int
1.15 kristaps 368: pre_br(DECL_ARGS)
369: {
370:
371: term_newln(p);
372: return(0);
373: }
374:
375:
376: /* ARGSUSED */
377: static int
1.19 kristaps 378: pre_HP(DECL_ARGS)
379: {
1.24 kristaps 380: size_t len;
381: int ival;
382: const struct man_node *nn;
1.19 kristaps 383:
1.20 kristaps 384: switch (n->type) {
385: case (MAN_BLOCK):
1.39 kristaps 386: print_bvspace(p, n);
1.24 kristaps 387: return(1);
1.20 kristaps 388: case (MAN_BODY):
389: p->flags |= TERMP_NOBREAK;
390: p->flags |= TERMP_TWOSPACE;
391: break;
392: default:
393: return(0);
394: }
395:
1.26 kristaps 396: len = mt->lmargin;
1.24 kristaps 397: ival = -1;
398:
399: /* Calculate offset. */
400:
1.39 kristaps 401: if (NULL != (nn = n->parent->head->child))
1.45 kristaps 402: if ((ival = a2width(nn)) >= 0)
1.24 kristaps 403: len = (size_t)ival;
404:
405: if (0 == len)
406: len = 1;
407:
1.26 kristaps 408: p->offset = mt->offset;
409: p->rmargin = mt->offset + len;
1.24 kristaps 410:
411: if (ival >= 0)
1.26 kristaps 412: mt->lmargin = (size_t)ival;
1.24 kristaps 413:
1.19 kristaps 414: return(1);
415: }
416:
417:
418: /* ARGSUSED */
1.20 kristaps 419: static void
420: post_HP(DECL_ARGS)
421: {
422:
423: switch (n->type) {
1.24 kristaps 424: case (MAN_BLOCK):
425: term_flushln(p);
426: break;
1.20 kristaps 427: case (MAN_BODY):
428: term_flushln(p);
429: p->flags &= ~TERMP_NOBREAK;
430: p->flags &= ~TERMP_TWOSPACE;
1.26 kristaps 431: p->offset = mt->offset;
1.20 kristaps 432: p->rmargin = p->maxrmargin;
433: break;
434: default:
435: break;
436: }
437: }
438:
439:
440: /* ARGSUSED */
1.19 kristaps 441: static int
1.1 kristaps 442: pre_PP(DECL_ARGS)
443: {
444:
1.19 kristaps 445: switch (n->type) {
446: case (MAN_BLOCK):
1.24 kristaps 447: mt->lmargin = INDENT;
1.39 kristaps 448: print_bvspace(p, n);
1.19 kristaps 449: break;
450: default:
1.26 kristaps 451: p->offset = mt->offset;
1.19 kristaps 452: break;
453: }
454:
455: return(1);
1.1 kristaps 456: }
457:
458:
1.3 kristaps 459: /* ARGSUSED */
1.1 kristaps 460: static int
1.4 kristaps 461: pre_IP(DECL_ARGS)
462: {
1.22 kristaps 463: const struct man_node *nn;
464: size_t len;
465: int ival;
1.18 kristaps 466:
1.22 kristaps 467: switch (n->type) {
468: case (MAN_BODY):
469: p->flags |= TERMP_NOLPAD;
470: p->flags |= TERMP_NOSPACE;
471: break;
472: case (MAN_HEAD):
473: p->flags |= TERMP_NOBREAK;
474: p->flags |= TERMP_TWOSPACE;
475: break;
1.23 kristaps 476: case (MAN_BLOCK):
1.39 kristaps 477: print_bvspace(p, n);
1.23 kristaps 478: /* FALLTHROUGH */
1.22 kristaps 479: default:
480: return(1);
481: }
1.18 kristaps 482:
1.26 kristaps 483: len = mt->lmargin;
1.22 kristaps 484: ival = -1;
1.4 kristaps 485:
1.22 kristaps 486: /* Calculate offset. */
1.4 kristaps 487:
1.22 kristaps 488: if (NULL != (nn = n->parent->head->child))
489: if (NULL != (nn = nn->next)) {
490: for ( ; nn->next; nn = nn->next)
491: /* Do nothing. */ ;
1.45 kristaps 492: if ((ival = a2width(nn)) >= 0)
1.22 kristaps 493: len = (size_t)ival;
494: }
1.4 kristaps 495:
1.22 kristaps 496: switch (n->type) {
497: case (MAN_HEAD):
1.23 kristaps 498: /* Handle zero-width lengths. */
499: if (0 == len)
500: len = 1;
501:
1.26 kristaps 502: p->offset = mt->offset;
503: p->rmargin = mt->offset + len;
1.22 kristaps 504: if (ival < 0)
505: break;
1.18 kristaps 506:
1.24 kristaps 507: /* Set the saved left-margin. */
1.26 kristaps 508: mt->lmargin = (size_t)ival;
1.24 kristaps 509:
1.22 kristaps 510: /* Don't print the length value. */
511: for (nn = n->child; nn->next; nn = nn->next)
1.45 kristaps 512: print_man_node(p, mt, nn, m);
1.22 kristaps 513: return(0);
1.23 kristaps 514: case (MAN_BODY):
1.26 kristaps 515: p->offset = mt->offset + len;
1.23 kristaps 516: p->rmargin = p->maxrmargin;
517: break;
1.22 kristaps 518: default:
519: break;
1.18 kristaps 520: }
521:
1.22 kristaps 522: return(1);
523: }
1.18 kristaps 524:
525:
1.22 kristaps 526: /* ARGSUSED */
527: static void
528: post_IP(DECL_ARGS)
529: {
1.4 kristaps 530:
1.22 kristaps 531: switch (n->type) {
532: case (MAN_HEAD):
533: term_flushln(p);
534: p->flags &= ~TERMP_NOBREAK;
535: p->flags &= ~TERMP_TWOSPACE;
536: p->rmargin = p->maxrmargin;
537: break;
538: case (MAN_BODY):
539: term_flushln(p);
540: p->flags &= ~TERMP_NOLPAD;
541: break;
542: default:
543: break;
544: }
1.4 kristaps 545: }
546:
547:
548: /* ARGSUSED */
549: static int
1.1 kristaps 550: pre_TP(DECL_ARGS)
551: {
1.23 kristaps 552: const struct man_node *nn;
553: size_t len;
554: int ival;
1.1 kristaps 555:
1.21 kristaps 556: switch (n->type) {
557: case (MAN_HEAD):
558: p->flags |= TERMP_NOBREAK;
559: p->flags |= TERMP_TWOSPACE;
560: break;
561: case (MAN_BODY):
562: p->flags |= TERMP_NOLPAD;
563: p->flags |= TERMP_NOSPACE;
1.23 kristaps 564: break;
565: case (MAN_BLOCK):
1.39 kristaps 566: print_bvspace(p, n);
1.23 kristaps 567: /* FALLTHROUGH */
568: default:
569: return(1);
570: }
571:
1.24 kristaps 572: len = (size_t)mt->lmargin;
1.23 kristaps 573: ival = -1;
574:
575: /* Calculate offset. */
576:
577: if (NULL != (nn = n->parent->head->child))
1.39 kristaps 578: if (NULL != nn->next)
1.45 kristaps 579: if ((ival = a2width(nn)) >= 0)
1.23 kristaps 580: len = (size_t)ival;
581:
582: switch (n->type) {
583: case (MAN_HEAD):
584: /* Handle zero-length properly. */
585: if (0 == len)
586: len = 1;
587:
1.26 kristaps 588: p->offset = mt->offset;
589: p->rmargin = mt->offset + len;
1.23 kristaps 590:
591: /* Don't print same-line elements. */
592: for (nn = n->child; nn; nn = nn->next)
593: if (nn->line > n->line)
1.45 kristaps 594: print_man_node(p, mt, nn, m);
1.24 kristaps 595:
596: if (ival >= 0)
1.26 kristaps 597: mt->lmargin = (size_t)ival;
1.24 kristaps 598:
1.23 kristaps 599: return(0);
600: case (MAN_BODY):
1.26 kristaps 601: p->offset = mt->offset + len;
1.23 kristaps 602: p->rmargin = p->maxrmargin;
1.21 kristaps 603: break;
604: default:
605: break;
606: }
1.16 kristaps 607:
1.21 kristaps 608: return(1);
609: }
1.1 kristaps 610:
611:
1.21 kristaps 612: /* ARGSUSED */
613: static void
614: post_TP(DECL_ARGS)
615: {
1.1 kristaps 616:
1.21 kristaps 617: switch (n->type) {
618: case (MAN_HEAD):
619: term_flushln(p);
620: p->flags &= ~TERMP_NOBREAK;
621: p->flags &= ~TERMP_TWOSPACE;
622: p->rmargin = p->maxrmargin;
623: break;
624: case (MAN_BODY):
625: term_flushln(p);
626: p->flags &= ~TERMP_NOLPAD;
627: break;
628: default:
629: break;
630: }
1.1 kristaps 631: }
632:
633:
1.3 kristaps 634: /* ARGSUSED */
1.1 kristaps 635: static int
636: pre_SS(DECL_ARGS)
637: {
638:
1.19 kristaps 639: switch (n->type) {
640: case (MAN_BLOCK):
1.24 kristaps 641: mt->lmargin = INDENT;
1.26 kristaps 642: mt->offset = INDENT;
1.24 kristaps 643: /* If following a prior empty `SS', no vspace. */
644: if (n->prev && MAN_SS == n->prev->tok)
645: if (NULL == n->prev->body->child)
646: break;
647: if (NULL == n->prev)
648: break;
649: term_vspace(p);
1.19 kristaps 650: break;
651: case (MAN_HEAD):
1.52 kristaps 652: term_fontrepl(p, TERMFONT_BOLD);
1.19 kristaps 653: p->offset = HALFINDENT;
654: break;
1.24 kristaps 655: case (MAN_BODY):
1.26 kristaps 656: p->offset = mt->offset;
1.24 kristaps 657: break;
1.19 kristaps 658: default:
659: break;
660: }
661:
1.1 kristaps 662: return(1);
663: }
664:
665:
1.3 kristaps 666: /* ARGSUSED */
1.1 kristaps 667: static void
668: post_SS(DECL_ARGS)
669: {
670:
1.19 kristaps 671: switch (n->type) {
672: case (MAN_HEAD):
673: term_newln(p);
674: break;
1.24 kristaps 675: case (MAN_BODY):
676: term_newln(p);
677: break;
1.19 kristaps 678: default:
679: break;
680: }
1.1 kristaps 681: }
682:
683:
1.3 kristaps 684: /* ARGSUSED */
1.1 kristaps 685: static int
686: pre_SH(DECL_ARGS)
687: {
1.22 kristaps 688:
1.19 kristaps 689: switch (n->type) {
690: case (MAN_BLOCK):
1.24 kristaps 691: mt->lmargin = INDENT;
1.26 kristaps 692: mt->offset = INDENT;
1.22 kristaps 693: /* If following a prior empty `SH', no vspace. */
1.19 kristaps 694: if (n->prev && MAN_SH == n->prev->tok)
695: if (NULL == n->prev->body->child)
696: break;
697: term_vspace(p);
698: break;
699: case (MAN_HEAD):
1.52 kristaps 700: term_fontrepl(p, TERMFONT_BOLD);
1.19 kristaps 701: p->offset = 0;
702: break;
703: case (MAN_BODY):
1.26 kristaps 704: p->offset = mt->offset;
1.19 kristaps 705: break;
706: default:
707: break;
708: }
1.1 kristaps 709:
710: return(1);
711: }
712:
713:
1.3 kristaps 714: /* ARGSUSED */
1.1 kristaps 715: static void
716: post_SH(DECL_ARGS)
717: {
718:
1.19 kristaps 719: switch (n->type) {
720: case (MAN_HEAD):
721: term_newln(p);
722: break;
723: case (MAN_BODY):
724: term_newln(p);
725: break;
726: default:
727: break;
728: }
1.1 kristaps 729: }
730:
731:
1.26 kristaps 732: /* ARGSUSED */
733: static int
734: pre_RS(DECL_ARGS)
735: {
736: const struct man_node *nn;
737: int ival;
738:
739: switch (n->type) {
740: case (MAN_BLOCK):
741: term_newln(p);
742: return(1);
743: case (MAN_HEAD):
744: return(0);
745: default:
746: break;
747: }
748:
749: if (NULL == (nn = n->parent->head->child)) {
750: mt->offset = mt->lmargin + INDENT;
751: p->offset = mt->offset;
752: return(1);
753: }
754:
1.45 kristaps 755: if ((ival = a2width(nn)) < 0)
1.26 kristaps 756: return(1);
757:
758: mt->offset = INDENT + (size_t)ival;
759: p->offset = mt->offset;
760:
761: return(1);
762: }
763:
764:
765: /* ARGSUSED */
766: static void
767: post_RS(DECL_ARGS)
768: {
769:
770: switch (n->type) {
771: case (MAN_BLOCK):
772: mt->offset = mt->lmargin = INDENT;
773: break;
774: default:
775: term_newln(p);
776: p->offset = INDENT;
777: break;
778: }
779: }
780:
781:
1.1 kristaps 782: static void
1.45 kristaps 783: print_man_node(DECL_ARGS)
1.1 kristaps 784: {
1.54 kristaps 785: int c;
1.1 kristaps 786:
787: c = 1;
788:
789: switch (n->type) {
790: case(MAN_TEXT):
1.4 kristaps 791: if (0 == *n->string) {
792: term_vspace(p);
1.1 kristaps 793: break;
794: }
1.54 kristaps 795:
1.4 kristaps 796: term_word(p, n->string);
1.52 kristaps 797:
1.19 kristaps 798: /* FIXME: this means that macro lines are munged! */
1.52 kristaps 799:
1.24 kristaps 800: if (MANT_LITERAL & mt->fl) {
1.19 kristaps 801: p->flags |= TERMP_NOSPACE;
802: term_flushln(p);
803: }
1.1 kristaps 804: break;
805: default:
1.52 kristaps 806: term_fontrepl(p, TERMFONT_NONE);
1.19 kristaps 807: if (termacts[n->tok].pre)
1.24 kristaps 808: c = (*termacts[n->tok].pre)(p, mt, n, m);
1.1 kristaps 809: break;
810: }
811:
812: if (c && n->child)
1.52 kristaps 813: print_man_nodelist(p, mt, n->child, m);
1.1 kristaps 814:
1.51 kristaps 815: if (MAN_TEXT != n->type) {
1.1 kristaps 816: if (termacts[n->tok].post)
1.24 kristaps 817: (*termacts[n->tok].post)(p, mt, n, m);
1.52 kristaps 818: term_fontrepl(p, TERMFONT_NONE);
1.51 kristaps 819: }
1.1 kristaps 820: }
821:
822:
823: static void
1.52 kristaps 824: print_man_nodelist(DECL_ARGS)
1.1 kristaps 825: {
1.19 kristaps 826:
1.45 kristaps 827: print_man_node(p, mt, n, m);
1.1 kristaps 828: if ( ! n->next)
829: return;
1.52 kristaps 830: print_man_nodelist(p, mt, n->next, m);
1.1 kristaps 831: }
832:
833:
1.31 kristaps 834: static void
1.45 kristaps 835: print_man_foot(struct termp *p, const struct man_meta *meta)
1.1 kristaps 836: {
1.43 kristaps 837: char buf[DATESIZ];
1.1 kristaps 838:
1.52 kristaps 839: term_fontrepl(p, TERMFONT_NONE);
1.50 kristaps 840:
1.43 kristaps 841: time2a(meta->date, buf, DATESIZ);
1.1 kristaps 842:
843: term_vspace(p);
844:
845: p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
846: p->rmargin = p->maxrmargin - strlen(buf);
847: p->offset = 0;
848:
849: if (meta->source)
850: term_word(p, meta->source);
851: if (meta->source)
852: term_word(p, "");
853: term_flushln(p);
854:
855: p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
856: p->offset = p->rmargin;
857: p->rmargin = p->maxrmargin;
858: p->flags &= ~TERMP_NOBREAK;
859:
860: term_word(p, buf);
861: term_flushln(p);
862: }
863:
864:
1.31 kristaps 865: static void
1.46 kristaps 866: print_man_head(struct termp *p, const struct man_meta *m)
1.1 kristaps 867: {
1.46 kristaps 868: char buf[BUFSIZ], title[BUFSIZ];
1.1 kristaps 869:
870: p->rmargin = p->maxrmargin;
871: p->offset = 0;
1.46 kristaps 872: buf[0] = title[0] = '\0';
1.1 kristaps 873:
1.46 kristaps 874: if (m->vol)
875: strlcpy(buf, m->vol, BUFSIZ);
1.1 kristaps 876:
1.46 kristaps 877: snprintf(title, BUFSIZ, "%s(%d)", m->title, m->msec);
1.1 kristaps 878:
879: p->offset = 0;
1.10 kristaps 880: p->rmargin = (p->maxrmargin - strlen(buf) + 1) / 2;
1.1 kristaps 881: p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
882:
883: term_word(p, title);
884: term_flushln(p);
885:
886: p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
887: p->offset = p->rmargin;
888: p->rmargin = p->maxrmargin - strlen(title);
889:
890: term_word(p, buf);
891: term_flushln(p);
892:
893: p->offset = p->rmargin;
894: p->rmargin = p->maxrmargin;
895: p->flags &= ~TERMP_NOBREAK;
896: p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
897:
898: term_word(p, title);
899: term_flushln(p);
900:
901: p->rmargin = p->maxrmargin;
902: p->offset = 0;
903: p->flags &= ~TERMP_NOSPACE;
904: }
CVSweb