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

Annotation of mandoc/mdoc_html.c, Revision 1.1

1.1     ! kristaps    1: /*     $Id: html.c,v 1.50 2009/09/21 14:40:31 kristaps Exp $ */
        !             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: #include <sys/queue.h>
        !            19:
        !            20: #include <assert.h>
        !            21: #include <ctype.h>
        !            22: #include <err.h>
        !            23: #include <stdio.h>
        !            24: #include <stdlib.h>
        !            25: #include <string.h>
        !            26: #include <unistd.h>
        !            27:
        !            28: #include "html.h"
        !            29: #include "mdoc.h"
        !            30:
        !            31: #define        INDENT           5
        !            32: #define        HALFINDENT       3
        !            33:
        !            34: #define        MDOC_ARGS         const struct mdoc_meta *m, \
        !            35:                          const struct mdoc_node *n, \
        !            36:                          struct html *h
        !            37: #define        MAN_ARGS          const struct man_meta *m, \
        !            38:                          const struct man_node *n, \
        !            39:                          struct html *h
        !            40:
        !            41: struct htmlmdoc {
        !            42:        int             (*pre)(MDOC_ARGS);
        !            43:        void            (*post)(MDOC_ARGS);
        !            44: };
        !            45:
        !            46: static void              print_mdoc(MDOC_ARGS);
        !            47: static void              print_mdoc_head(MDOC_ARGS);
        !            48: static void              print_mdoc_node(MDOC_ARGS);
        !            49: static void              print_mdoc_nodelist(MDOC_ARGS);
        !            50:
        !            51: static int               a2width(const char *);
        !            52: static int               a2offs(const char *);
        !            53: static int               a2list(const struct mdoc_node *);
        !            54:
        !            55: static void              mdoc_root_post(MDOC_ARGS);
        !            56: static int               mdoc_root_pre(MDOC_ARGS);
        !            57: static int               mdoc_tbl_pre(MDOC_ARGS, int);
        !            58: static int               mdoc_tbl_block_pre(MDOC_ARGS, int, int, int, int);
        !            59: static int               mdoc_tbl_body_pre(MDOC_ARGS, int, int);
        !            60: static int               mdoc_tbl_head_pre(MDOC_ARGS, int, int);
        !            61:
        !            62: static int               mdoc_ad_pre(MDOC_ARGS);
        !            63: static int               mdoc_an_pre(MDOC_ARGS);
        !            64: static void              mdoc_aq_post(MDOC_ARGS);
        !            65: static int               mdoc_aq_pre(MDOC_ARGS);
        !            66: static int               mdoc_ar_pre(MDOC_ARGS);
        !            67: static int               mdoc_bd_pre(MDOC_ARGS);
        !            68: static void              mdoc_bl_post(MDOC_ARGS);
        !            69: static int               mdoc_bl_pre(MDOC_ARGS);
        !            70: static int               mdoc_cd_pre(MDOC_ARGS);
        !            71: static int               mdoc_d1_pre(MDOC_ARGS);
        !            72: static void              mdoc_dq_post(MDOC_ARGS);
        !            73: static int               mdoc_dq_pre(MDOC_ARGS);
        !            74: static int               mdoc_dv_pre(MDOC_ARGS);
        !            75: static int               mdoc_fa_pre(MDOC_ARGS);
        !            76: static int               mdoc_fd_pre(MDOC_ARGS);
        !            77: static int               mdoc_fl_pre(MDOC_ARGS);
        !            78: static int               mdoc_fn_pre(MDOC_ARGS);
        !            79: static int               mdoc_ft_pre(MDOC_ARGS);
        !            80: static int               mdoc_em_pre(MDOC_ARGS);
        !            81: static int               mdoc_er_pre(MDOC_ARGS);
        !            82: static int               mdoc_ev_pre(MDOC_ARGS);
        !            83: static int               mdoc_ex_pre(MDOC_ARGS);
        !            84: static int               mdoc_it_pre(MDOC_ARGS);
        !            85: static int               mdoc_nd_pre(MDOC_ARGS);
        !            86: static int               mdoc_nm_pre(MDOC_ARGS);
        !            87: static int               mdoc_ns_pre(MDOC_ARGS);
        !            88: static void              mdoc_op_post(MDOC_ARGS);
        !            89: static int               mdoc_op_pre(MDOC_ARGS);
        !            90: static int               mdoc_pa_pre(MDOC_ARGS);
        !            91: static void              mdoc_pq_post(MDOC_ARGS);
        !            92: static int               mdoc_pq_pre(MDOC_ARGS);
        !            93: static void              mdoc_qq_post(MDOC_ARGS);
        !            94: static int               mdoc_qq_pre(MDOC_ARGS);
        !            95: static int               mdoc_sh_pre(MDOC_ARGS);
        !            96: static int               mdoc_sp_pre(MDOC_ARGS);
        !            97: static void              mdoc_sq_post(MDOC_ARGS);
        !            98: static int               mdoc_sq_pre(MDOC_ARGS);
        !            99: static int               mdoc_ss_pre(MDOC_ARGS);
        !           100: static int               mdoc_sx_pre(MDOC_ARGS);
        !           101: static int               mdoc_vt_pre(MDOC_ARGS);
        !           102: static int               mdoc_xr_pre(MDOC_ARGS);
        !           103: static int               mdoc_xx_pre(MDOC_ARGS);
        !           104:
        !           105: #ifdef __linux__
        !           106: extern size_t            strlcpy(char *, const char *, size_t);
        !           107: extern size_t            strlcat(char *, const char *, size_t);
        !           108: #endif
        !           109:
        !           110: static const struct htmlmdoc mdocs[MDOC_MAX] = {
        !           111:        {NULL, NULL}, /* Ap */
        !           112:        {NULL, NULL}, /* Dd */
        !           113:        {NULL, NULL}, /* Dt */
        !           114:        {NULL, NULL}, /* Os */
        !           115:        {mdoc_sh_pre, NULL }, /* Sh */
        !           116:        {mdoc_ss_pre, NULL }, /* Ss */
        !           117:        {mdoc_sp_pre, NULL}, /* Pp */
        !           118:        {mdoc_d1_pre, NULL}, /* D1 */
        !           119:        {mdoc_d1_pre, NULL}, /* Dl */
        !           120:        {mdoc_bd_pre, NULL}, /* Bd */
        !           121:        {NULL, NULL}, /* Ed */
        !           122:        {mdoc_bl_pre, mdoc_bl_post}, /* Bl */
        !           123:        {NULL, NULL}, /* El */
        !           124:        {mdoc_it_pre, NULL}, /* It */
        !           125:        {mdoc_ad_pre, NULL}, /* Ad */
        !           126:        {mdoc_an_pre, NULL}, /* An */
        !           127:        {mdoc_ar_pre, NULL}, /* Ar */
        !           128:        {mdoc_cd_pre, NULL}, /* Cd */
        !           129:        {mdoc_fl_pre, NULL}, /* Cm */
        !           130:        {mdoc_dv_pre, NULL}, /* Dv */
        !           131:        {mdoc_er_pre, NULL}, /* Er */
        !           132:        {mdoc_ev_pre, NULL}, /* Ev */
        !           133:        {mdoc_ex_pre, NULL}, /* Ex */
        !           134:        {mdoc_fa_pre, NULL}, /* Fa */
        !           135:        {mdoc_fd_pre, NULL}, /* Fd */
        !           136:        {mdoc_fl_pre, NULL}, /* Fl */
        !           137:        {mdoc_fn_pre, NULL}, /* Fn */
        !           138:        {mdoc_ft_pre, NULL}, /* Ft */
        !           139:        {NULL, NULL}, /* Ic */
        !           140:        {NULL, NULL}, /* In */
        !           141:        {NULL, NULL}, /* Li */
        !           142:        {mdoc_nd_pre, NULL}, /* Nd */
        !           143:        {mdoc_nm_pre, NULL}, /* Nm */
        !           144:        {mdoc_op_pre, mdoc_op_post}, /* Op */
        !           145:        {NULL, NULL}, /* Ot */
        !           146:        {mdoc_pa_pre, NULL}, /* Pa */
        !           147:        {NULL, NULL}, /* Rv */
        !           148:        {NULL, NULL}, /* St */
        !           149:        {NULL, NULL}, /* Va */
        !           150:        {mdoc_vt_pre, NULL}, /* Vt */
        !           151:        {mdoc_xr_pre, NULL}, /* Xr */
        !           152:        {NULL, NULL}, /* %A */
        !           153:        {NULL, NULL}, /* %B */
        !           154:        {NULL, NULL}, /* %D */
        !           155:        {NULL, NULL}, /* %I */
        !           156:        {NULL, NULL}, /* %J */
        !           157:        {NULL, NULL}, /* %N */
        !           158:        {NULL, NULL}, /* %O */
        !           159:        {NULL, NULL}, /* %P */
        !           160:        {NULL, NULL}, /* %R */
        !           161:        {NULL, NULL}, /* %T */
        !           162:        {NULL, NULL}, /* %V */
        !           163:        {NULL, NULL}, /* Ac */
        !           164:        {mdoc_aq_pre, mdoc_aq_post}, /* Ao */
        !           165:        {mdoc_aq_pre, mdoc_aq_post}, /* Aq */
        !           166:        {NULL, NULL}, /* At */
        !           167:        {NULL, NULL}, /* Bc */
        !           168:        {NULL, NULL}, /* Bf */
        !           169:        {NULL, NULL}, /* Bo */
        !           170:        {NULL, NULL}, /* Bq */
        !           171:        {mdoc_xx_pre, NULL}, /* Bsx */
        !           172:        {NULL, NULL}, /* Bx */
        !           173:        {NULL, NULL}, /* Db */
        !           174:        {NULL, NULL}, /* Dc */
        !           175:        {NULL, NULL}, /* Do */
        !           176:        {mdoc_dq_pre, mdoc_dq_post}, /* Dq */
        !           177:        {NULL, NULL}, /* Ec */
        !           178:        {NULL, NULL}, /* Ef */
        !           179:        {mdoc_em_pre, NULL}, /* Em */
        !           180:        {NULL, NULL}, /* Eo */
        !           181:        {mdoc_xx_pre, NULL}, /* Fx */
        !           182:        {NULL, NULL}, /* Ms */
        !           183:        {NULL, NULL}, /* No */
        !           184:        {mdoc_ns_pre, NULL}, /* Ns */
        !           185:        {mdoc_xx_pre, NULL}, /* Nx */
        !           186:        {mdoc_xx_pre, NULL}, /* Ox */
        !           187:        {NULL, NULL}, /* Pc */
        !           188:        {NULL, NULL}, /* Pf */
        !           189:        {mdoc_pq_pre, mdoc_pq_post}, /* Po */
        !           190:        {mdoc_pq_pre, mdoc_pq_post}, /* Pq */
        !           191:        {NULL, NULL}, /* Qc */
        !           192:        {NULL, NULL}, /* Ql */
        !           193:        {mdoc_qq_pre, mdoc_qq_post}, /* Qo */
        !           194:        {mdoc_qq_pre, mdoc_qq_post}, /* Qq */
        !           195:        {NULL, NULL}, /* Re */
        !           196:        {NULL, NULL}, /* Rs */
        !           197:        {NULL, NULL}, /* Sc */
        !           198:        {mdoc_sq_pre, mdoc_sq_post}, /* So */
        !           199:        {mdoc_sq_pre, mdoc_sq_post}, /* Sq */
        !           200:        {NULL, NULL}, /* Sm */
        !           201:        {mdoc_sx_pre, NULL}, /* Sx */
        !           202:        {NULL, NULL}, /* Sy */
        !           203:        {NULL, NULL}, /* Tn */
        !           204:        {mdoc_xx_pre, NULL}, /* Ux */
        !           205:        {NULL, NULL}, /* Xc */
        !           206:        {NULL, NULL}, /* Xo */
        !           207:        {NULL, NULL}, /* Fo */
        !           208:        {NULL, NULL}, /* Fc */
        !           209:        {NULL, NULL}, /* Oo */
        !           210:        {NULL, NULL}, /* Oc */
        !           211:        {NULL, NULL}, /* Bk */
        !           212:        {NULL, NULL}, /* Ek */
        !           213:        {NULL, NULL}, /* Bt */
        !           214:        {NULL, NULL}, /* Hf */
        !           215:        {NULL, NULL}, /* Fr */
        !           216:        {NULL, NULL}, /* Ud */
        !           217:        {NULL, NULL}, /* Lb */
        !           218:        {mdoc_sp_pre, NULL}, /* Lp */
        !           219:        {NULL, NULL}, /* Lk */
        !           220:        {NULL, NULL}, /* Mt */
        !           221:        {NULL, NULL}, /* Brq */
        !           222:        {NULL, NULL}, /* Bro */
        !           223:        {NULL, NULL}, /* Brc */
        !           224:        {NULL, NULL}, /* %C */
        !           225:        {NULL, NULL}, /* Es */
        !           226:        {NULL, NULL}, /* En */
        !           227:        {mdoc_xx_pre, NULL}, /* Dx */
        !           228:        {NULL, NULL}, /* %Q */
        !           229:        {mdoc_sp_pre, NULL}, /* br */
        !           230:        {mdoc_sp_pre, NULL}, /* sp */
        !           231: };
        !           232:
        !           233: static char              buf[BUFSIZ]; /* XXX */
        !           234:
        !           235: #define        bufcat(x)         (void)strlcat(buf, (x), BUFSIZ)
        !           236: #define        bufinit()         buf[0] = 0
        !           237: #define        buffmt(...)       (void)snprintf(buf, BUFSIZ - 1, __VA_ARGS__)
        !           238:
        !           239: void
        !           240: html_mdoc(void *arg, const struct mdoc *m)
        !           241: {
        !           242:        struct html     *h;
        !           243:        struct tag      *t;
        !           244:
        !           245:        h = (struct html *)arg;
        !           246:
        !           247:        print_gen_doctype(h);
        !           248:        t = print_otag(h, TAG_HTML, 0, NULL);
        !           249:        print_mdoc(mdoc_meta(m), mdoc_node(m), h);
        !           250:        print_tagq(h, t);
        !           251:
        !           252:        printf("\n");
        !           253: }
        !           254:
        !           255:
        !           256: static int
        !           257: a2list(const struct mdoc_node *n)
        !           258: {
        !           259:        int              i;
        !           260:
        !           261:        assert(MDOC_BLOCK == n->type && MDOC_Bl == n->tok);
        !           262:        assert(n->args);
        !           263:
        !           264:        for (i = 0; i < (int)n->args->argc; i++)
        !           265:                switch (n->args->argv[i].arg) {
        !           266:                case (MDOC_Enum):
        !           267:                        /* FALLTHROUGH */
        !           268:                case (MDOC_Dash):
        !           269:                        /* FALLTHROUGH */
        !           270:                case (MDOC_Hyphen):
        !           271:                        /* FALLTHROUGH */
        !           272:                case (MDOC_Bullet):
        !           273:                        /* FALLTHROUGH */
        !           274:                case (MDOC_Tag):
        !           275:                        /* FALLTHROUGH */
        !           276:                case (MDOC_Hang):
        !           277:                        /* FALLTHROUGH */
        !           278:                case (MDOC_Inset):
        !           279:                        /* FALLTHROUGH */
        !           280:                case (MDOC_Diag):
        !           281:                        /* FALLTHROUGH */
        !           282:                case (MDOC_Item):
        !           283:                        /* FALLTHROUGH */
        !           284:                case (MDOC_Column):
        !           285:                        /* FALLTHROUGH */
        !           286:                case (MDOC_Ohang):
        !           287:                        return(n->args->argv[i].arg);
        !           288:                default:
        !           289:                        break;
        !           290:                }
        !           291:
        !           292:        abort();
        !           293:        /* NOTREACHED */
        !           294: }
        !           295:
        !           296:
        !           297: static int
        !           298: a2width(const char *p)
        !           299: {
        !           300:        int              i, len;
        !           301:
        !           302:        if (0 == (len = (int)strlen(p)))
        !           303:                return(0);
        !           304:        for (i = 0; i < len - 1; i++)
        !           305:                if ( ! isdigit((u_char)p[i]))
        !           306:                        break;
        !           307:
        !           308:        if (i == len - 1)
        !           309:                if ('n' == p[len - 1] || 'm' == p[len - 1])
        !           310:                        return(atoi(p) + 2);
        !           311:
        !           312:        return(len + 2);
        !           313: }
        !           314:
        !           315:
        !           316: static int
        !           317: a2offs(const char *p)
        !           318: {
        !           319:        int              len, i;
        !           320:
        !           321:        if (0 == strcmp(p, "left"))
        !           322:                return(0);
        !           323:        if (0 == strcmp(p, "indent"))
        !           324:                return(INDENT + 1);
        !           325:        if (0 == strcmp(p, "indent-two"))
        !           326:                return((INDENT + 1) * 2);
        !           327:
        !           328:        if (0 == (len = (int)strlen(p)))
        !           329:                return(0);
        !           330:
        !           331:        for (i = 0; i < len - 1; i++)
        !           332:                if ( ! isdigit((u_char)p[i]))
        !           333:                        break;
        !           334:
        !           335:        if (i == len - 1)
        !           336:                if ('n' == p[len - 1] || 'm' == p[len - 1])
        !           337:                        return(atoi(p));
        !           338:
        !           339:        return(len);
        !           340: }
        !           341:
        !           342:
        !           343: static void
        !           344: print_mdoc(MDOC_ARGS)
        !           345: {
        !           346:        struct tag      *t;
        !           347:        struct htmlpair  tag;
        !           348:
        !           349:        t = print_otag(h, TAG_HEAD, 0, NULL);
        !           350:        print_mdoc_head(m, n, h);
        !           351:        print_tagq(h, t);
        !           352:
        !           353:        t = print_otag(h, TAG_BODY, 0, NULL);
        !           354:
        !           355:        tag.key = ATTR_CLASS;
        !           356:        tag.val = "body";
        !           357:        print_otag(h, TAG_DIV, 1, &tag);
        !           358:
        !           359:        print_mdoc_nodelist(m, n, h);
        !           360:        print_tagq(h, t);
        !           361: }
        !           362:
        !           363:
        !           364: /* ARGSUSED */
        !           365: static void
        !           366: print_mdoc_head(MDOC_ARGS)
        !           367: {
        !           368:        char            b[BUFSIZ];
        !           369:
        !           370:        print_gen_head(h);
        !           371:
        !           372:        (void)snprintf(b, BUFSIZ - 1,
        !           373:                        "%s(%d)", m->title, m->msec);
        !           374:
        !           375:        if (m->arch) {
        !           376:                (void)strlcat(b, " (", BUFSIZ);
        !           377:                (void)strlcat(b, m->arch, BUFSIZ);
        !           378:                (void)strlcat(b, ")", BUFSIZ);
        !           379:        }
        !           380:
        !           381:        print_otag(h, TAG_TITLE, 0, NULL);
        !           382:        print_text(h, b);
        !           383: }
        !           384:
        !           385:
        !           386: static void
        !           387: print_mdoc_nodelist(MDOC_ARGS)
        !           388: {
        !           389:
        !           390:        print_mdoc_node(m, n, h);
        !           391:        if (n->next)
        !           392:                print_mdoc_nodelist(m, n->next, h);
        !           393: }
        !           394:
        !           395:
        !           396: static void
        !           397: print_mdoc_node(MDOC_ARGS)
        !           398: {
        !           399:        int              child;
        !           400:        struct tag      *t;
        !           401:
        !           402:        child = 1;
        !           403:        t = SLIST_FIRST(&h->tags);
        !           404:
        !           405:        bufinit();
        !           406:
        !           407:        switch (n->type) {
        !           408:        case (MDOC_ROOT):
        !           409:                child = mdoc_root_pre(m, n, h);
        !           410:                break;
        !           411:        case (MDOC_TEXT):
        !           412:                print_text(h, n->string);
        !           413:                break;
        !           414:        default:
        !           415:                if (mdocs[n->tok].pre)
        !           416:                        child = (*mdocs[n->tok].pre)(m, n, h);
        !           417:                break;
        !           418:        }
        !           419:
        !           420:        if (child && n->child)
        !           421:                print_mdoc_nodelist(m, n->child, h);
        !           422:
        !           423:        print_stagq(h, t);
        !           424:
        !           425:        bufinit();
        !           426:
        !           427:        switch (n->type) {
        !           428:        case (MDOC_ROOT):
        !           429:                mdoc_root_post(m, n, h);
        !           430:                break;
        !           431:        case (MDOC_TEXT):
        !           432:                break;
        !           433:        default:
        !           434:                if (mdocs[n->tok].post)
        !           435:                        (*mdocs[n->tok].post)(m, n, h);
        !           436:                break;
        !           437:        }
        !           438: }
        !           439:
        !           440:
        !           441: /* ARGSUSED */
        !           442: static void
        !           443: mdoc_root_post(MDOC_ARGS)
        !           444: {
        !           445:        struct tm        tm;
        !           446:        struct htmlpair  tag[2];
        !           447:        struct tag      *t, *tt;
        !           448:        char             b[BUFSIZ];
        !           449:
        !           450:        (void)localtime_r(&m->date, &tm);
        !           451:
        !           452:        if (0 == strftime(b, BUFSIZ - 1, "%B %e, %Y", &tm))
        !           453:                err(EXIT_FAILURE, "strftime");
        !           454:
        !           455:        tag[0].key = ATTR_CLASS;
        !           456:        tag[0].val = "footer";
        !           457:        tag[1].key = ATTR_STYLE;
        !           458:        tag[1].val = "width: 100%;";
        !           459:        t = print_otag(h, TAG_TABLE, 2, tag);
        !           460:        tt = print_otag(h, TAG_TR, 0, NULL);
        !           461:
        !           462:        tag[0].key = ATTR_STYLE;
        !           463:        tag[0].val = "width: 50%;";
        !           464:        print_otag(h, TAG_TD, 1, tag);
        !           465:        print_text(h, b);
        !           466:        print_stagq(h, tt);
        !           467:
        !           468:        tag[0].key = ATTR_STYLE;
        !           469:        tag[0].val = "width: 50%; text-align: right;";
        !           470:        print_otag(h, TAG_TD, 1, tag);
        !           471:        print_text(h, m->os);
        !           472:        print_tagq(h, t);
        !           473: }
        !           474:
        !           475:
        !           476: /* ARGSUSED */
        !           477: static int
        !           478: mdoc_root_pre(MDOC_ARGS)
        !           479: {
        !           480:        struct htmlpair  tag[2];
        !           481:        struct tag      *t, *tt;
        !           482:        char             b[BUFSIZ], title[BUFSIZ];
        !           483:
        !           484:        (void)strlcpy(b, m->vol, BUFSIZ);
        !           485:
        !           486:        if (m->arch) {
        !           487:                (void)strlcat(b, " (", BUFSIZ);
        !           488:                (void)strlcat(b, m->arch, BUFSIZ);
        !           489:                (void)strlcat(b, ")", BUFSIZ);
        !           490:        }
        !           491:
        !           492:        (void)snprintf(title, BUFSIZ - 1,
        !           493:                        "%s(%d)", m->title, m->msec);
        !           494:
        !           495:        tag[0].key = ATTR_CLASS;
        !           496:        tag[0].val = "header";
        !           497:        tag[1].key = ATTR_STYLE;
        !           498:        tag[1].val = "width: 100%;";
        !           499:        t = print_otag(h, TAG_TABLE, 2, tag);
        !           500:        tt = print_otag(h, TAG_TR, 0, NULL);
        !           501:
        !           502:        tag[0].key = ATTR_STYLE;
        !           503:        tag[0].val = "width: 33%;";
        !           504:        print_otag(h, TAG_TD, 1, tag);
        !           505:        print_text(h, b);
        !           506:        print_stagq(h, tt);
        !           507:
        !           508:        tag[0].key = ATTR_STYLE;
        !           509:        tag[0].val = "width: 33%; text-align: center;";
        !           510:        print_otag(h, TAG_TD, 1, tag);
        !           511:        print_text(h, title);
        !           512:        print_stagq(h, tt);
        !           513:
        !           514:        tag[0].key = ATTR_STYLE;
        !           515:        tag[0].val = "width: 33%; text-align: right;";
        !           516:        print_otag(h, TAG_TD, 1, tag);
        !           517:        print_text(h, b);
        !           518:        print_tagq(h, t);
        !           519:
        !           520:        return(1);
        !           521: }
        !           522:
        !           523:
        !           524: /* ARGSUSED */
        !           525: static int
        !           526: mdoc_sh_pre(MDOC_ARGS)
        !           527: {
        !           528:        struct htmlpair          tag[2];
        !           529:        const struct mdoc_node  *nn;
        !           530:
        !           531:        if (MDOC_HEAD == n->type) {
        !           532:                tag[0].key = ATTR_CLASS;
        !           533:                tag[0].val = "sec-head";
        !           534:                print_otag(h, TAG_DIV, 1, tag);
        !           535:                print_otag(h, TAG_SPAN, 1, tag);
        !           536:
        !           537:                for (nn = n->child; nn; nn = nn->next) {
        !           538:                        bufcat(nn->string);
        !           539:                        if (nn->next)
        !           540:                                bufcat(" ");
        !           541:                }
        !           542:                tag[0].key = ATTR_NAME;
        !           543:                tag[0].val = buf;
        !           544:                print_otag(h, TAG_A, 1, tag);
        !           545:                return(1);
        !           546:        } else if (MDOC_BLOCK == n->type) {
        !           547:                tag[0].key = ATTR_CLASS;
        !           548:                tag[0].val = "sec-block";
        !           549:
        !           550:                if (n->prev && NULL == n->prev->body->child) {
        !           551:                        print_otag(h, TAG_DIV, 1, tag);
        !           552:                        return(1);
        !           553:                }
        !           554:
        !           555:                bufcat("margin-top: 1em;");
        !           556:                if (NULL == n->next)
        !           557:                        bufcat("margin-bottom: 1em;");
        !           558:
        !           559:                tag[1].key = ATTR_STYLE;
        !           560:                tag[1].val = buf;
        !           561:
        !           562:                print_otag(h, TAG_DIV, 2, tag);
        !           563:                return(1);
        !           564:        }
        !           565:
        !           566:        buffmt("margin-left: %dem;", INDENT);
        !           567:
        !           568:        tag[0].key = ATTR_CLASS;
        !           569:        tag[0].val = "sec-body";
        !           570:        tag[1].key = ATTR_STYLE;
        !           571:        tag[1].val = buf;
        !           572:
        !           573:        print_otag(h, TAG_DIV, 2, tag);
        !           574:        return(1);
        !           575: }
        !           576:
        !           577:
        !           578: /* ARGSUSED */
        !           579: static int
        !           580: mdoc_ss_pre(MDOC_ARGS)
        !           581: {
        !           582:        struct htmlpair          tag[2];
        !           583:        int                      i;
        !           584:        const struct mdoc_node  *nn;
        !           585:
        !           586:        i = 0;
        !           587:
        !           588:        if (MDOC_BODY == n->type) {
        !           589:                tag[i].key = ATTR_CLASS;
        !           590:                tag[i++].val = "ssec-body";
        !           591:                if (n->parent->next && n->child) {
        !           592:                        bufcat("margin-bottom: 1em;");
        !           593:                        tag[i].key = ATTR_STYLE;
        !           594:                        tag[i++].val = buf;
        !           595:                }
        !           596:                print_otag(h, TAG_DIV, i, tag);
        !           597:                return(1);
        !           598:        } else if (MDOC_BLOCK == n->type) {
        !           599:                tag[i].key = ATTR_CLASS;
        !           600:                tag[i++].val = "ssec-block";
        !           601:                if (n->prev) {
        !           602:                        bufcat("margin-top: 1em;");
        !           603:                        tag[i].key = ATTR_STYLE;
        !           604:                        tag[i++].val = buf;
        !           605:                }
        !           606:                print_otag(h, TAG_DIV, i, tag);
        !           607:                return(1);
        !           608:        }
        !           609:
        !           610:        buffmt("margin-left: -%dem;", INDENT - HALFINDENT);
        !           611:
        !           612:        tag[0].key = ATTR_CLASS;
        !           613:        tag[0].val = "ssec-head";
        !           614:        tag[1].key = ATTR_STYLE;
        !           615:        tag[1].val = buf;
        !           616:
        !           617:        print_otag(h, TAG_DIV, 2, tag);
        !           618:        print_otag(h, TAG_SPAN, 1, tag);
        !           619:
        !           620:        bufinit();
        !           621:        for (nn = n->child; nn; nn = nn->next) {
        !           622:                bufcat(nn->string);
        !           623:                if (nn->next)
        !           624:                        bufcat(" ");
        !           625:        }
        !           626:        tag[0].key = ATTR_NAME;
        !           627:        tag[0].val = buf;
        !           628:        print_otag(h, TAG_A, 1, tag);
        !           629:
        !           630:        return(1);
        !           631: }
        !           632:
        !           633:
        !           634: /* ARGSUSED */
        !           635: static int
        !           636: mdoc_fl_pre(MDOC_ARGS)
        !           637: {
        !           638:        struct htmlpair  tag;
        !           639:
        !           640:        tag.key = ATTR_CLASS;
        !           641:        tag.val = "flag";
        !           642:
        !           643:        print_otag(h, TAG_SPAN, 1, &tag);
        !           644:        if (MDOC_Fl == n->tok) {
        !           645:                print_text(h, "\\-");
        !           646:                h->flags |= HTML_NOSPACE;
        !           647:        }
        !           648:        return(1);
        !           649: }
        !           650:
        !           651:
        !           652: /* ARGSUSED */
        !           653: static int
        !           654: mdoc_nd_pre(MDOC_ARGS)
        !           655: {
        !           656:        struct htmlpair  tag;
        !           657:
        !           658:        if (MDOC_BODY != n->type)
        !           659:                return(1);
        !           660:
        !           661:        /* XXX - this can contain block elements! */
        !           662:        print_text(h, "\\(em");
        !           663:        tag.key = ATTR_CLASS;
        !           664:        tag.val = "desc-body";
        !           665:        print_otag(h, TAG_SPAN, 1, &tag);
        !           666:        return(1);
        !           667: }
        !           668:
        !           669:
        !           670: /* ARGSUSED */
        !           671: static int
        !           672: mdoc_op_pre(MDOC_ARGS)
        !           673: {
        !           674:        struct htmlpair  tag;
        !           675:
        !           676:        if (MDOC_BODY != n->type)
        !           677:                return(1);
        !           678:
        !           679:        /* XXX - this can contain block elements! */
        !           680:        print_text(h, "\\(lB");
        !           681:        h->flags |= HTML_NOSPACE;
        !           682:        tag.key = ATTR_CLASS;
        !           683:        tag.val = "opt";
        !           684:        print_otag(h, TAG_SPAN, 1, &tag);
        !           685:        return(1);
        !           686: }
        !           687:
        !           688:
        !           689: /* ARGSUSED */
        !           690: static void
        !           691: mdoc_op_post(MDOC_ARGS)
        !           692: {
        !           693:
        !           694:        if (MDOC_BODY != n->type)
        !           695:                return;
        !           696:        h->flags |= HTML_NOSPACE;
        !           697:        print_text(h, "\\(rB");
        !           698: }
        !           699:
        !           700:
        !           701: static int
        !           702: mdoc_nm_pre(MDOC_ARGS)
        !           703: {
        !           704:        struct htmlpair tag;
        !           705:
        !           706:        if ( ! (HTML_NEWLINE & h->flags))
        !           707:                if (SEC_SYNOPSIS == n->sec) {
        !           708:                        tag.key = ATTR_STYLE;
        !           709:                        tag.val = "clear: both;";
        !           710:                        print_otag(h, TAG_BR, 1, &tag);
        !           711:                }
        !           712:
        !           713:        tag.key = ATTR_CLASS;
        !           714:        tag.val = "name";
        !           715:
        !           716:        print_otag(h, TAG_SPAN, 1, &tag);
        !           717:        if (NULL == n->child)
        !           718:                print_text(h, m->name);
        !           719:
        !           720:        return(1);
        !           721: }
        !           722:
        !           723:
        !           724: /* ARGSUSED */
        !           725: static int
        !           726: mdoc_xr_pre(MDOC_ARGS)
        !           727: {
        !           728:        struct htmlpair          tag[2];
        !           729:        const char              *name, *sec;
        !           730:        const struct mdoc_node  *nn;
        !           731:
        !           732:        nn = n->child;
        !           733:        name = nn && nn->string ? nn->string : "";
        !           734:        nn = nn ? nn->next : NULL;
        !           735:        sec = nn && nn->string ? nn->string : "";
        !           736:
        !           737:        buffmt("%s%s%s.html", name, name && sec ? "." : "", sec);
        !           738:
        !           739:        tag[0].key = ATTR_CLASS;
        !           740:        tag[0].val = "link-man";
        !           741:        tag[1].key = ATTR_HREF;
        !           742:        tag[1].val = buf;
        !           743:        print_otag(h, TAG_A, 2, tag);
        !           744:
        !           745:        nn = n->child;
        !           746:        print_text(h, nn->string);
        !           747:        if (NULL == (nn = nn->next))
        !           748:                return(0);
        !           749:
        !           750:        h->flags |= HTML_NOSPACE;
        !           751:        print_text(h, "(");
        !           752:        h->flags |= HTML_NOSPACE;
        !           753:        print_text(h, nn->string);
        !           754:        h->flags |= HTML_NOSPACE;
        !           755:        print_text(h, ")");
        !           756:
        !           757:        return(0);
        !           758: }
        !           759:
        !           760:
        !           761: /* ARGSUSED */
        !           762: static int
        !           763: mdoc_ns_pre(MDOC_ARGS)
        !           764: {
        !           765:
        !           766:        h->flags |= HTML_NOSPACE;
        !           767:        return(1);
        !           768: }
        !           769:
        !           770:
        !           771: /* ARGSUSED */
        !           772: static int
        !           773: mdoc_ar_pre(MDOC_ARGS)
        !           774: {
        !           775:        struct htmlpair tag;
        !           776:
        !           777:        tag.key = ATTR_CLASS;
        !           778:        tag.val = "arg";
        !           779:
        !           780:        print_otag(h, TAG_SPAN, 1, &tag);
        !           781:        return(1);
        !           782: }
        !           783:
        !           784:
        !           785: /* ARGSUSED */
        !           786: static int
        !           787: mdoc_xx_pre(MDOC_ARGS)
        !           788: {
        !           789:        const char      *pp;
        !           790:        struct htmlpair  tag;
        !           791:
        !           792:        switch (n->tok) {
        !           793:        case (MDOC_Bsx):
        !           794:                pp = "BSDI BSD/OS";
        !           795:                break;
        !           796:        case (MDOC_Dx):
        !           797:                pp = "DragonFlyBSD";
        !           798:                break;
        !           799:        case (MDOC_Fx):
        !           800:                pp = "FreeBSD";
        !           801:                break;
        !           802:        case (MDOC_Nx):
        !           803:                pp = "NetBSD";
        !           804:                break;
        !           805:        case (MDOC_Ox):
        !           806:                pp = "OpenBSD";
        !           807:                break;
        !           808:        case (MDOC_Ux):
        !           809:                pp = "UNIX";
        !           810:                break;
        !           811:        default:
        !           812:                return(1);
        !           813:        }
        !           814:
        !           815:        tag.key = ATTR_CLASS;
        !           816:        tag.val = "unix";
        !           817:
        !           818:        print_otag(h, TAG_SPAN, 1, &tag);
        !           819:        print_text(h, pp);
        !           820:        return(1);
        !           821: }
        !           822:
        !           823:
        !           824: /* ARGSUSED */
        !           825: static int
        !           826: mdoc_tbl_block_pre(MDOC_ARGS, int t, int w, int o, int c)
        !           827: {
        !           828:        struct htmlpair  tag;
        !           829:
        !           830:        switch (t) {
        !           831:        case (MDOC_Column):
        !           832:                /* FALLTHROUGH */
        !           833:        case (MDOC_Item):
        !           834:                /* FALLTHROUGH */
        !           835:        case (MDOC_Ohang):
        !           836:                buffmt("margin-left: %dem; clear: both;", o);
        !           837:                break;
        !           838:        default:
        !           839:                buffmt("margin-left: %dem; clear: both;", w + o);
        !           840:                break;
        !           841:        }
        !           842:
        !           843:        if ( ! c && MDOC_Column != t) {
        !           844:               if (n->prev && n->prev->body->child)
        !           845:                       bufcat("padding-top: 1em;");
        !           846:               else if (NULL == n->prev)
        !           847:                       bufcat("padding-top: 1em;");
        !           848:        }
        !           849:
        !           850:        tag.key = ATTR_STYLE;
        !           851:        tag.val = buf;
        !           852:        print_otag(h, TAG_DIV, 1, &tag);
        !           853:        return(1);
        !           854: }
        !           855:
        !           856:
        !           857: /* ARGSUSED */
        !           858: static int
        !           859: mdoc_tbl_body_pre(MDOC_ARGS, int t, int w)
        !           860: {
        !           861:
        !           862:        print_otag(h, TAG_DIV, 0, NULL);
        !           863:        return(1);
        !           864: }
        !           865:
        !           866:
        !           867: /* ARGSUSED */
        !           868: static int
        !           869: mdoc_tbl_head_pre(MDOC_ARGS, int t, int w)
        !           870: {
        !           871:        struct htmlpair  tag;
        !           872:        struct ord      *ord;
        !           873:        char             nbuf[BUFSIZ];
        !           874:
        !           875:        switch (t) {
        !           876:        case (MDOC_Item):
        !           877:                /* FALLTHROUGH */
        !           878:        case (MDOC_Ohang):
        !           879:                print_otag(h, TAG_DIV, 0, NULL);
        !           880:                break;
        !           881:        case (MDOC_Column):
        !           882:                buffmt("min-width: %dem;", w);
        !           883:                bufcat("clear: none;");
        !           884:                if (n->next && MDOC_HEAD == n->next->type)
        !           885:                        bufcat("float: left;");
        !           886:                tag.key = ATTR_STYLE;
        !           887:                tag.val = buf;
        !           888:                print_otag(h, TAG_DIV, 1, &tag);
        !           889:                break;
        !           890:        default:
        !           891:                buffmt("margin-left: -%dem;", w);
        !           892:                bufcat("clear: left;");
        !           893:                bufcat("float: left;");
        !           894:                bufcat("padding-right: 1em;");
        !           895:                tag.key = ATTR_STYLE;
        !           896:                tag.val = buf;
        !           897:                print_otag(h, TAG_DIV, 1, &tag);
        !           898:                break;
        !           899:        }
        !           900:
        !           901:        switch (t) {
        !           902:        case (MDOC_Diag):
        !           903:                tag.key = ATTR_CLASS;
        !           904:                tag.val = "diag";
        !           905:                print_otag(h, TAG_SPAN, 1, &tag);
        !           906:                break;
        !           907:        case (MDOC_Enum):
        !           908:                ord = SLIST_FIRST(&h->ords);
        !           909:                assert(ord);
        !           910:                nbuf[BUFSIZ - 1] = 0;
        !           911:                (void)snprintf(nbuf, BUFSIZ - 1, "%d.", ord->pos++);
        !           912:                print_text(h, nbuf);
        !           913:                return(0);
        !           914:        case (MDOC_Dash):
        !           915:                print_text(h, "\\(en");
        !           916:                return(0);
        !           917:        case (MDOC_Hyphen):
        !           918:                print_text(h, "\\-");
        !           919:                return(0);
        !           920:        case (MDOC_Bullet):
        !           921:                print_text(h, "\\(bu");
        !           922:                return(0);
        !           923:        default:
        !           924:                break;
        !           925:        }
        !           926:
        !           927:        return(1);
        !           928: }
        !           929:
        !           930:
        !           931: static int
        !           932: mdoc_tbl_pre(MDOC_ARGS, int type)
        !           933: {
        !           934:        int                      i, w, o, c, wp;
        !           935:        const struct mdoc_node  *bl, *nn;
        !           936:
        !           937:        bl = n->parent->parent;
        !           938:        if (MDOC_BLOCK != n->type)
        !           939:                bl = bl->parent;
        !           940:
        !           941:        /* FIXME: fmt_vspace() equivalent. */
        !           942:
        !           943:        assert(bl->args);
        !           944:
        !           945:        w = o = c = 0;
        !           946:        wp = -1;
        !           947:
        !           948:        for (i = 0; i < (int)bl->args->argc; i++)
        !           949:                if (MDOC_Width == bl->args->argv[i].arg) {
        !           950:                        assert(bl->args->argv[i].sz);
        !           951:                        wp = i;
        !           952:                        w = a2width(bl->args->argv[i].value[0]);
        !           953:                } else if (MDOC_Offset == bl->args->argv[i].arg) {
        !           954:                        assert(bl->args->argv[i].sz);
        !           955:                        o = a2offs(bl->args->argv[i].value[0]);
        !           956:                } else if (MDOC_Compact == bl->args->argv[i].arg)
        !           957:                        c = 1;
        !           958:
        !           959:        if (MDOC_HEAD == n->type && MDOC_Column == type) {
        !           960:                nn = n->parent->child;
        !           961:                assert(nn && MDOC_HEAD == nn->type);
        !           962:                for (i = 0; nn && nn != n; nn = nn->next, i++)
        !           963:                        /* Counter... */ ;
        !           964:                assert(nn);
        !           965:                if (wp >= 0 && i < (int)bl->args[wp].argv->sz)
        !           966:                        w = a2width(bl->args->argv[wp].value[i]);
        !           967:        }
        !           968:
        !           969:        switch (type) {
        !           970:        case (MDOC_Enum):
        !           971:                /* FALLTHROUGH */
        !           972:        case (MDOC_Dash):
        !           973:                /* FALLTHROUGH */
        !           974:        case (MDOC_Hyphen):
        !           975:                /* FALLTHROUGH */
        !           976:        case (MDOC_Bullet):
        !           977:                if (w < 4)
        !           978:                        w = 4;
        !           979:                break;
        !           980:        case (MDOC_Inset):
        !           981:                /* FALLTHROUGH */
        !           982:        case (MDOC_Diag):
        !           983:                w = 1;
        !           984:                break;
        !           985:        default:
        !           986:                if (0 == w)
        !           987:                        w = 10;
        !           988:                break;
        !           989:        }
        !           990:
        !           991:        switch (n->type) {
        !           992:        case (MDOC_BLOCK):
        !           993:                break;
        !           994:        case (MDOC_HEAD):
        !           995:                return(mdoc_tbl_head_pre(m, n, h, type, w));
        !           996:        case (MDOC_BODY):
        !           997:                return(mdoc_tbl_body_pre(m, n, h, type, w));
        !           998:        default:
        !           999:                abort();
        !          1000:                /* NOTREACHED */
        !          1001:        }
        !          1002:
        !          1003:        return(mdoc_tbl_block_pre(m, n, h, type, w, o, c));
        !          1004: }
        !          1005:
        !          1006:
        !          1007: /* ARGSUSED */
        !          1008: static int
        !          1009: mdoc_bl_pre(MDOC_ARGS)
        !          1010: {
        !          1011:        struct ord      *ord;
        !          1012:
        !          1013:        if (MDOC_BLOCK != n->type)
        !          1014:                return(1);
        !          1015:        if (MDOC_Enum != a2list(n))
        !          1016:                return(1);
        !          1017:
        !          1018:        ord = malloc(sizeof(struct ord));
        !          1019:        if (NULL == ord)
        !          1020:                err(EXIT_FAILURE, "malloc");
        !          1021:        ord->cookie = n;
        !          1022:        ord->pos = 1;
        !          1023:        SLIST_INSERT_HEAD(&h->ords, ord, entry);
        !          1024:
        !          1025:        return(1);
        !          1026: }
        !          1027:
        !          1028:
        !          1029: /* ARGSUSED */
        !          1030: static void
        !          1031: mdoc_bl_post(MDOC_ARGS)
        !          1032: {
        !          1033:        struct ord      *ord;
        !          1034:
        !          1035:        if (MDOC_BLOCK != n->type)
        !          1036:                return;
        !          1037:        if (MDOC_Enum != a2list(n))
        !          1038:                return;
        !          1039:
        !          1040:        ord = SLIST_FIRST(&h->ords);
        !          1041:        assert(ord);
        !          1042:        SLIST_REMOVE_HEAD(&h->ords, entry);
        !          1043:        free(ord);
        !          1044: }
        !          1045:
        !          1046:
        !          1047: static int
        !          1048: mdoc_it_pre(MDOC_ARGS)
        !          1049: {
        !          1050:        int              type;
        !          1051:
        !          1052:        if (MDOC_BLOCK == n->type)
        !          1053:                type = a2list(n->parent->parent);
        !          1054:        else
        !          1055:                type = a2list(n->parent->parent->parent);
        !          1056:
        !          1057:        return(mdoc_tbl_pre(m, n, h, type));
        !          1058: }
        !          1059:
        !          1060:
        !          1061: /* ARGSUSED */
        !          1062: static int
        !          1063: mdoc_ex_pre(MDOC_ARGS)
        !          1064: {
        !          1065:        const struct mdoc_node  *nn;
        !          1066:        struct tag              *t;
        !          1067:        struct htmlpair          tag;
        !          1068:
        !          1069:        print_text(h, "The");
        !          1070:
        !          1071:        tag.key = ATTR_CLASS;
        !          1072:        tag.val = "utility";
        !          1073:
        !          1074:        for (nn = n->child; nn; nn = nn->next) {
        !          1075:                t = print_otag(h, TAG_SPAN, 1, &tag);
        !          1076:                print_text(h, nn->string);
        !          1077:                print_tagq(h, t);
        !          1078:
        !          1079:                h->flags |= HTML_NOSPACE;
        !          1080:
        !          1081:                if (nn->next && NULL == nn->next->next)
        !          1082:                        print_text(h, ", and");
        !          1083:                else if (nn->next)
        !          1084:                        print_text(h, ",");
        !          1085:                else
        !          1086:                        h->flags &= ~HTML_NOSPACE;
        !          1087:        }
        !          1088:
        !          1089:        if (n->child->next)
        !          1090:                print_text(h, "utilities exit");
        !          1091:        else
        !          1092:                print_text(h, "utility exits");
        !          1093:
        !          1094:                print_text(h, "0 on success, and >0 if an error occurs.");
        !          1095:        return(0);
        !          1096: }
        !          1097:
        !          1098:
        !          1099: /* ARGSUSED */
        !          1100: static int
        !          1101: mdoc_dq_pre(MDOC_ARGS)
        !          1102: {
        !          1103:
        !          1104:        if (MDOC_BODY != n->type)
        !          1105:                return(1);
        !          1106:        print_text(h, "\\(lq");
        !          1107:        h->flags |= HTML_NOSPACE;
        !          1108:        return(1);
        !          1109: }
        !          1110:
        !          1111:
        !          1112: /* ARGSUSED */
        !          1113: static void
        !          1114: mdoc_dq_post(MDOC_ARGS)
        !          1115: {
        !          1116:
        !          1117:        if (MDOC_BODY != n->type)
        !          1118:                return;
        !          1119:        h->flags |= HTML_NOSPACE;
        !          1120:        print_text(h, "\\(rq");
        !          1121: }
        !          1122:
        !          1123:
        !          1124: /* ARGSUSED */
        !          1125: static int
        !          1126: mdoc_pq_pre(MDOC_ARGS)
        !          1127: {
        !          1128:
        !          1129:        if (MDOC_BODY != n->type)
        !          1130:                return(1);
        !          1131:        print_text(h, "\\&(");
        !          1132:        h->flags |= HTML_NOSPACE;
        !          1133:        return(1);
        !          1134: }
        !          1135:
        !          1136:
        !          1137: /* ARGSUSED */
        !          1138: static void
        !          1139: mdoc_pq_post(MDOC_ARGS)
        !          1140: {
        !          1141:
        !          1142:        if (MDOC_BODY != n->type)
        !          1143:                return;
        !          1144:        print_text(h, ")");
        !          1145: }
        !          1146:
        !          1147:
        !          1148: /* ARGSUSED */
        !          1149: static int
        !          1150: mdoc_sq_pre(MDOC_ARGS)
        !          1151: {
        !          1152:
        !          1153:        if (MDOC_BODY != n->type)
        !          1154:                return(1);
        !          1155:        print_text(h, "\\(oq");
        !          1156:        h->flags |= HTML_NOSPACE;
        !          1157:        return(1);
        !          1158: }
        !          1159:
        !          1160:
        !          1161: /* ARGSUSED */
        !          1162: static void
        !          1163: mdoc_sq_post(MDOC_ARGS)
        !          1164: {
        !          1165:
        !          1166:        if (MDOC_BODY != n->type)
        !          1167:                return;
        !          1168:        h->flags |= HTML_NOSPACE;
        !          1169:        print_text(h, "\\(aq");
        !          1170: }
        !          1171:
        !          1172:
        !          1173: /* ARGSUSED */
        !          1174: static int
        !          1175: mdoc_em_pre(MDOC_ARGS)
        !          1176: {
        !          1177:        struct htmlpair tag;
        !          1178:
        !          1179:        tag.key = ATTR_CLASS;
        !          1180:        tag.val = "emph";
        !          1181:
        !          1182:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1183:        return(1);
        !          1184: }
        !          1185:
        !          1186:
        !          1187: /* ARGSUSED */
        !          1188: static int
        !          1189: mdoc_d1_pre(MDOC_ARGS)
        !          1190: {
        !          1191:        struct htmlpair tag[2];
        !          1192:
        !          1193:        if (MDOC_BLOCK != n->type)
        !          1194:                return(1);
        !          1195:
        !          1196:        buffmt("margin-left: %dem;", INDENT);
        !          1197:
        !          1198:        tag[0].key = ATTR_CLASS;
        !          1199:        tag[0].val = "lit-block";
        !          1200:        tag[1].key = ATTR_STYLE;
        !          1201:        tag[1].val = buf;
        !          1202:
        !          1203:        print_otag(h, TAG_DIV, 2, tag);
        !          1204:        return(1);
        !          1205: }
        !          1206:
        !          1207:
        !          1208: /* ARGSUSED */
        !          1209: static int
        !          1210: mdoc_sx_pre(MDOC_ARGS)
        !          1211: {
        !          1212:        struct htmlpair          tag[2];
        !          1213:        const struct mdoc_node  *nn;
        !          1214:
        !          1215:        bufcat("#");
        !          1216:        for (nn = n->child; nn; nn = nn->next) {
        !          1217:                bufcat(nn->string);
        !          1218:                if (nn->next)
        !          1219:                        bufcat(" ");
        !          1220:        }
        !          1221:
        !          1222:        tag[0].key = ATTR_HREF;
        !          1223:        tag[0].val = buf;
        !          1224:        tag[1].key = ATTR_CLASS;
        !          1225:        tag[1].val = "link-sec";
        !          1226:
        !          1227:        print_otag(h, TAG_A, 2, tag);
        !          1228:        return(1);
        !          1229: }
        !          1230:
        !          1231:
        !          1232: /* ARGSUSED */
        !          1233: static int
        !          1234: mdoc_aq_pre(MDOC_ARGS)
        !          1235: {
        !          1236:
        !          1237:        if (MDOC_BODY != n->type)
        !          1238:                return(1);
        !          1239:        print_text(h, "\\(la");
        !          1240:        h->flags |= HTML_NOSPACE;
        !          1241:        return(1);
        !          1242: }
        !          1243:
        !          1244:
        !          1245: /* ARGSUSED */
        !          1246: static void
        !          1247: mdoc_aq_post(MDOC_ARGS)
        !          1248: {
        !          1249:
        !          1250:        if (MDOC_BODY != n->type)
        !          1251:                return;
        !          1252:        h->flags |= HTML_NOSPACE;
        !          1253:        print_text(h, "\\(ra");
        !          1254: }
        !          1255:
        !          1256:
        !          1257: /* ARGSUSED */
        !          1258: static int
        !          1259: mdoc_bd_pre(MDOC_ARGS)
        !          1260: {
        !          1261:        struct htmlpair          tag[2];
        !          1262:        int                      t, c, o, i;
        !          1263:        const struct mdoc_node  *bl;
        !          1264:
        !          1265:        /* FIXME: fmt_vspace() shit. */
        !          1266:
        !          1267:        if (MDOC_BLOCK == n->type)
        !          1268:                bl = n;
        !          1269:        else if (MDOC_HEAD == n->type)
        !          1270:                return(0);
        !          1271:        else
        !          1272:                bl = n->parent;
        !          1273:
        !          1274:        t = o = c = 0;
        !          1275:
        !          1276:        for (i = 0; i < (int)bl->args->argc; i++)
        !          1277:                switch (bl->args->argv[i].arg) {
        !          1278:                case (MDOC_Offset):
        !          1279:                        assert(bl->args->argv[i].sz);
        !          1280:                        o = a2offs (bl->args->argv[i].value[0]);
        !          1281:                        break;
        !          1282:                case (MDOC_Compact):
        !          1283:                        c = 1;
        !          1284:                        break;
        !          1285:                case (MDOC_Ragged):
        !          1286:                        /* FALLTHROUGH */
        !          1287:                case (MDOC_Filled):
        !          1288:                        /* FALLTHROUGH */
        !          1289:                case (MDOC_Unfilled):
        !          1290:                        /* FALLTHROUGH */
        !          1291:                case (MDOC_Literal):
        !          1292:                        t = bl->args->argv[i].arg;
        !          1293:                        break;
        !          1294:                }
        !          1295:
        !          1296:        if (MDOC_BLOCK == n->type) {
        !          1297:                if (o)
        !          1298:                        buffmt("margin-left: %dem;", o);
        !          1299:                bufcat("margin-top: 1em;");
        !          1300:                tag[0].key = ATTR_STYLE;
        !          1301:                tag[0].val = buf;
        !          1302:                print_otag(h, TAG_DIV, 1, tag);
        !          1303:                return(1);
        !          1304:        }
        !          1305:
        !          1306:        switch (t) {
        !          1307:        case (MDOC_Unfilled):
        !          1308:        case (MDOC_Literal):
        !          1309:                break;
        !          1310:        default:
        !          1311:                return(1);
        !          1312:        }
        !          1313:
        !          1314:        bufcat("white-space: pre;");
        !          1315:        tag[0].key = ATTR_STYLE;
        !          1316:        tag[0].val = buf;
        !          1317:        tag[1].key = ATTR_CLASS;
        !          1318:        tag[1].val = "lit-block";
        !          1319:
        !          1320:        print_otag(h, TAG_DIV, 2, tag);
        !          1321:
        !          1322:        for (n = n->child; n; n = n->next) {
        !          1323:                h->flags |= HTML_NOSPACE;
        !          1324:                print_mdoc_node(m, n, h);
        !          1325:                if (n->next)
        !          1326:                        print_text(h, "\n");
        !          1327:        }
        !          1328:
        !          1329:        return(0);
        !          1330: }
        !          1331:
        !          1332:
        !          1333: /* ARGSUSED */
        !          1334: static int
        !          1335: mdoc_pa_pre(MDOC_ARGS)
        !          1336: {
        !          1337:        struct htmlpair tag;
        !          1338:
        !          1339:        tag.key = ATTR_CLASS;
        !          1340:        tag.val = "file";
        !          1341:
        !          1342:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1343:        return(1);
        !          1344: }
        !          1345:
        !          1346:
        !          1347: /* ARGSUSED */
        !          1348: static int
        !          1349: mdoc_qq_pre(MDOC_ARGS)
        !          1350: {
        !          1351:
        !          1352:        if (MDOC_BODY != n->type)
        !          1353:                return(1);
        !          1354:        print_text(h, "\\*q");
        !          1355:        h->flags |= HTML_NOSPACE;
        !          1356:        return(1);
        !          1357: }
        !          1358:
        !          1359:
        !          1360: /* ARGSUSED */
        !          1361: static void
        !          1362: mdoc_qq_post(MDOC_ARGS)
        !          1363: {
        !          1364:
        !          1365:        if (MDOC_BODY != n->type)
        !          1366:                return;
        !          1367:        h->flags |= HTML_NOSPACE;
        !          1368:        print_text(h, "\\*q");
        !          1369: }
        !          1370:
        !          1371:
        !          1372: /* ARGSUSED */
        !          1373: static int
        !          1374: mdoc_ad_pre(MDOC_ARGS)
        !          1375: {
        !          1376:        struct htmlpair tag;
        !          1377:
        !          1378:        tag.key = ATTR_CLASS;
        !          1379:        tag.val = "addr";
        !          1380:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1381:        return(1);
        !          1382: }
        !          1383:
        !          1384:
        !          1385: /* ARGSUSED */
        !          1386: static int
        !          1387: mdoc_an_pre(MDOC_ARGS)
        !          1388: {
        !          1389:        struct htmlpair tag;
        !          1390:
        !          1391:        tag.key = ATTR_CLASS;
        !          1392:        tag.val = "author";
        !          1393:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1394:        return(1);
        !          1395: }
        !          1396:
        !          1397:
        !          1398: /* ARGSUSED */
        !          1399: static int
        !          1400: mdoc_cd_pre(MDOC_ARGS)
        !          1401: {
        !          1402:        struct htmlpair tag;
        !          1403:
        !          1404:        tag.key = ATTR_CLASS;
        !          1405:        tag.val = "config";
        !          1406:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1407:        return(1);
        !          1408: }
        !          1409:
        !          1410:
        !          1411: /* ARGSUSED */
        !          1412: static int
        !          1413: mdoc_dv_pre(MDOC_ARGS)
        !          1414: {
        !          1415:        struct htmlpair tag;
        !          1416:
        !          1417:        tag.key = ATTR_CLASS;
        !          1418:        tag.val = "define";
        !          1419:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1420:        return(1);
        !          1421: }
        !          1422:
        !          1423:
        !          1424: /* ARGSUSED */
        !          1425: static int
        !          1426: mdoc_ev_pre(MDOC_ARGS)
        !          1427: {
        !          1428:        struct htmlpair tag;
        !          1429:
        !          1430:        tag.key = ATTR_CLASS;
        !          1431:        tag.val = "env";
        !          1432:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1433:        return(1);
        !          1434: }
        !          1435:
        !          1436:
        !          1437: /* ARGSUSED */
        !          1438: static int
        !          1439: mdoc_er_pre(MDOC_ARGS)
        !          1440: {
        !          1441:        struct htmlpair tag;
        !          1442:
        !          1443:        tag.key = ATTR_CLASS;
        !          1444:        tag.val = "errno";
        !          1445:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1446:        return(1);
        !          1447: }
        !          1448:
        !          1449:
        !          1450: /* ARGSUSED */
        !          1451: static int
        !          1452: mdoc_fa_pre(MDOC_ARGS)
        !          1453: {
        !          1454:        const struct mdoc_node  *nn;
        !          1455:        struct htmlpair          tag;
        !          1456:        struct tag              *t;
        !          1457:
        !          1458:        tag.key = ATTR_CLASS;
        !          1459:        tag.val = "farg";
        !          1460:
        !          1461:        if (n->parent->tok != MDOC_Fo) {
        !          1462:                print_otag(h, TAG_SPAN, 1, &tag);
        !          1463:                return(1);
        !          1464:        }
        !          1465:
        !          1466:        for (nn = n->child; nn; nn = nn->next) {
        !          1467:                t = print_otag(h, TAG_SPAN, 1, &tag);
        !          1468:                print_text(h, nn->string);
        !          1469:                print_tagq(h, t);
        !          1470:                if (nn->next)
        !          1471:                        print_text(h, ",");
        !          1472:        }
        !          1473:
        !          1474:        if (n->child && n->next && n->next->tok == MDOC_Fa)
        !          1475:                print_text(h, ",");
        !          1476:
        !          1477:        return(0);
        !          1478: }
        !          1479:
        !          1480:
        !          1481: /* ARGSUSED */
        !          1482: static int
        !          1483: mdoc_fd_pre(MDOC_ARGS)
        !          1484: {
        !          1485:        struct htmlpair tag;
        !          1486:
        !          1487:        if (SEC_SYNOPSIS == n->sec) {
        !          1488:                if (n->next && MDOC_Fd != n->next->tok) {
        !          1489:                        tag.key = ATTR_STYLE;
        !          1490:                        tag.val = "margin-bottom: 1em;";
        !          1491:                        print_otag(h, TAG_DIV, 1, &tag);
        !          1492:                } else
        !          1493:                        print_otag(h, TAG_DIV, 0, NULL);
        !          1494:        }
        !          1495:
        !          1496:        tag.key = ATTR_CLASS;
        !          1497:        tag.val = "macro";
        !          1498:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1499:        return(1);
        !          1500: }
        !          1501:
        !          1502:
        !          1503: /* ARGSUSED */
        !          1504: static int
        !          1505: mdoc_vt_pre(MDOC_ARGS)
        !          1506: {
        !          1507:        struct htmlpair tag;
        !          1508:
        !          1509:        if (SEC_SYNOPSIS == n->sec) {
        !          1510:                if (n->next && MDOC_Vt != n->next->tok) {
        !          1511:                        tag.key = ATTR_STYLE;
        !          1512:                        tag.val = "margin-bottom: 1em;";
        !          1513:                        print_otag(h, TAG_DIV, 1, &tag);
        !          1514:                } else
        !          1515:                        print_otag(h, TAG_DIV, 0, NULL);
        !          1516:        }
        !          1517:
        !          1518:        tag.key = ATTR_CLASS;
        !          1519:        tag.val = "type";
        !          1520:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1521:        return(1);
        !          1522: }
        !          1523:
        !          1524: /* ARGSUSED */
        !          1525: static int
        !          1526: mdoc_ft_pre(MDOC_ARGS)
        !          1527: {
        !          1528:        struct htmlpair tag;
        !          1529:
        !          1530:        if (SEC_SYNOPSIS == n->sec) {
        !          1531:                if (n->prev && MDOC_Fo == n->prev->tok) {
        !          1532:                        tag.key = ATTR_STYLE;
        !          1533:                        tag.val = "magin-bottom: 1em;";
        !          1534:                        print_otag(h, TAG_DIV, 1, &tag);
        !          1535:                } else
        !          1536:                        print_otag(h, TAG_DIV, 0, NULL);
        !          1537:        }
        !          1538:
        !          1539:        tag.key = ATTR_CLASS;
        !          1540:        tag.val = "type";
        !          1541:        print_otag(h, TAG_SPAN, 1, &tag);
        !          1542:        return(1);
        !          1543: }
        !          1544:
        !          1545:
        !          1546: /* ARGSUSED */
        !          1547: static int
        !          1548: mdoc_fn_pre(MDOC_ARGS)
        !          1549: {
        !          1550:        struct tag              *t;
        !          1551:        struct htmlpair          tag;
        !          1552:        const struct mdoc_node  *nn;
        !          1553:
        !          1554:        if (SEC_SYNOPSIS == n->sec) {
        !          1555:                if (n->next) {
        !          1556:                        tag.key = ATTR_STYLE;
        !          1557:                        tag.val = "margin-bottom: 1em";
        !          1558:                        print_otag(h, TAG_DIV, 1, &tag);
        !          1559:                } else
        !          1560:                        print_otag(h, TAG_DIV, 0, NULL);
        !          1561:        }
        !          1562:
        !          1563:        tag.key = ATTR_CLASS;
        !          1564:        tag.val = "type";
        !          1565:
        !          1566:        t = print_otag(h, TAG_SPAN, 1, &tag);
        !          1567:        print_text(h, n->child->string);
        !          1568:        print_tagq(h, t);
        !          1569:
        !          1570:        h->flags |= HTML_NOSPACE;
        !          1571:        print_text(h, "(");
        !          1572:
        !          1573:        for (nn = n->child->next; nn; nn = nn->next) {
        !          1574:                tag.key = ATTR_CLASS;
        !          1575:                tag.val = "farg";
        !          1576:                t = print_otag(h, TAG_SPAN, 1, &tag);
        !          1577:                print_text(h, nn->string);
        !          1578:                print_tagq(h, t);
        !          1579:                if (nn->next)
        !          1580:                        print_text(h, ",");
        !          1581:        }
        !          1582:
        !          1583:        print_text(h, ")");
        !          1584:
        !          1585:        if (SEC_SYNOPSIS == n->sec)
        !          1586:                print_text(h, ";");
        !          1587:
        !          1588:        return(0);
        !          1589: }
        !          1590:
        !          1591:
        !          1592: /* ARGSUSED */
        !          1593: static int
        !          1594: mdoc_sp_pre(MDOC_ARGS)
        !          1595: {
        !          1596:        int             len;
        !          1597:        struct htmlpair tag;
        !          1598:
        !          1599:        switch (n->tok) {
        !          1600:        case (MDOC_sp):
        !          1601:                len = n->child ? atoi(n->child->string) : 1;
        !          1602:                break;
        !          1603:        case (MDOC_br):
        !          1604:                len = 0;
        !          1605:                break;
        !          1606:        default:
        !          1607:                len = 1;
        !          1608:                break;
        !          1609:        }
        !          1610:
        !          1611:        buffmt("height: %dem", len);
        !          1612:        tag.key = ATTR_STYLE;
        !          1613:        tag.val = buf;
        !          1614:        print_otag(h, TAG_DIV, 1, &tag);
        !          1615:        return(1);
        !          1616:
        !          1617: }

CVSweb