Annotation of mandoc/man_term.c, Revision 1.82
1.82 ! kristaps 1: /* $Id: man_term.c,v 1.81 2010/07/22 13:36:25 kristaps Exp $ */
1.1 kristaps 2: /*
1.80 schwarze 3: * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
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.71 kristaps 29: #include "mandoc.h"
1.40 kristaps 30: #include "out.h"
1.36 kristaps 31: #include "man.h"
1.1 kristaps 32: #include "term.h"
1.36 kristaps 33: #include "chars.h"
34: #include "main.h"
1.1 kristaps 35:
1.18 kristaps 36: #define INDENT 7
37: #define HALFINDENT 3
38:
1.44 kristaps 39: /* FIXME: have PD set the default vspace width. */
40:
1.24 kristaps 41: struct mtermp {
42: int fl;
1.19 kristaps 43: #define MANT_LITERAL (1 << 0)
1.26 kristaps 44: /*
45: * Default amount to indent the left margin after leading text
46: * has been printed (e.g., `HP' left-indent, `TP' and `IP' body
47: * indent). This needs to be saved because `HP' and so on, if
48: * not having a specified value, must default.
49: *
50: * Note that this is the indentation AFTER the left offset, so
51: * the total offset is usually offset + lmargin.
52: */
53: size_t lmargin;
54: /*
55: * The default offset, i.e., the amount between any text and the
56: * page boundary.
57: */
58: size_t offset;
1.24 kristaps 59: };
1.19 kristaps 60:
1.1 kristaps 61: #define DECL_ARGS struct termp *p, \
1.24 kristaps 62: struct mtermp *mt, \
1.1 kristaps 63: const struct man_node *n, \
64: const struct man_meta *m
65:
66: struct termact {
67: int (*pre)(DECL_ARGS);
68: void (*post)(DECL_ARGS);
1.56 kristaps 69: int flags;
70: #define MAN_NOTEXT (1 << 0) /* Never has text children. */
1.1 kristaps 71: };
72:
1.77 kristaps 73: static int a2width(const struct termp *, const char *);
74: static size_t a2height(const struct termp *, const char *);
1.39 kristaps 75:
1.52 kristaps 76: static void print_man_nodelist(DECL_ARGS);
1.45 kristaps 77: static void print_man_node(DECL_ARGS);
1.74 kristaps 78: static void print_man_head(struct termp *, const void *);
1.73 kristaps 79: static void print_man_foot(struct termp *, const void *);
1.39 kristaps 80: static void print_bvspace(struct termp *,
81: const struct man_node *);
82:
1.1 kristaps 83: static int pre_B(DECL_ARGS);
1.3 kristaps 84: static int pre_BI(DECL_ARGS);
1.19 kristaps 85: static int pre_HP(DECL_ARGS);
1.1 kristaps 86: static int pre_I(DECL_ARGS);
1.4 kristaps 87: static int pre_IP(DECL_ARGS);
1.1 kristaps 88: static int pre_PP(DECL_ARGS);
1.3 kristaps 89: static int pre_RB(DECL_ARGS);
90: static int pre_RI(DECL_ARGS);
1.26 kristaps 91: static int pre_RS(DECL_ARGS);
1.1 kristaps 92: static int pre_SH(DECL_ARGS);
93: static int pre_SS(DECL_ARGS);
94: static int pre_TP(DECL_ARGS);
1.19 kristaps 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.82 ! kristaps 108: { pre_sp, NULL, MAN_NOTEXT }, /* br */
1.56 kristaps 109: { NULL, NULL, 0 }, /* TH */
110: { pre_SH, post_SH, 0 }, /* SH */
111: { pre_SS, post_SS, 0 }, /* SS */
112: { pre_TP, post_TP, 0 }, /* TP */
113: { pre_PP, NULL, 0 }, /* LP */
114: { pre_PP, NULL, 0 }, /* PP */
115: { pre_PP, NULL, 0 }, /* P */
116: { pre_IP, post_IP, 0 }, /* IP */
117: { pre_HP, post_HP, 0 }, /* HP */
118: { NULL, NULL, 0 }, /* SM */
119: { pre_B, NULL, 0 }, /* SB */
120: { pre_BI, NULL, 0 }, /* BI */
121: { pre_BI, NULL, 0 }, /* IB */
122: { pre_RB, NULL, 0 }, /* BR */
123: { pre_RB, NULL, 0 }, /* RB */
124: { NULL, NULL, 0 }, /* R */
125: { pre_B, NULL, 0 }, /* B */
126: { pre_I, NULL, 0 }, /* I */
127: { pre_RI, NULL, 0 }, /* IR */
128: { pre_RI, NULL, 0 }, /* RI */
129: { NULL, NULL, MAN_NOTEXT }, /* na */
130: { pre_I, NULL, 0 }, /* i */
131: { pre_sp, NULL, MAN_NOTEXT }, /* sp */
132: { pre_nf, NULL, 0 }, /* nf */
133: { pre_fi, NULL, 0 }, /* fi */
134: { NULL, NULL, 0 }, /* r */
135: { NULL, NULL, 0 }, /* RE */
136: { pre_RS, post_RS, 0 }, /* RS */
137: { pre_ign, NULL, 0 }, /* DT */
138: { pre_ign, NULL, 0 }, /* UC */
139: { pre_ign, NULL, 0 }, /* PD */
1.57 kristaps 140: { pre_sp, NULL, MAN_NOTEXT }, /* Sp */
141: { pre_nf, NULL, 0 }, /* Vb */
142: { pre_fi, NULL, 0 }, /* Ve */
1.70 joerg 143: { pre_ign, NULL, 0 }, /* AT */
1.1 kristaps 144: };
145:
146:
147:
1.31 kristaps 148: void
1.36 kristaps 149: terminal_man(void *arg, const struct man *man)
1.1 kristaps 150: {
1.36 kristaps 151: struct termp *p;
152: const struct man_node *n;
153: const struct man_meta *m;
154: struct mtermp mt;
155:
156: p = (struct termp *)arg;
157:
1.58 kristaps 158: p->overstep = 0;
1.65 joerg 159: p->maxrmargin = p->defrmargin;
1.77 kristaps 160: p->tabwidth = term_len(p, 5);
1.73 kristaps 161:
1.36 kristaps 162: if (NULL == p->symtab)
163: switch (p->enc) {
164: case (TERMENC_ASCII):
165: p->symtab = chars_init(CHARS_ASCII);
166: break;
167: default:
168: abort();
169: /* NOTREACHED */
170: }
171:
172: n = man_node(man);
173: m = man_meta(man);
1.1 kristaps 174:
1.75 schwarze 175: term_begin(p, print_man_head, print_man_foot, m);
1.1 kristaps 176: p->flags |= TERMP_NOSPACE;
1.19 kristaps 177:
1.24 kristaps 178: mt.fl = 0;
1.77 kristaps 179: mt.lmargin = term_len(p, INDENT);
180: mt.offset = term_len(p, INDENT);
1.24 kristaps 181:
1.36 kristaps 182: if (n->child)
1.52 kristaps 183: print_man_nodelist(p, &mt, n->child, m);
1.73 kristaps 184:
185: term_end(p);
1.1 kristaps 186: }
187:
188:
1.77 kristaps 189: static size_t
190: a2height(const struct termp *p, const char *cp)
1.18 kristaps 191: {
1.40 kristaps 192: struct roffsu su;
1.18 kristaps 193:
1.77 kristaps 194: if ( ! a2roffsu(cp, &su, SCALE_VS))
195: SCALE_VS_INIT(&su, term_strlen(p, cp));
1.18 kristaps 196:
1.77 kristaps 197: return(term_vspan(p, &su));
1.18 kristaps 198: }
199:
200:
201: static int
1.77 kristaps 202: a2width(const struct termp *p, const char *cp)
1.38 kristaps 203: {
1.40 kristaps 204: struct roffsu su;
1.38 kristaps 205:
1.77 kristaps 206: if ( ! a2roffsu(cp, &su, SCALE_BU))
1.41 kristaps 207: return(-1);
1.40 kristaps 208:
1.77 kristaps 209: return((int)term_hspan(p, &su));
1.38 kristaps 210: }
211:
212:
1.39 kristaps 213: static void
214: print_bvspace(struct termp *p, const struct man_node *n)
1.18 kristaps 215: {
1.39 kristaps 216: term_newln(p);
1.18 kristaps 217:
1.39 kristaps 218: if (NULL == n->prev)
219: return;
1.18 kristaps 220:
1.39 kristaps 221: if (MAN_SS == n->prev->tok)
222: return;
223: if (MAN_SH == n->prev->tok)
224: return;
1.18 kristaps 225:
1.39 kristaps 226: term_vspace(p);
1.18 kristaps 227: }
228:
229:
1.3 kristaps 230: /* ARGSUSED */
1.1 kristaps 231: static int
1.29 kristaps 232: pre_ign(DECL_ARGS)
233: {
234:
235: return(0);
236: }
237:
238:
239: /* ARGSUSED */
240: static int
1.1 kristaps 241: pre_I(DECL_ARGS)
242: {
243:
1.52 kristaps 244: term_fontrepl(p, TERMFONT_UNDER);
1.19 kristaps 245: return(1);
246: }
247:
248:
249: /* ARGSUSED */
1.3 kristaps 250: static int
1.19 kristaps 251: pre_fi(DECL_ARGS)
252: {
253:
1.81 kristaps 254: term_newln(p);
1.24 kristaps 255: mt->fl &= ~MANT_LITERAL;
1.19 kristaps 256: return(1);
257: }
258:
259:
260: /* ARGSUSED */
261: static int
262: pre_nf(DECL_ARGS)
263: {
264:
1.81 kristaps 265: term_newln(p);
1.24 kristaps 266: mt->fl |= MANT_LITERAL;
1.57 kristaps 267: return(MAN_Vb != n->tok);
1.19 kristaps 268: }
269:
270:
271: /* ARGSUSED */
272: static int
1.35 kristaps 273: pre_RB(DECL_ARGS)
1.3 kristaps 274: {
275: const struct man_node *nn;
276: int i;
277:
278: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
1.35 kristaps 279: if (i % 2 && MAN_RB == n->tok)
1.52 kristaps 280: term_fontrepl(p, TERMFONT_BOLD);
1.35 kristaps 281: else if ( ! (i % 2) && MAN_RB != n->tok)
1.52 kristaps 282: term_fontrepl(p, TERMFONT_BOLD);
283: else
284: term_fontrepl(p, TERMFONT_NONE);
1.35 kristaps 285:
1.4 kristaps 286: if (i > 0)
287: p->flags |= TERMP_NOSPACE;
1.35 kristaps 288:
1.45 kristaps 289: print_man_node(p, mt, nn, m);
1.3 kristaps 290: }
291: return(0);
292: }
293:
294:
295: /* ARGSUSED */
296: static int
297: pre_RI(DECL_ARGS)
298: {
299: const struct man_node *nn;
300: int i;
301:
302: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
1.49 kristaps 303: if (i % 2 && MAN_RI == n->tok)
1.52 kristaps 304: term_fontrepl(p, TERMFONT_UNDER);
1.49 kristaps 305: else if ( ! (i % 2) && MAN_RI != n->tok)
1.52 kristaps 306: term_fontrepl(p, TERMFONT_UNDER);
307: else
308: term_fontrepl(p, TERMFONT_NONE);
1.49 kristaps 309:
1.4 kristaps 310: if (i > 0)
311: p->flags |= TERMP_NOSPACE;
1.52 kristaps 312:
1.45 kristaps 313: print_man_node(p, mt, nn, m);
1.3 kristaps 314: }
315: return(0);
316: }
317:
318:
319: /* ARGSUSED */
320: static int
321: pre_BI(DECL_ARGS)
322: {
1.35 kristaps 323: const struct man_node *nn;
324: int i;
1.3 kristaps 325:
326: for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
1.35 kristaps 327: if (i % 2 && MAN_BI == n->tok)
1.52 kristaps 328: term_fontrepl(p, TERMFONT_UNDER);
1.35 kristaps 329: else if (i % 2)
1.52 kristaps 330: term_fontrepl(p, TERMFONT_BOLD);
1.35 kristaps 331: else if (MAN_BI == n->tok)
1.52 kristaps 332: term_fontrepl(p, TERMFONT_BOLD);
1.30 kristaps 333: else
1.52 kristaps 334: term_fontrepl(p, TERMFONT_UNDER);
1.35 kristaps 335:
336: if (i)
1.4 kristaps 337: p->flags |= TERMP_NOSPACE;
1.52 kristaps 338:
1.45 kristaps 339: print_man_node(p, mt, nn, m);
1.3 kristaps 340: }
341: return(0);
342: }
343:
344:
345: /* ARGSUSED */
1.1 kristaps 346: static int
347: pre_B(DECL_ARGS)
348: {
349:
1.52 kristaps 350: term_fontrepl(p, TERMFONT_BOLD);
1.1 kristaps 351: return(1);
352: }
353:
354:
1.3 kristaps 355: /* ARGSUSED */
1.1 kristaps 356: static int
1.19 kristaps 357: pre_sp(DECL_ARGS)
358: {
1.77 kristaps 359: size_t i, len;
1.19 kristaps 360:
1.82 ! kristaps 361: switch (n->tok) {
! 362: case (MAN_br):
! 363: len = 0;
! 364: break;
! 365: default:
! 366: len = n->child ? a2height(p, n->child->string) : 1;
! 367: break;
! 368: }
1.38 kristaps 369:
1.19 kristaps 370: if (0 == len)
371: term_newln(p);
1.82 ! kristaps 372: for (i = 0; i < len; i++)
1.19 kristaps 373: term_vspace(p);
374:
1.15 kristaps 375: return(0);
376: }
377:
378:
379: /* ARGSUSED */
380: static int
1.19 kristaps 381: pre_HP(DECL_ARGS)
382: {
1.24 kristaps 383: size_t len;
384: int ival;
385: const struct man_node *nn;
1.19 kristaps 386:
1.20 kristaps 387: switch (n->type) {
388: case (MAN_BLOCK):
1.39 kristaps 389: print_bvspace(p, n);
1.24 kristaps 390: return(1);
1.20 kristaps 391: case (MAN_BODY):
392: p->flags |= TERMP_NOBREAK;
393: p->flags |= TERMP_TWOSPACE;
394: break;
395: default:
396: return(0);
397: }
398:
1.26 kristaps 399: len = mt->lmargin;
1.24 kristaps 400: ival = -1;
401:
402: /* Calculate offset. */
403:
1.39 kristaps 404: if (NULL != (nn = n->parent->head->child))
1.77 kristaps 405: if ((ival = a2width(p, nn->string)) >= 0)
1.24 kristaps 406: len = (size_t)ival;
407:
408: if (0 == len)
1.77 kristaps 409: len = term_len(p, 1);
1.24 kristaps 410:
1.26 kristaps 411: p->offset = mt->offset;
412: p->rmargin = mt->offset + len;
1.24 kristaps 413:
414: if (ival >= 0)
1.26 kristaps 415: mt->lmargin = (size_t)ival;
1.24 kristaps 416:
1.19 kristaps 417: return(1);
418: }
419:
420:
421: /* ARGSUSED */
1.20 kristaps 422: static void
423: post_HP(DECL_ARGS)
424: {
425:
426: switch (n->type) {
1.24 kristaps 427: case (MAN_BLOCK):
428: term_flushln(p);
429: break;
1.20 kristaps 430: case (MAN_BODY):
431: term_flushln(p);
432: p->flags &= ~TERMP_NOBREAK;
433: p->flags &= ~TERMP_TWOSPACE;
1.26 kristaps 434: p->offset = mt->offset;
1.20 kristaps 435: p->rmargin = p->maxrmargin;
436: break;
437: default:
438: break;
439: }
440: }
441:
442:
443: /* ARGSUSED */
1.19 kristaps 444: static int
1.1 kristaps 445: pre_PP(DECL_ARGS)
446: {
447:
1.19 kristaps 448: switch (n->type) {
449: case (MAN_BLOCK):
1.77 kristaps 450: mt->lmargin = term_len(p, INDENT);
1.39 kristaps 451: print_bvspace(p, n);
1.19 kristaps 452: break;
453: default:
1.26 kristaps 454: p->offset = mt->offset;
1.19 kristaps 455: break;
456: }
457:
458: return(1);
1.1 kristaps 459: }
460:
461:
1.3 kristaps 462: /* ARGSUSED */
1.1 kristaps 463: static int
1.4 kristaps 464: pre_IP(DECL_ARGS)
465: {
1.22 kristaps 466: const struct man_node *nn;
467: size_t len;
468: int ival;
1.18 kristaps 469:
1.22 kristaps 470: switch (n->type) {
471: case (MAN_BODY):
472: p->flags |= TERMP_NOLPAD;
473: p->flags |= TERMP_NOSPACE;
474: break;
475: case (MAN_HEAD):
476: p->flags |= TERMP_NOBREAK;
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.77 kristaps 494: if ((ival = a2width(p, nn->string)) >= 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)
1.77 kristaps 502: len = term_len(p, 1);
1.23 kristaps 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->rmargin = p->maxrmargin;
538: break;
539: case (MAN_BODY):
540: term_flushln(p);
541: p->flags &= ~TERMP_NOLPAD;
542: break;
543: default:
544: break;
545: }
1.4 kristaps 546: }
547:
548:
549: /* ARGSUSED */
550: static int
1.1 kristaps 551: pre_TP(DECL_ARGS)
552: {
1.23 kristaps 553: const struct man_node *nn;
554: size_t len;
555: int ival;
1.1 kristaps 556:
1.21 kristaps 557: switch (n->type) {
558: case (MAN_HEAD):
559: p->flags |= TERMP_NOBREAK;
560: p->flags |= TERMP_TWOSPACE;
561: break;
562: case (MAN_BODY):
563: p->flags |= TERMP_NOLPAD;
564: p->flags |= TERMP_NOSPACE;
1.23 kristaps 565: break;
566: case (MAN_BLOCK):
1.39 kristaps 567: print_bvspace(p, n);
1.23 kristaps 568: /* FALLTHROUGH */
569: default:
570: return(1);
571: }
572:
1.24 kristaps 573: len = (size_t)mt->lmargin;
1.23 kristaps 574: ival = -1;
575:
576: /* Calculate offset. */
577:
1.56 kristaps 578: if (NULL != (nn = n->parent->head->child)) {
579: while (nn && MAN_TEXT != nn->type)
580: nn = nn->next;
581: if (nn && nn->next)
1.77 kristaps 582: if ((ival = a2width(p, nn->string)) >= 0)
1.23 kristaps 583: len = (size_t)ival;
1.56 kristaps 584: }
1.23 kristaps 585:
586: switch (n->type) {
587: case (MAN_HEAD):
588: /* Handle zero-length properly. */
589: if (0 == len)
1.77 kristaps 590: len = term_len(p, 1);
1.23 kristaps 591:
1.26 kristaps 592: p->offset = mt->offset;
593: p->rmargin = mt->offset + len;
1.23 kristaps 594:
595: /* Don't print same-line elements. */
596: for (nn = n->child; nn; nn = nn->next)
597: if (nn->line > n->line)
1.45 kristaps 598: print_man_node(p, mt, nn, m);
1.24 kristaps 599:
600: if (ival >= 0)
1.26 kristaps 601: mt->lmargin = (size_t)ival;
1.24 kristaps 602:
1.23 kristaps 603: return(0);
604: case (MAN_BODY):
1.26 kristaps 605: p->offset = mt->offset + len;
1.23 kristaps 606: p->rmargin = p->maxrmargin;
1.21 kristaps 607: break;
608: default:
609: break;
610: }
1.16 kristaps 611:
1.21 kristaps 612: return(1);
613: }
1.1 kristaps 614:
615:
1.21 kristaps 616: /* ARGSUSED */
617: static void
618: post_TP(DECL_ARGS)
619: {
1.1 kristaps 620:
1.21 kristaps 621: switch (n->type) {
622: case (MAN_HEAD):
623: term_flushln(p);
624: p->flags &= ~TERMP_NOBREAK;
625: p->flags &= ~TERMP_TWOSPACE;
626: p->rmargin = p->maxrmargin;
627: break;
628: case (MAN_BODY):
629: term_flushln(p);
630: p->flags &= ~TERMP_NOLPAD;
631: break;
632: default:
633: break;
634: }
1.1 kristaps 635: }
636:
637:
1.3 kristaps 638: /* ARGSUSED */
1.1 kristaps 639: static int
640: pre_SS(DECL_ARGS)
641: {
642:
1.19 kristaps 643: switch (n->type) {
644: case (MAN_BLOCK):
1.77 kristaps 645: mt->lmargin = term_len(p, INDENT);
646: mt->offset = term_len(p, INDENT);
1.24 kristaps 647: /* If following a prior empty `SS', no vspace. */
648: if (n->prev && MAN_SS == n->prev->tok)
649: if (NULL == n->prev->body->child)
650: break;
651: if (NULL == n->prev)
652: break;
653: term_vspace(p);
1.19 kristaps 654: break;
655: case (MAN_HEAD):
1.52 kristaps 656: term_fontrepl(p, TERMFONT_BOLD);
1.77 kristaps 657: p->offset = term_len(p, HALFINDENT);
1.19 kristaps 658: break;
1.24 kristaps 659: case (MAN_BODY):
1.26 kristaps 660: p->offset = mt->offset;
1.24 kristaps 661: break;
1.19 kristaps 662: default:
663: break;
664: }
665:
1.1 kristaps 666: return(1);
667: }
668:
669:
1.3 kristaps 670: /* ARGSUSED */
1.1 kristaps 671: static void
672: post_SS(DECL_ARGS)
673: {
674:
1.19 kristaps 675: switch (n->type) {
676: case (MAN_HEAD):
677: term_newln(p);
678: break;
1.24 kristaps 679: case (MAN_BODY):
680: term_newln(p);
681: break;
1.19 kristaps 682: default:
683: break;
684: }
1.1 kristaps 685: }
686:
687:
1.3 kristaps 688: /* ARGSUSED */
1.1 kristaps 689: static int
690: pre_SH(DECL_ARGS)
691: {
1.22 kristaps 692:
1.19 kristaps 693: switch (n->type) {
694: case (MAN_BLOCK):
1.77 kristaps 695: mt->lmargin = term_len(p, INDENT);
696: mt->offset = term_len(p, INDENT);
1.22 kristaps 697: /* If following a prior empty `SH', no vspace. */
1.19 kristaps 698: if (n->prev && MAN_SH == n->prev->tok)
699: if (NULL == n->prev->body->child)
700: break;
1.61 kristaps 701: /* If the first macro, no vspae. */
702: if (NULL == n->prev)
703: break;
1.19 kristaps 704: term_vspace(p);
705: break;
706: case (MAN_HEAD):
1.52 kristaps 707: term_fontrepl(p, TERMFONT_BOLD);
1.19 kristaps 708: p->offset = 0;
709: break;
710: case (MAN_BODY):
1.26 kristaps 711: p->offset = mt->offset;
1.19 kristaps 712: break;
713: default:
714: break;
715: }
1.1 kristaps 716:
717: return(1);
718: }
719:
720:
1.3 kristaps 721: /* ARGSUSED */
1.1 kristaps 722: static void
723: post_SH(DECL_ARGS)
724: {
725:
1.19 kristaps 726: switch (n->type) {
727: case (MAN_HEAD):
728: term_newln(p);
729: break;
730: case (MAN_BODY):
731: term_newln(p);
732: break;
733: default:
734: break;
735: }
1.1 kristaps 736: }
737:
738:
1.26 kristaps 739: /* ARGSUSED */
740: static int
741: pre_RS(DECL_ARGS)
742: {
743: const struct man_node *nn;
744: int ival;
745:
746: switch (n->type) {
747: case (MAN_BLOCK):
748: term_newln(p);
749: return(1);
750: case (MAN_HEAD):
751: return(0);
752: default:
753: break;
754: }
755:
756: if (NULL == (nn = n->parent->head->child)) {
1.77 kristaps 757: mt->offset = mt->lmargin + term_len(p, INDENT);
1.26 kristaps 758: p->offset = mt->offset;
759: return(1);
760: }
761:
1.77 kristaps 762: if ((ival = a2width(p, nn->string)) < 0)
1.26 kristaps 763: return(1);
764:
1.77 kristaps 765: mt->offset = term_len(p, INDENT) + (size_t)ival;
1.26 kristaps 766: p->offset = mt->offset;
767:
768: return(1);
769: }
770:
771:
772: /* ARGSUSED */
773: static void
774: post_RS(DECL_ARGS)
775: {
776:
777: switch (n->type) {
778: case (MAN_BLOCK):
1.77 kristaps 779: mt->offset = mt->lmargin = term_len(p, INDENT);
1.59 kristaps 780: break;
781: case (MAN_HEAD):
1.26 kristaps 782: break;
783: default:
784: term_newln(p);
1.77 kristaps 785: p->offset = term_len(p, INDENT);
1.26 kristaps 786: break;
787: }
788: }
789:
790:
1.1 kristaps 791: static void
1.45 kristaps 792: print_man_node(DECL_ARGS)
1.1 kristaps 793: {
1.65 joerg 794: size_t rm, rmax;
1.54 kristaps 795: int c;
1.1 kristaps 796:
797: c = 1;
798:
799: switch (n->type) {
800: case(MAN_TEXT):
1.4 kristaps 801: if (0 == *n->string) {
802: term_vspace(p);
1.1 kristaps 803: break;
804: }
1.54 kristaps 805:
1.4 kristaps 806: term_word(p, n->string);
1.52 kristaps 807:
1.19 kristaps 808: /* FIXME: this means that macro lines are munged! */
1.52 kristaps 809:
1.24 kristaps 810: if (MANT_LITERAL & mt->fl) {
1.65 joerg 811: rm = p->rmargin;
812: rmax = p->maxrmargin;
1.60 kristaps 813: p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
1.19 kristaps 814: p->flags |= TERMP_NOSPACE;
815: term_flushln(p);
1.65 joerg 816: p->rmargin = rm;
817: p->maxrmargin = rmax;
1.19 kristaps 818: }
1.1 kristaps 819: break;
820: default:
1.56 kristaps 821: if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
822: term_fontrepl(p, TERMFONT_NONE);
1.19 kristaps 823: if (termacts[n->tok].pre)
1.24 kristaps 824: c = (*termacts[n->tok].pre)(p, mt, n, m);
1.1 kristaps 825: break;
826: }
827:
828: if (c && n->child)
1.52 kristaps 829: print_man_nodelist(p, mt, n->child, m);
1.1 kristaps 830:
1.51 kristaps 831: if (MAN_TEXT != n->type) {
1.1 kristaps 832: if (termacts[n->tok].post)
1.24 kristaps 833: (*termacts[n->tok].post)(p, mt, n, m);
1.56 kristaps 834: if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
835: term_fontrepl(p, TERMFONT_NONE);
1.51 kristaps 836: }
1.63 kristaps 837:
838: if (MAN_EOS & n->flags)
839: p->flags |= TERMP_SENTENCE;
1.1 kristaps 840: }
841:
842:
843: static void
1.52 kristaps 844: print_man_nodelist(DECL_ARGS)
1.1 kristaps 845: {
1.19 kristaps 846:
1.45 kristaps 847: print_man_node(p, mt, n, m);
1.1 kristaps 848: if ( ! n->next)
849: return;
1.52 kristaps 850: print_man_nodelist(p, mt, n->next, m);
1.1 kristaps 851: }
852:
853:
1.31 kristaps 854: static void
1.73 kristaps 855: print_man_foot(struct termp *p, const void *arg)
1.1 kristaps 856: {
1.43 kristaps 857: char buf[DATESIZ];
1.73 kristaps 858: const struct man_meta *meta;
859:
860: meta = (const struct man_meta *)arg;
1.1 kristaps 861:
1.52 kristaps 862: term_fontrepl(p, TERMFONT_NONE);
1.50 kristaps 863:
1.72 kristaps 864: if (meta->rawdate)
865: strlcpy(buf, meta->rawdate, DATESIZ);
866: else
867: time2a(meta->date, buf, DATESIZ);
1.1 kristaps 868:
1.69 joerg 869: term_vspace(p);
870: term_vspace(p);
1.1 kristaps 871: term_vspace(p);
872:
873: p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
1.77 kristaps 874: p->rmargin = p->maxrmargin - term_strlen(p, buf);
1.1 kristaps 875: p->offset = 0;
876:
877: if (meta->source)
878: term_word(p, meta->source);
879: if (meta->source)
880: term_word(p, "");
881: term_flushln(p);
882:
883: p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
884: p->offset = p->rmargin;
885: p->rmargin = p->maxrmargin;
886: p->flags &= ~TERMP_NOBREAK;
887:
888: term_word(p, buf);
889: term_flushln(p);
890: }
891:
892:
1.31 kristaps 893: static void
1.73 kristaps 894: print_man_head(struct termp *p, const void *arg)
1.1 kristaps 895: {
1.46 kristaps 896: char buf[BUFSIZ], title[BUFSIZ];
1.57 kristaps 897: size_t buflen, titlen;
1.73 kristaps 898: const struct man_meta *m;
899:
900: m = (const struct man_meta *)arg;
1.1 kristaps 901:
1.62 kristaps 902: /*
903: * Note that old groff would spit out some spaces before the
904: * header. We discontinue this strange behaviour, but at one
905: * point we did so here.
906: */
907:
1.1 kristaps 908: p->rmargin = p->maxrmargin;
1.58 kristaps 909:
1.1 kristaps 910: p->offset = 0;
1.46 kristaps 911: buf[0] = title[0] = '\0';
1.1 kristaps 912:
1.46 kristaps 913: if (m->vol)
914: strlcpy(buf, m->vol, BUFSIZ);
1.77 kristaps 915: buflen = term_strlen(p, buf);
1.1 kristaps 916:
1.64 kristaps 917: snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec);
1.77 kristaps 918: titlen = term_strlen(p, title);
1.1 kristaps 919:
920: p->offset = 0;
1.57 kristaps 921: p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
1.77 kristaps 922: (p->maxrmargin -
923: term_strlen(p, buf) + term_len(p, 1)) / 2 :
1.57 kristaps 924: p->maxrmargin - buflen;
1.1 kristaps 925: p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
926:
927: term_word(p, title);
928: term_flushln(p);
929:
930: p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
931: p->offset = p->rmargin;
1.57 kristaps 932: p->rmargin = p->offset + buflen + titlen < p->maxrmargin ?
933: p->maxrmargin - titlen : p->maxrmargin;
1.1 kristaps 934:
935: term_word(p, buf);
936: term_flushln(p);
937:
938: p->flags &= ~TERMP_NOBREAK;
1.57 kristaps 939: if (p->rmargin + titlen <= p->maxrmargin) {
940: p->flags |= TERMP_NOLPAD | TERMP_NOSPACE;
941: p->offset = p->rmargin;
942: p->rmargin = p->maxrmargin;
943: term_word(p, title);
944: term_flushln(p);
945: }
1.1 kristaps 946:
947: p->rmargin = p->maxrmargin;
948: p->offset = 0;
949: p->flags &= ~TERMP_NOSPACE;
1.61 kristaps 950:
1.62 kristaps 951: /*
952: * Groff likes to have some leading spaces before content. Well
953: * that's fine by me.
954: */
955:
1.61 kristaps 956: term_vspace(p);
957: term_vspace(p);
958: term_vspace(p);
1.1 kristaps 959: }
CVSweb