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

Annotation of mandoc/man_html.c, Revision 1.33

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

CVSweb