[BACK]Return to man_term.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Annotation of mandoc/man_term.c, Revision 1.55

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

CVSweb