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