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