[BACK]Return to man_html.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mandoc

Annotation of src/usr.bin/mandoc/man_html.c, Revision 1.10

1.10    ! schwarze    1: /*     $Id: man_html.c,v 1.9 2010/04/25 16:32:19 schwarze Exp $ */
1.1       schwarze    2: /*
                      3:  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      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.
                     16:  */
                     17: #include <sys/types.h>
                     18:
                     19: #include <assert.h>
                     20: #include <ctype.h>
                     21: #include <stdio.h>
                     22: #include <stdlib.h>
                     23: #include <string.h>
                     24:
                     25: #include "out.h"
                     26: #include "html.h"
                     27: #include "man.h"
                     28: #include "main.h"
                     29:
                     30: /* TODO: preserve ident widths. */
1.2       schwarze   31: /* FIXME: have PD set the default vspace width. */
1.1       schwarze   32:
                     33: #define        INDENT            5
                     34: #define        HALFINDENT        3
                     35:
                     36: #define        MAN_ARGS          const struct man_meta *m, \
                     37:                          const struct man_node *n, \
                     38:                          struct html *h
                     39:
                     40: struct htmlman {
                     41:        int             (*pre)(MAN_ARGS);
                     42:        int             (*post)(MAN_ARGS);
                     43: };
                     44:
                     45: static void              print_man(MAN_ARGS);
                     46: static void              print_man_head(MAN_ARGS);
                     47: static void              print_man_nodelist(MAN_ARGS);
                     48: static void              print_man_node(MAN_ARGS);
                     49:
                     50: static int               a2width(const struct man_node *,
                     51:                                struct roffsu *);
                     52:
                     53: static int               man_alt_pre(MAN_ARGS);
                     54: static int               man_br_pre(MAN_ARGS);
                     55: static int               man_ign_pre(MAN_ARGS);
                     56: static void              man_root_post(MAN_ARGS);
                     57: static int               man_root_pre(MAN_ARGS);
                     58: static int               man_B_pre(MAN_ARGS);
                     59: static int               man_HP_pre(MAN_ARGS);
                     60: static int               man_I_pre(MAN_ARGS);
                     61: static int               man_IP_pre(MAN_ARGS);
                     62: static int               man_PP_pre(MAN_ARGS);
                     63: static int               man_RS_pre(MAN_ARGS);
                     64: static int               man_SB_pre(MAN_ARGS);
                     65: static int               man_SH_pre(MAN_ARGS);
                     66: static int               man_SM_pre(MAN_ARGS);
                     67: static int               man_SS_pre(MAN_ARGS);
                     68:
                     69: static const struct htmlman mans[MAN_MAX] = {
                     70:        { man_br_pre, NULL }, /* br */
                     71:        { NULL, NULL }, /* TH */
                     72:        { man_SH_pre, NULL }, /* SH */
                     73:        { man_SS_pre, NULL }, /* SS */
                     74:        { man_IP_pre, NULL }, /* TP */
                     75:        { man_PP_pre, NULL }, /* LP */
                     76:        { man_PP_pre, NULL }, /* PP */
                     77:        { man_PP_pre, NULL }, /* P */
                     78:        { man_IP_pre, NULL }, /* IP */
                     79:        { man_HP_pre, NULL }, /* HP */
                     80:        { man_SM_pre, NULL }, /* SM */
                     81:        { man_SB_pre, NULL }, /* SB */
                     82:        { man_alt_pre, NULL }, /* BI */
                     83:        { man_alt_pre, NULL }, /* IB */
                     84:        { man_alt_pre, NULL }, /* BR */
                     85:        { man_alt_pre, NULL }, /* RB */
                     86:        { NULL, NULL }, /* R */
                     87:        { man_B_pre, NULL }, /* B */
                     88:        { man_I_pre, NULL }, /* I */
                     89:        { man_alt_pre, NULL }, /* IR */
                     90:        { man_alt_pre, NULL }, /* RI */
                     91:        { NULL, NULL }, /* na */
                     92:        { NULL, NULL }, /* i */
                     93:        { man_br_pre, NULL }, /* sp */
                     94:        { NULL, NULL }, /* nf */
                     95:        { NULL, NULL }, /* fi */
                     96:        { NULL, NULL }, /* r */
                     97:        { NULL, NULL }, /* RE */
                     98:        { man_RS_pre, NULL }, /* RS */
                     99:        { man_ign_pre, NULL }, /* DT */
                    100:        { man_ign_pre, NULL }, /* UC */
1.2       schwarze  101:        { man_ign_pre, NULL }, /* PD */
1.6       schwarze  102:        { man_br_pre, NULL }, /* Sp */
1.8       schwarze  103:        { man_ign_pre, NULL }, /* Vb */
                    104:        { NULL, NULL }, /* Ve */
                    105:        { man_ign_pre, NULL }, /* de */
                    106:        { man_ign_pre, NULL }, /* dei */
                    107:        { man_ign_pre, NULL }, /* am */
                    108:        { man_ign_pre, NULL }, /* ami */
                    109:        { man_ign_pre, NULL }, /* ig */
                    110:        { NULL, NULL }, /* . */
1.9       schwarze  111:        { NULL, NULL }, /* if */
                    112:        { NULL, NULL }, /* ie */
                    113:        { NULL, NULL }, /* el */
1.1       schwarze  114: };
                    115:
                    116:
                    117: void
                    118: html_man(void *arg, const struct man *m)
                    119: {
                    120:        struct html     *h;
                    121:        struct tag      *t;
                    122:
                    123:        h = (struct html *)arg;
                    124:
1.5       schwarze  125:        print_gen_decls(h);
1.1       schwarze  126:
                    127:        t = print_otag(h, TAG_HTML, 0, NULL);
                    128:        print_man(man_meta(m), man_node(m), h);
                    129:        print_tagq(h, t);
                    130:
                    131:        printf("\n");
                    132: }
                    133:
                    134:
                    135: static void
                    136: print_man(MAN_ARGS)
                    137: {
                    138:        struct tag      *t;
                    139:        struct htmlpair  tag;
                    140:
                    141:        t = print_otag(h, TAG_HEAD, 0, NULL);
                    142:
                    143:        print_man_head(m, n, h);
                    144:        print_tagq(h, t);
                    145:        t = print_otag(h, TAG_BODY, 0, NULL);
                    146:
                    147:        tag.key = ATTR_CLASS;
                    148:        tag.val = "body";
                    149:        print_otag(h, TAG_DIV, 1, &tag);
                    150:
                    151:        print_man_nodelist(m, n, h);
                    152:
                    153:        print_tagq(h, t);
                    154: }
                    155:
                    156:
                    157: /* ARGSUSED */
                    158: static void
                    159: print_man_head(MAN_ARGS)
                    160: {
                    161:
                    162:        print_gen_head(h);
                    163:        bufinit(h);
1.10    ! schwarze  164:        buffmt(h, "%s(%s)", m->title, m->msec);
1.1       schwarze  165:
                    166:        print_otag(h, TAG_TITLE, 0, NULL);
                    167:        print_text(h, h->buf);
                    168: }
                    169:
                    170:
                    171: static void
                    172: print_man_nodelist(MAN_ARGS)
                    173: {
                    174:
                    175:        print_man_node(m, n, h);
                    176:        if (n->next)
                    177:                print_man_nodelist(m, n->next, h);
                    178: }
                    179:
                    180:
                    181: static void
                    182: print_man_node(MAN_ARGS)
                    183: {
                    184:        int              child;
                    185:        struct tag      *t;
                    186:
                    187:        child = 1;
1.2       schwarze  188:        t = h->tags.head;
1.1       schwarze  189:
                    190:        bufinit(h);
                    191:
1.7       schwarze  192:        /*
                    193:         * FIXME: embedded elements within next-line scopes (e.g., `br'
                    194:         * within an empty `B') will cause formatting to be forgotten
                    195:         * due to scope closing out.
                    196:         */
                    197:
1.1       schwarze  198:        switch (n->type) {
                    199:        case (MAN_ROOT):
                    200:                child = man_root_pre(m, n, h);
                    201:                break;
                    202:        case (MAN_TEXT):
                    203:                print_text(h, n->string);
1.4       schwarze  204:                return;
1.1       schwarze  205:        default:
1.4       schwarze  206:                /*
                    207:                 * Close out scope of font prior to opening a macro
                    208:                 * scope.  Assert that the metafont is on the top of the
                    209:                 * stack (it's never nested).
                    210:                 */
                    211:                if (h->metaf) {
                    212:                        assert(h->metaf == t);
                    213:                        print_tagq(h, h->metaf);
                    214:                        assert(NULL == h->metaf);
                    215:                        t = h->tags.head;
                    216:                }
1.1       schwarze  217:                if (mans[n->tok].pre)
                    218:                        child = (*mans[n->tok].pre)(m, n, h);
                    219:                break;
                    220:        }
                    221:
                    222:        if (child && n->child)
                    223:                print_man_nodelist(m, n->child, h);
                    224:
1.4       schwarze  225:        /* This will automatically close out any font scope. */
1.1       schwarze  226:        print_stagq(h, t);
                    227:
                    228:        bufinit(h);
                    229:
                    230:        switch (n->type) {
                    231:        case (MAN_ROOT):
                    232:                man_root_post(m, n, h);
                    233:                break;
                    234:        case (MAN_TEXT):
                    235:                break;
                    236:        default:
                    237:                if (mans[n->tok].post)
                    238:                        (*mans[n->tok].post)(m, n, h);
                    239:                break;
                    240:        }
                    241: }
                    242:
                    243:
                    244: static int
                    245: a2width(const struct man_node *n, struct roffsu *su)
                    246: {
                    247:
                    248:        if (MAN_TEXT != n->type)
                    249:                return(0);
                    250:        if (a2roffsu(n->string, su, SCALE_BU))
                    251:                return(1);
                    252:
                    253:        return(0);
                    254: }
                    255:
                    256:
                    257: /* ARGSUSED */
                    258: static int
                    259: man_root_pre(MAN_ARGS)
                    260: {
1.3       schwarze  261:        struct htmlpair  tag[3];
1.1       schwarze  262:        struct tag      *t, *tt;
                    263:        char             b[BUFSIZ], title[BUFSIZ];
                    264:
                    265:        b[0] = 0;
                    266:        if (m->vol)
                    267:                (void)strlcat(b, m->vol, BUFSIZ);
                    268:
1.10    ! schwarze  269:        snprintf(title, BUFSIZ - 1, "%s(%s)", m->title, m->msec);
1.1       schwarze  270:
                    271:        PAIR_CLASS_INIT(&tag[0], "header");
                    272:        bufcat_style(h, "width", "100%");
                    273:        PAIR_STYLE_INIT(&tag[1], h);
1.3       schwarze  274:        PAIR_SUMMARY_INIT(&tag[2], "header");
                    275:
                    276:        t = print_otag(h, TAG_TABLE, 3, tag);
1.1       schwarze  277:        tt = print_otag(h, TAG_TR, 0, NULL);
                    278:
                    279:        bufinit(h);
                    280:        bufcat_style(h, "width", "10%");
                    281:        PAIR_STYLE_INIT(&tag[0], h);
                    282:        print_otag(h, TAG_TD, 1, tag);
                    283:        print_text(h, title);
                    284:        print_stagq(h, tt);
                    285:
                    286:        bufinit(h);
                    287:        bufcat_style(h, "width", "80%");
                    288:        bufcat_style(h, "white-space", "nowrap");
                    289:        bufcat_style(h, "text-align", "center");
                    290:        PAIR_STYLE_INIT(&tag[0], h);
                    291:        print_otag(h, TAG_TD, 1, tag);
                    292:        print_text(h, b);
                    293:        print_stagq(h, tt);
                    294:
                    295:        bufinit(h);
                    296:        bufcat_style(h, "width", "10%");
                    297:        bufcat_style(h, "text-align", "right");
                    298:        PAIR_STYLE_INIT(&tag[0], h);
                    299:        print_otag(h, TAG_TD, 1, tag);
                    300:        print_text(h, title);
                    301:        print_tagq(h, t);
                    302:        return(1);
                    303: }
                    304:
                    305:
                    306: /* ARGSUSED */
                    307: static void
                    308: man_root_post(MAN_ARGS)
                    309: {
1.3       schwarze  310:        struct htmlpair  tag[3];
1.1       schwarze  311:        struct tag      *t, *tt;
1.2       schwarze  312:        char             b[DATESIZ];
1.1       schwarze  313:
1.2       schwarze  314:        time2a(m->date, b, DATESIZ);
1.1       schwarze  315:
                    316:        PAIR_CLASS_INIT(&tag[0], "footer");
                    317:        bufcat_style(h, "width", "100%");
                    318:        PAIR_STYLE_INIT(&tag[1], h);
1.3       schwarze  319:        PAIR_SUMMARY_INIT(&tag[2], "footer");
                    320:
                    321:        t = print_otag(h, TAG_TABLE, 3, tag);
1.1       schwarze  322:        tt = print_otag(h, TAG_TR, 0, NULL);
                    323:
                    324:        bufinit(h);
                    325:        bufcat_style(h, "width", "50%");
                    326:        PAIR_STYLE_INIT(&tag[0], h);
                    327:        print_otag(h, TAG_TD, 1, tag);
                    328:        print_text(h, b);
                    329:        print_stagq(h, tt);
                    330:
                    331:        bufinit(h);
                    332:        bufcat_style(h, "width", "50%");
                    333:        bufcat_style(h, "text-align", "right");
                    334:        PAIR_STYLE_INIT(&tag[0], h);
                    335:        print_otag(h, TAG_TD, 1, tag);
                    336:        if (m->source)
                    337:                print_text(h, m->source);
                    338:        print_tagq(h, t);
                    339: }
                    340:
                    341:
                    342:
                    343: /* ARGSUSED */
                    344: static int
                    345: man_br_pre(MAN_ARGS)
                    346: {
                    347:        struct roffsu    su;
                    348:        struct htmlpair  tag;
                    349:
                    350:        SCALE_VS_INIT(&su, 1);
                    351:
1.8       schwarze  352:        switch (n->tok) {
                    353:        case (MAN_Sp):
                    354:                SCALE_VS_INIT(&su, 0.5);
                    355:                break;
                    356:        case (MAN_sp):
                    357:                if (n->child)
                    358:                        a2roffsu(n->child->string, &su, SCALE_VS);
                    359:                break;
                    360:        default:
1.1       schwarze  361:                su.scale = 0;
1.8       schwarze  362:                break;
                    363:        }
1.1       schwarze  364:
                    365:        bufcat_su(h, "height", &su);
                    366:        PAIR_STYLE_INIT(&tag, h);
                    367:        print_otag(h, TAG_DIV, 1, &tag);
1.4       schwarze  368:
1.3       schwarze  369:        /* So the div isn't empty: */
                    370:        print_text(h, "\\~");
                    371:
1.1       schwarze  372:        return(0);
                    373: }
                    374:
                    375:
                    376: /* ARGSUSED */
                    377: static int
                    378: man_SH_pre(MAN_ARGS)
                    379: {
                    380:        struct htmlpair  tag[2];
                    381:        struct roffsu    su;
                    382:
                    383:        if (MAN_BODY == n->type) {
                    384:                SCALE_HS_INIT(&su, INDENT);
                    385:                bufcat_su(h, "margin-left", &su);
                    386:                PAIR_CLASS_INIT(&tag[0], "sec-body");
                    387:                PAIR_STYLE_INIT(&tag[1], h);
                    388:                print_otag(h, TAG_DIV, 2, tag);
                    389:                return(1);
                    390:        } else if (MAN_BLOCK == n->type) {
                    391:                PAIR_CLASS_INIT(&tag[0], "sec-block");
                    392:                if (n->prev && MAN_SH == n->prev->tok)
                    393:                        if (NULL == n->prev->body->child) {
                    394:                                print_otag(h, TAG_DIV, 1, tag);
                    395:                                return(1);
                    396:                        }
                    397:
                    398:                SCALE_VS_INIT(&su, 1);
                    399:                bufcat_su(h, "margin-top", &su);
                    400:                if (NULL == n->next)
                    401:                        bufcat_su(h, "margin-bottom", &su);
                    402:                PAIR_STYLE_INIT(&tag[1], h);
                    403:                print_otag(h, TAG_DIV, 2, tag);
                    404:                return(1);
                    405:        }
                    406:
                    407:        PAIR_CLASS_INIT(&tag[0], "sec-head");
                    408:        print_otag(h, TAG_DIV, 1, tag);
                    409:        return(1);
                    410: }
                    411:
                    412:
                    413: /* ARGSUSED */
                    414: static int
                    415: man_alt_pre(MAN_ARGS)
                    416: {
                    417:        const struct man_node   *nn;
                    418:        struct tag              *t;
                    419:        int                      i;
1.4       schwarze  420:        enum htmlfont            fp;
1.1       schwarze  421:
                    422:        for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
                    423:                switch (n->tok) {
                    424:                case (MAN_BI):
1.4       schwarze  425:                        fp = i % 2 ? HTMLFONT_ITALIC : HTMLFONT_BOLD;
1.1       schwarze  426:                        break;
                    427:                case (MAN_IB):
1.4       schwarze  428:                        fp = i % 2 ? HTMLFONT_BOLD : HTMLFONT_ITALIC;
1.1       schwarze  429:                        break;
                    430:                case (MAN_RI):
1.4       schwarze  431:                        fp = i % 2 ? HTMLFONT_ITALIC : HTMLFONT_NONE;
1.1       schwarze  432:                        break;
                    433:                case (MAN_IR):
1.4       schwarze  434:                        fp = i % 2 ? HTMLFONT_NONE : HTMLFONT_ITALIC;
1.1       schwarze  435:                        break;
                    436:                case (MAN_BR):
1.4       schwarze  437:                        fp = i % 2 ? HTMLFONT_NONE : HTMLFONT_BOLD;
1.1       schwarze  438:                        break;
                    439:                case (MAN_RB):
1.4       schwarze  440:                        fp = i % 2 ? HTMLFONT_BOLD : HTMLFONT_NONE;
1.1       schwarze  441:                        break;
                    442:                default:
                    443:                        abort();
                    444:                        /* NOTREACHED */
                    445:                }
                    446:
                    447:                if (i)
                    448:                        h->flags |= HTML_NOSPACE;
                    449:
1.4       schwarze  450:                /*
                    451:                 * Open and close the scope with each argument, so that
                    452:                 * internal \f escapes, which are common, are also
                    453:                 * closed out with the scope.
                    454:                 */
                    455:                t = print_ofont(h, fp);
                    456:                print_man_node(m, nn, h);
                    457:                print_tagq(h, t);
1.1       schwarze  458:        }
                    459:
                    460:        return(0);
                    461: }
                    462:
                    463:
                    464: /* ARGSUSED */
                    465: static int
                    466: man_SB_pre(MAN_ARGS)
                    467: {
                    468:        struct htmlpair  tag;
                    469:
1.4       schwarze  470:        /* FIXME: print_ofont(). */
1.1       schwarze  471:        PAIR_CLASS_INIT(&tag, "small bold");
                    472:        print_otag(h, TAG_SPAN, 1, &tag);
                    473:        return(1);
                    474: }
                    475:
                    476:
                    477: /* ARGSUSED */
                    478: static int
                    479: man_SM_pre(MAN_ARGS)
                    480: {
                    481:        struct htmlpair  tag;
                    482:
                    483:        PAIR_CLASS_INIT(&tag, "small");
                    484:        print_otag(h, TAG_SPAN, 1, &tag);
                    485:        return(1);
                    486: }
                    487:
                    488:
                    489: /* ARGSUSED */
                    490: static int
                    491: man_SS_pre(MAN_ARGS)
                    492: {
                    493:        struct htmlpair  tag[3];
                    494:        struct roffsu    su;
                    495:
                    496:        SCALE_VS_INIT(&su, 1);
                    497:
                    498:        if (MAN_BODY == n->type) {
                    499:                PAIR_CLASS_INIT(&tag[0], "ssec-body");
                    500:                if (n->parent->next && n->child) {
                    501:                        bufcat_su(h, "margin-bottom", &su);
                    502:                        PAIR_STYLE_INIT(&tag[1], h);
                    503:                        print_otag(h, TAG_DIV, 2, tag);
                    504:                        return(1);
                    505:                }
                    506:
                    507:                print_otag(h, TAG_DIV, 1, tag);
                    508:                return(1);
                    509:        } else if (MAN_BLOCK == n->type) {
                    510:                PAIR_CLASS_INIT(&tag[0], "ssec-block");
                    511:                if (n->prev && MAN_SS == n->prev->tok)
                    512:                        if (n->prev->body->child) {
                    513:                                bufcat_su(h, "margin-top", &su);
                    514:                                PAIR_STYLE_INIT(&tag[1], h);
                    515:                                print_otag(h, TAG_DIV, 2, tag);
                    516:                                return(1);
                    517:                        }
                    518:
                    519:                print_otag(h, TAG_DIV, 1, tag);
                    520:                return(1);
                    521:        }
                    522:
                    523:        SCALE_HS_INIT(&su, INDENT - HALFINDENT);
                    524:        bufcat_su(h, "margin-left", &su);
                    525:        PAIR_CLASS_INIT(&tag[0], "ssec-head");
                    526:        PAIR_STYLE_INIT(&tag[1], h);
                    527:        print_otag(h, TAG_DIV, 2, tag);
                    528:        return(1);
                    529: }
                    530:
                    531:
                    532: /* ARGSUSED */
                    533: static int
                    534: man_PP_pre(MAN_ARGS)
                    535: {
                    536:        struct htmlpair  tag;
                    537:        struct roffsu    su;
                    538:        int              i;
                    539:
                    540:        if (MAN_BLOCK != n->type)
                    541:                return(1);
                    542:
                    543:        i = 0;
                    544:
1.4       schwarze  545:        if (MAN_ROOT == n->parent->type) {
1.1       schwarze  546:                SCALE_HS_INIT(&su, INDENT);
                    547:                bufcat_su(h, "margin-left", &su);
1.4       schwarze  548:                i = 1;
1.1       schwarze  549:        }
1.4       schwarze  550:        if (n->prev) {
1.1       schwarze  551:                SCALE_VS_INIT(&su, 1);
1.4       schwarze  552:                bufcat_su(h, "margin-top", &su);
                    553:                i = 1;
1.1       schwarze  554:        }
                    555:
                    556:        PAIR_STYLE_INIT(&tag, h);
1.4       schwarze  557:        print_otag(h, TAG_DIV, i, &tag);
1.1       schwarze  558:        return(1);
                    559: }
                    560:
                    561:
                    562: /* ARGSUSED */
                    563: static int
                    564: man_IP_pre(MAN_ARGS)
                    565: {
                    566:        struct roffsu            su;
                    567:        struct htmlpair          tag;
                    568:        const struct man_node   *nn;
                    569:        int                      width;
                    570:
                    571:        /*
                    572:         * This scattering of 1-BU margins and pads is to make sure that
                    573:         * when text overruns its box, the subsequent text isn't flush
                    574:         * up against it.  However, the rest of the right-hand box must
                    575:         * also be adjusted in consideration of this 1-BU space.
                    576:         */
                    577:
                    578:        if (MAN_BODY == n->type) {
                    579:                SCALE_HS_INIT(&su, INDENT);
                    580:                bufcat_su(h, "margin-left", &su);
                    581:                PAIR_STYLE_INIT(&tag, h);
                    582:                print_otag(h, TAG_DIV, 1, &tag);
                    583:                return(1);
                    584:        }
                    585:
                    586:        nn = MAN_BLOCK == n->type ?
                    587:                n->head->child : n->parent->head->child;
                    588:
                    589:        SCALE_HS_INIT(&su, INDENT);
                    590:        width = 0;
                    591:
1.7       schwarze  592:        /* Width is the last token. */
                    593:
1.1       schwarze  594:        if (MAN_IP == n->tok && NULL != nn)
                    595:                if (NULL != (nn = nn->next)) {
                    596:                        for ( ; nn->next; nn = nn->next)
                    597:                                /* Do nothing. */ ;
                    598:                        width = a2width(nn, &su);
                    599:                }
                    600:
1.7       schwarze  601:        /* Width is the first token. */
                    602:
                    603:        if (MAN_TP == n->tok && NULL != nn) {
                    604:                /* Skip past non-text children. */
                    605:                while (nn && MAN_TEXT != nn->type)
                    606:                        nn = nn->next;
                    607:                if (nn)
                    608:                        width = a2width(nn, &su);
                    609:        }
1.1       schwarze  610:
                    611:        if (MAN_BLOCK == n->type) {
                    612:                bufcat_su(h, "margin-left", &su);
                    613:                SCALE_VS_INIT(&su, 1);
                    614:                bufcat_su(h, "margin-top", &su);
                    615:                bufcat_style(h, "clear", "both");
                    616:                PAIR_STYLE_INIT(&tag, h);
                    617:                print_otag(h, TAG_DIV, 1, &tag);
                    618:                return(1);
                    619:        }
                    620:
                    621:        bufcat_su(h, "min-width", &su);
                    622:        SCALE_INVERT(&su);
                    623:        bufcat_su(h, "margin-left", &su);
                    624:        SCALE_HS_INIT(&su, 1);
                    625:        bufcat_su(h, "margin-right", &su);
                    626:        bufcat_style(h, "clear", "left");
                    627:
                    628:        if (n->next && n->next->child)
                    629:                bufcat_style(h, "float", "left");
                    630:
                    631:        PAIR_STYLE_INIT(&tag, h);
                    632:        print_otag(h, TAG_DIV, 1, &tag);
                    633:
1.7       schwarze  634:        /*
                    635:         * Without a length string, we can print all of our children.
                    636:         */
1.1       schwarze  637:
                    638:        if ( ! width)
                    639:                return(1);
1.7       schwarze  640:
                    641:        /*
                    642:         * When a length has been specified, we need to carefully print
                    643:         * our child context:  IP gets all children printed but the last
                    644:         * (the width), while TP gets all children printed but the first
                    645:         * (the width).
                    646:         */
1.1       schwarze  647:
                    648:        if (MAN_IP == n->tok)
                    649:                for (nn = n->child; nn->next; nn = nn->next)
                    650:                        print_man_node(m, nn, h);
                    651:        if (MAN_TP == n->tok)
                    652:                for (nn = n->child->next; nn; nn = nn->next)
                    653:                        print_man_node(m, nn, h);
                    654:
                    655:        return(0);
                    656: }
                    657:
                    658:
                    659: /* ARGSUSED */
                    660: static int
                    661: man_HP_pre(MAN_ARGS)
                    662: {
                    663:        const struct man_node   *nn;
                    664:        struct htmlpair          tag;
                    665:        struct roffsu            su;
                    666:
                    667:        if (MAN_HEAD == n->type)
                    668:                return(0);
                    669:
                    670:        nn = MAN_BLOCK == n->type ?
                    671:                n->head->child : n->parent->head->child;
                    672:
                    673:        SCALE_HS_INIT(&su, INDENT);
                    674:
                    675:        if (NULL != nn)
                    676:                (void)a2width(nn, &su);
                    677:
                    678:        if (MAN_BLOCK == n->type) {
                    679:                bufcat_su(h, "margin-left", &su);
                    680:                SCALE_VS_INIT(&su, 1);
                    681:                bufcat_su(h, "margin-top", &su);
                    682:                bufcat_style(h, "clear", "both");
                    683:                PAIR_STYLE_INIT(&tag, h);
                    684:                print_otag(h, TAG_DIV, 1, &tag);
                    685:                return(1);
                    686:        }
                    687:
                    688:        bufcat_su(h, "margin-left", &su);
                    689:        SCALE_INVERT(&su);
                    690:        bufcat_su(h, "text-indent", &su);
                    691:
                    692:        PAIR_STYLE_INIT(&tag, h);
                    693:        print_otag(h, TAG_DIV, 1, &tag);
                    694:        return(1);
                    695: }
                    696:
                    697:
                    698: /* ARGSUSED */
                    699: static int
                    700: man_B_pre(MAN_ARGS)
                    701: {
                    702:
1.4       schwarze  703:        print_ofont(h, HTMLFONT_BOLD);
1.1       schwarze  704:        return(1);
                    705: }
                    706:
                    707:
                    708: /* ARGSUSED */
                    709: static int
                    710: man_I_pre(MAN_ARGS)
                    711: {
1.4       schwarze  712:
                    713:        print_ofont(h, HTMLFONT_ITALIC);
1.1       schwarze  714:        return(1);
                    715: }
                    716:
                    717:
                    718: /* ARGSUSED */
                    719: static int
                    720: man_ign_pre(MAN_ARGS)
                    721: {
                    722:
                    723:        return(0);
                    724: }
                    725:
                    726:
                    727: /* ARGSUSED */
                    728: static int
                    729: man_RS_pre(MAN_ARGS)
                    730: {
                    731:        struct htmlpair  tag;
                    732:        struct roffsu    su;
                    733:
                    734:        if (MAN_HEAD == n->type)
                    735:                return(0);
                    736:        else if (MAN_BODY == n->type)
                    737:                return(1);
                    738:
                    739:        SCALE_HS_INIT(&su, INDENT);
                    740:        bufcat_su(h, "margin-left", &su);
                    741:
                    742:        if (n->head->child) {
                    743:                SCALE_VS_INIT(&su, 1);
                    744:                a2width(n->head->child, &su);
                    745:                bufcat_su(h, "margin-top", &su);
                    746:        }
                    747:
                    748:        PAIR_STYLE_INIT(&tag, h);
                    749:        print_otag(h, TAG_DIV, 1, &tag);
                    750:        return(1);
                    751: }