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