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

Annotation of mandoc/html.c, Revision 1.27

1.27    ! kristaps    1: /* $Id: html.c,v 1.26 2008/12/10 17:40:56 kristaps Exp $ */
1.1       kristaps    2: /*
                      3:  * Copyright (c) 2008 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
                      7:  * above copyright notice and this permission notice appear in all
                      8:  * copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
                     11:  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
                     12:  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
                     13:  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
                     14:  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
                     15:  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
                     16:  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
                     17:  * PERFORMANCE OF THIS SOFTWARE.
                     18:  */
1.4       kristaps   19: #include <sys/param.h>
                     20: #include <sys/stat.h>
                     21:
1.1       kristaps   22: #include <assert.h>
1.4       kristaps   23: #include <err.h>
                     24: #include <fcntl.h>
1.1       kristaps   25: #include <stdlib.h>
1.4       kristaps   26: #include <stdio.h>
1.2       kristaps   27: #include <string.h>
1.4       kristaps   28: #include <unistd.h>
1.1       kristaps   29:
1.19      kristaps   30: #include "html.h"
1.2       kristaps   31: #include "ml.h"
                     32:
1.8       kristaps   33: /* TODO: allow head/tail-less invocations (just "div" start). */
                     34:
1.7       kristaps   35: struct htmlnode {
1.8       kristaps   36:        int              tok;
                     37:        enum md_ns       ns;
1.10      kristaps   38:        int              argc[ROFF_MAXLINEARG];
1.7       kristaps   39:        char            *argv[ROFF_MAXLINEARG];
                     40:        struct htmlnode *parent;
                     41: };
                     42:
                     43: struct htmlq {
                     44:        struct htmlnode *last;
                     45: };
                     46:
                     47:
1.19      kristaps   48: static int             html_loadcss(struct md_mbuf *,
                     49:                                const char *);
1.9       kristaps   50: static int             html_alloc(void **);
                     51: static void            html_free(void *);
1.25      kristaps   52: static ssize_t         html_endtag(struct ml_args *,
1.2       kristaps   53:                                enum md_ns, int);
1.25      kristaps   54: static ssize_t         html_beginstring(struct ml_args *,
1.14      kristaps   55:                                const char *, size_t);
1.25      kristaps   56: static ssize_t         html_endstring(struct ml_args *,
1.14      kristaps   57:                                const char *, size_t);
1.25      kristaps   58: static ssize_t         html_begintag(struct ml_args *,
                     59:                                enum md_ns, int,
1.2       kristaps   60:                                const int *, const char **);
1.25      kristaps   61: static int             html_begin(struct ml_args *,
                     62:                                const struct tm *,
                     63:                                const char *, const char *,
                     64:                                enum roffmsec, enum roffvol);
                     65: static int             html_end(struct ml_args *,
1.4       kristaps   66:                                const struct tm *,
                     67:                                const char *, const char *,
1.21      kristaps   68:                                enum roffmsec, enum roffvol);
1.7       kristaps   69: static int             html_printargs(struct md_mbuf *, int,
                     70:                                const char *, const int *,
                     71:                                const char **, size_t *);
1.25      kristaps   72: static ssize_t         html_beginhttp(struct md_mbuf *,
                     73:                                const struct md_args *,
                     74:                                const char *, size_t);
                     75: static ssize_t         html_endhttp(struct md_mbuf *,
                     76:                                const struct md_args *,
                     77:                                const char *, size_t);
1.7       kristaps   78: static int             html_blocktagname(struct md_mbuf *,
1.10      kristaps   79:                                const struct md_args *, int,
                     80:                                struct htmlq *, const int *,
                     81:                                const char **, size_t *);
1.7       kristaps   82: static int             html_blocktagargs(struct md_mbuf *,
1.2       kristaps   83:                                const struct md_args *, int,
1.7       kristaps   84:                                const int *, const char **, size_t *);
1.10      kristaps   85: static int             html_headtagname(struct md_mbuf *,
                     86:                                const struct md_args *, int,
                     87:                                struct htmlq *, const int *,
                     88:                                const char **, size_t *);
                     89: static int             html_headtagargs(struct md_mbuf *,
1.3       kristaps   90:                                const struct md_args *, int,
1.7       kristaps   91:                                const int *, const char **, size_t *);
1.12      kristaps   92: static int             html_bodytagname(struct md_mbuf *,
1.10      kristaps   93:                                const struct md_args *,
                     94:                                int, struct htmlq *, const int *,
                     95:                                const char **, size_t *);
1.12      kristaps   96: static int             html_bodytagargs(struct md_mbuf *,
1.3       kristaps   97:                                const struct md_args *, int,
1.7       kristaps   98:                                const int *, const char **, size_t *);
                     99: static int             html_inlinetagname(struct md_mbuf *,
                    100:                                const struct md_args *, int, size_t *);
                    101: static int             html_inlinetagargs(struct md_mbuf *,
1.2       kristaps  102:                                const struct md_args *, int,
1.7       kristaps  103:                                const int *, const char **, size_t *);
1.10      kristaps  104: static int             html_Bl_bodytagname(struct md_mbuf *,
                    105:                                struct htmlq *, const int *,
                    106:                                const char **, size_t *);
                    107: static int             html_It_blocktagname(struct md_mbuf *,
                    108:                                struct htmlq *, const int *,
                    109:                                const char **, size_t *);
                    110: static int             html_It_headtagname(struct md_mbuf *,
                    111:                                struct htmlq *, const int *,
                    112:                                const char **, size_t *);
                    113: static int             html_It_bodytagname(struct md_mbuf *,
                    114:                                struct htmlq *, const int *,
                    115:                                const char **, size_t *);
1.19      kristaps  116: static int             html_tputln(struct md_mbuf *,
                    117:                                enum ml_scope, int, enum html_tag);
                    118: static int             html_aputln(struct md_mbuf *, enum ml_scope,
                    119:                                int, enum html_tag,
                    120:                                int, const struct html_pair *);
1.10      kristaps  121:
                    122:
                    123: /* ARGSUSED */
                    124: static int
                    125: html_It_headtagname(struct md_mbuf *mbuf, struct htmlq *q,
                    126:                const int *argc, const char **argv, size_t *res)
                    127: {
                    128:        struct htmlnode *n;
1.11      kristaps  129:        int              i;
1.26      kristaps  130:        struct html_pair attr[2];
1.10      kristaps  131:
                    132:        for (n = q->last; n; n = n->parent)
                    133:                if (n->tok == ROFF_Bl)
                    134:                        break;
                    135:
                    136:        assert(n);
1.13      kristaps  137:
                    138:        /* LINTED */
1.11      kristaps  139:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  140:                        i < ROFF_MAXLINEARG; i++) {
                    141:                switch (n->argc[i]) {
1.14      kristaps  142:                case (ROFF_Ohang):
1.19      kristaps  143:                        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10      kristaps  144:                case (ROFF_Tag):
1.26      kristaps  145:                        attr[0].attr = HTML_ATTR_VALIGN;
                    146:                        attr[0].val = "top";
                    147:                        attr[1].attr = HTML_ATTR_NOWRAP;
                    148:                        attr[1].val = "true";
                    149:                        return(html_saput(mbuf, HTML_TAG_TD,
                    150:                                                res, 2, attr));
1.10      kristaps  151:                case (ROFF_Column):
1.26      kristaps  152:                        attr[0].attr = HTML_ATTR_VALIGN;
                    153:                        attr[0].val = "top";
                    154:                        return(html_saput(mbuf, HTML_TAG_TD,
                    155:                                                res, 1, attr));
1.10      kristaps  156:                default:
                    157:                        break;
                    158:                }
                    159:        }
                    160:
1.16      kristaps  161:        return(0);
1.10      kristaps  162: }
                    163:
                    164:
                    165: /* ARGSUSED */
                    166: static int
                    167: html_It_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
                    168:                const int *argc, const char **argv, size_t *res)
                    169: {
                    170:        struct htmlnode *n;
1.11      kristaps  171:        int              i;
1.26      kristaps  172:        struct html_pair attr[1];
1.10      kristaps  173:
                    174:        for (n = q->last; n; n = n->parent)
                    175:                if (n->tok == ROFF_Bl)
                    176:                        break;
                    177:
                    178:        assert(n);
1.13      kristaps  179:
                    180:        /* LINTED */
1.11      kristaps  181:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  182:                        i < ROFF_MAXLINEARG; i++) {
                    183:                switch (n->argc[i]) {
                    184:                case (ROFF_Enum):
                    185:                        /* FALLTHROUGH */
                    186:                case (ROFF_Bullet):
                    187:                        /* FALLTHROUGH */
                    188:                case (ROFF_Dash):
                    189:                        /* FALLTHROUGH */
                    190:                case (ROFF_Hyphen):
                    191:                        /* FALLTHROUGH */
                    192:                case (ROFF_Item):
                    193:                        /* FALLTHROUGH */
                    194:                case (ROFF_Diag):
                    195:                        /* FALLTHROUGH */
                    196:                case (ROFF_Hang):
                    197:                        /* FALLTHROUGH */
                    198:                case (ROFF_Ohang):
                    199:                        /* FALLTHROUGH */
                    200:                case (ROFF_Inset):
1.19      kristaps  201:                        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.10      kristaps  202:                case (ROFF_Tag):
                    203:                        /* FALLTHROUGH */
                    204:                case (ROFF_Column):
1.26      kristaps  205:                        attr[0].attr = HTML_ATTR_VALIGN;
                    206:                        attr[0].val = "top";
                    207:                        return(html_saput(mbuf, HTML_TAG_TD,
                    208:                                                res, 1, attr));
1.10      kristaps  209:                default:
                    210:                        break;
                    211:                }
                    212:        }
                    213:
                    214:        assert(i != ROFF_MAXLINEARG);
1.16      kristaps  215:        return(0);
1.10      kristaps  216: }
                    217:
                    218:
                    219: /* ARGSUSED */
                    220: static int
                    221: html_Bl_bodytagname(struct md_mbuf *mbuf, struct htmlq *q,
                    222:                const int *argc, const char **argv, size_t *res)
                    223: {
1.11      kristaps  224:        int              i;
1.10      kristaps  225:
1.11      kristaps  226:        for (i = 0; ROFF_ARGMAX != argc[i]
1.10      kristaps  227:                        && i < ROFF_MAXLINEARG; i++) {
                    228:                switch (argc[i]) {
                    229:                case (ROFF_Enum):
1.19      kristaps  230:                        return(html_stput(mbuf, HTML_TAG_OL, res));
1.10      kristaps  231:                case (ROFF_Bullet):
                    232:                        /* FALLTHROUGH */
                    233:                case (ROFF_Dash):
                    234:                        /* FALLTHROUGH */
                    235:                case (ROFF_Hyphen):
                    236:                        /* FALLTHROUGH */
                    237:                case (ROFF_Item):
                    238:                        /* FALLTHROUGH */
                    239:                case (ROFF_Diag):
                    240:                        /* FALLTHROUGH */
                    241:                case (ROFF_Hang):
                    242:                        /* FALLTHROUGH */
                    243:                case (ROFF_Ohang):
                    244:                        /* FALLTHROUGH */
                    245:                case (ROFF_Inset):
1.19      kristaps  246:                        return(html_stput(mbuf, HTML_TAG_UL, res));
1.10      kristaps  247:                case (ROFF_Tag):
                    248:                        /* FALLTHROUGH */
                    249:                case (ROFF_Column):
1.19      kristaps  250:                        return(html_stput(mbuf, HTML_TAG_TABLE, res));
1.10      kristaps  251:                default:
                    252:                        break;
                    253:                }
                    254:        }
                    255:
                    256:        assert(i != ROFF_MAXLINEARG);
1.16      kristaps  257:        return(0);
1.10      kristaps  258: }
                    259:
                    260:
                    261: /* ARGSUSED */
                    262: static int
                    263: html_It_blocktagname(struct md_mbuf *mbuf, struct htmlq *q,
                    264:                const int *argc, const char **argv, size_t *res)
                    265: {
                    266:        struct htmlnode *n;
1.11      kristaps  267:        int              i;
1.10      kristaps  268:
                    269:        for (n = q->last; n; n = n->parent)
                    270:                if (n->tok == ROFF_Bl)
                    271:                        break;
                    272:
                    273:        assert(n);
1.13      kristaps  274:
                    275:        /* LINTED */
1.11      kristaps  276:        for (i = 0; ROFF_ARGMAX != n->argc[i] &&
1.10      kristaps  277:                        i < ROFF_MAXLINEARG; i++) {
                    278:                switch (n->argc[i]) {
                    279:                case (ROFF_Enum):
                    280:                        /* FALLTHROUGH */
                    281:                case (ROFF_Bullet):
                    282:                        /* FALLTHROUGH */
                    283:                case (ROFF_Dash):
                    284:                        /* FALLTHROUGH */
                    285:                case (ROFF_Hyphen):
                    286:                        /* FALLTHROUGH */
                    287:                case (ROFF_Item):
                    288:                        /* FALLTHROUGH */
                    289:                case (ROFF_Diag):
                    290:                        /* FALLTHROUGH */
                    291:                case (ROFF_Hang):
                    292:                        /* FALLTHROUGH */
                    293:                case (ROFF_Ohang):
                    294:                        /* FALLTHROUGH */
                    295:                case (ROFF_Inset):
1.19      kristaps  296:                        return(html_stput(mbuf, HTML_TAG_LI, res));
1.10      kristaps  297:                case (ROFF_Tag):
                    298:                        /* FALLTHROUGH */
                    299:                case (ROFF_Column):
1.19      kristaps  300:                        return(html_stput(mbuf, HTML_TAG_TR, res));
1.10      kristaps  301:                default:
                    302:                        break;
                    303:                }
                    304:        }
                    305:
                    306:        assert(i != ROFF_MAXLINEARG);
1.16      kristaps  307:        return(0);
1.10      kristaps  308: }
1.2       kristaps  309:
                    310:
1.4       kristaps  311: static int
                    312: html_loadcss(struct md_mbuf *mbuf, const char *css)
                    313: {
                    314:        size_t           res, bufsz;
                    315:        char            *buf;
                    316:        struct stat      st;
                    317:        int              fd, c;
                    318:        ssize_t          ssz;
                    319:
                    320:        c = 0;
                    321:        res = 0;
                    322:        buf = NULL;
                    323:
                    324:        if (-1 == (fd = open(css, O_RDONLY, 0))) {
                    325:                warn("%s", css);
                    326:                return(0);
                    327:        }
                    328:
                    329:        if (-1 == fstat(fd, &st)) {
                    330:                warn("%s", css);
                    331:                goto out;
                    332:        }
                    333:
                    334:        bufsz = MAX(st.st_blksize, BUFSIZ);
                    335:        if (NULL == (buf = malloc(bufsz))) {
                    336:                warn("malloc");
                    337:                goto out;
                    338:        }
                    339:
                    340:        for (;;) {
                    341:                if (-1 == (ssz = read(fd, buf, bufsz))) {
                    342:                        warn("%s", css);
                    343:                        goto out;
                    344:                } else if (0 == ssz)
                    345:                        break;
                    346:                if ( ! ml_nputs(mbuf, buf, (size_t)ssz, &res))
                    347:                        goto out;
                    348:        }
                    349:
                    350:        c = 1;
                    351:
                    352: out:
                    353:        if (-1 == close(fd)) {
                    354:                warn("%s", css);
                    355:                c = 0;
                    356:        }
                    357:
                    358:        if (buf)
                    359:                free(buf);
                    360:
                    361:        return(c);
                    362: }
                    363:
                    364:
1.18      kristaps  365: static int
1.19      kristaps  366: html_tputln(struct md_mbuf *mbuf, enum ml_scope scope,
                    367:                int i, enum html_tag tag)
1.18      kristaps  368: {
                    369:
1.19      kristaps  370:        if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18      kristaps  371:                return(0);
1.19      kristaps  372:        if ( ! html_tput(mbuf, scope, tag, NULL))
1.18      kristaps  373:                return(0);
1.19      kristaps  374:        return(ml_nputs(mbuf, "\n", 1, NULL));
1.18      kristaps  375: }
                    376:
                    377:
                    378: static int
1.19      kristaps  379: html_aputln(struct md_mbuf *mbuf, enum ml_scope scope, int i,
                    380:                enum html_tag tag, int sz, const struct html_pair *p)
1.18      kristaps  381: {
                    382:
1.19      kristaps  383:        if ( ! ml_putchars(mbuf, ' ', INDENT(i) * INDENT_SZ, NULL))
1.18      kristaps  384:                return(0);
1.19      kristaps  385:        if ( ! html_aput(mbuf, scope, tag, NULL, sz, p))
                    386:                return(0);
                    387:        return(ml_nputs(mbuf, "\n", 1, NULL));
1.18      kristaps  388: }
                    389:
                    390:
1.3       kristaps  391: /* ARGSUSED */
1.2       kristaps  392: static int
1.25      kristaps  393: html_begin(struct ml_args *p, const struct tm *tm, const char *os,
1.21      kristaps  394:                const char *name, enum roffmsec msec, enum roffvol vol)
1.2       kristaps  395: {
1.22      kristaps  396:        enum roffvol     bvol;
1.19      kristaps  397:        struct html_pair attr[4];
1.21      kristaps  398:        char             ts[32], title[64];
1.19      kristaps  399:        int              i;
1.2       kristaps  400:
1.19      kristaps  401:        (void)snprintf(ts, sizeof(ts), "%s(%s)",
                    402:                        name, roff_msecname(msec));
1.4       kristaps  403:
1.21      kristaps  404:        if (vol >= ROFF_ARCH_START) {
1.22      kristaps  405:                switch (msec) {
                    406:                case(ROFF_MSEC_1):
                    407:                        /* FALLTHROUGH */
                    408:                case(ROFF_MSEC_6):
                    409:                        /* FALLTHROUGH */
                    410:                case(ROFF_MSEC_7):
                    411:                        bvol = ROFF_VOL_URM;
                    412:                        break;
                    413:                case(ROFF_MSEC_2):
                    414:                        /* FALLTHROUGH */
                    415:                case(ROFF_MSEC_3):
                    416:                        /* FALLTHROUGH */
                    417:                case(ROFF_MSEC_3p):
                    418:                        /* FALLTHROUGH */
                    419:                case(ROFF_MSEC_4):
                    420:                        /* FALLTHROUGH */
                    421:                case(ROFF_MSEC_5):
                    422:                        bvol = ROFF_VOL_PRM;
                    423:                        break;
                    424:                case(ROFF_MSEC_8):
                    425:                        bvol = ROFF_VOL_PRM;
                    426:                        break;
                    427:                case(ROFF_MSEC_9):
                    428:                        bvol = ROFF_VOL_KM;
                    429:                        break;
                    430:                case(ROFF_MSEC_UNASS):
                    431:                        /* FALLTHROUGH */
                    432:                case(ROFF_MSEC_DRAFT):
                    433:                        /* FALLTHROUGH */
                    434:                case(ROFF_MSEC_PAPER):
                    435:                        bvol = ROFF_VOL_NONE;
                    436:                        break;
                    437:                default:
                    438:                        abort();
                    439:                        /* NOTREACHED */
                    440:                }
1.21      kristaps  441:
1.22      kristaps  442:                (void)snprintf(title, sizeof(title), "%s (%s)",
                    443:                                roff_volname(bvol), roff_volname(vol));
                    444:        } else
                    445:                (void)snprintf(title, sizeof(title), "%s", roff_volname(vol));
1.21      kristaps  446:
                    447:
1.18      kristaps  448:        i = 0;
1.4       kristaps  449:
1.25      kristaps  450:        if ( ! html_typeput(p->mbuf, HTML_TYPE_4_01_STRICT, NULL))
1.17      kristaps  451:                return(0);
1.25      kristaps  452:        if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_HTML))
1.17      kristaps  453:                return(0);
1.25      kristaps  454:        if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_HEAD))
1.17      kristaps  455:                return(0);
1.19      kristaps  456:
                    457:        attr[0].attr = HTML_ATTR_HTTP_EQUIV;
                    458:        attr[0].val = "content-type";
                    459:        attr[1].attr = HTML_ATTR_CONTENT;
                    460:        attr[1].val = "text/html;charset=utf-8";
                    461:
1.25      kristaps  462:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17      kristaps  463:                return(0);
1.19      kristaps  464:
                    465:        attr[0].attr = HTML_ATTR_NAME;
                    466:        attr[0].val = "resource-type";
                    467:        attr[1].attr = HTML_ATTR_CONTENT;
                    468:        attr[1].val = "document";
                    469:
1.25      kristaps  470:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_META, 2, attr))
1.17      kristaps  471:                return(0);
1.19      kristaps  472:
1.25      kristaps  473:        if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_TITLE))
1.17      kristaps  474:                return(0);
1.25      kristaps  475:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.17      kristaps  476:                return(0);
1.25      kristaps  477:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TITLE))
1.2       kristaps  478:                return(0);
1.4       kristaps  479:
1.25      kristaps  480:        if (HTML_CSS_EMBED & p->args->params.html.flags) {
1.19      kristaps  481:                attr[0].attr = HTML_ATTR_TYPE;
                    482:                attr[0].val = "text/css";
                    483:
1.25      kristaps  484:                if ( ! html_aputln(p->mbuf, ML_OPEN, i,
1.19      kristaps  485:                                        HTML_TAG_STYLE, 1, attr))
1.4       kristaps  486:                        return(0);
1.25      kristaps  487:                if ( ! html_commentput(p->mbuf, ML_OPEN, NULL))
1.22      kristaps  488:                        return(0);
1.19      kristaps  489:
1.25      kristaps  490:                if ( ! html_loadcss(p->mbuf, p->args->params.html.css))
1.4       kristaps  491:                        return(0);
1.19      kristaps  492:
1.25      kristaps  493:                if ( ! html_commentput(p->mbuf, ML_CLOSE, NULL))
1.22      kristaps  494:                        return(0);
1.25      kristaps  495:                if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_STYLE))
1.4       kristaps  496:                        return(0);
1.19      kristaps  497:        } else {
                    498:                attr[0].attr = HTML_ATTR_REL;
                    499:                attr[0].val = "stylesheet";
                    500:                attr[1].attr = HTML_ATTR_TYPE;
                    501:                attr[1].val = "text/css";
                    502:                attr[2].attr = HTML_ATTR_HREF;
1.25      kristaps  503:                attr[2].val = p->args->params.html.css;
1.19      kristaps  504:
1.25      kristaps  505:                if ( ! html_aputln(p->mbuf, ML_OPEN, i,
1.19      kristaps  506:                                        HTML_TAG_LINK, 3, attr))
                    507:                        return(0);
                    508:        }
1.4       kristaps  509:
1.25      kristaps  510:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_HEAD))
1.18      kristaps  511:                return(0);
1.25      kristaps  512:        if ( ! html_tputln(p->mbuf, ML_OPEN, i, HTML_TAG_BODY))
1.18      kristaps  513:                return(0);
1.19      kristaps  514:
                    515:        attr[0].attr = HTML_ATTR_CLASS;
                    516:        attr[0].val = "mdoc";
                    517:
1.25      kristaps  518:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_DIV, 1, attr))
1.18      kristaps  519:                return(0);
1.19      kristaps  520:
                    521:        attr[0].attr = HTML_ATTR_WIDTH;
                    522:        attr[0].val = "100%";
1.22      kristaps  523:        attr[1].attr = HTML_ATTR_CLASS;
                    524:        attr[1].val = "header-table";
1.19      kristaps  525:
1.25      kristaps  526:        if ( ! html_aputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 2, attr))
1.18      kristaps  527:                return(0);
1.25      kristaps  528:        if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TR))
1.18      kristaps  529:                return(0);
1.19      kristaps  530:
1.22      kristaps  531:        attr[0].attr = HTML_ATTR_ALIGN;
                    532:        attr[0].val = "left";
                    533:        attr[1].attr = HTML_ATTR_CLASS;
                    534:        attr[1].val = "header-section";
                    535:
1.25      kristaps  536:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.2       kristaps  537:                return(0);
1.25      kristaps  538:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.18      kristaps  539:                return(0);
1.25      kristaps  540:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18      kristaps  541:                return(0);
1.19      kristaps  542:
1.22      kristaps  543:        attr[0].attr = HTML_ATTR_ALIGN;
                    544:        attr[0].val = "center";
                    545:        attr[1].attr = HTML_ATTR_CLASS;
                    546:        attr[1].val = "header-volume";
                    547:
1.25      kristaps  548:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.22      kristaps  549:                return(0);
1.25      kristaps  550:        if ( ! ml_putstring(p->mbuf, title, NULL))
1.18      kristaps  551:                return(0);
1.25      kristaps  552:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.18      kristaps  553:                return(0);
1.19      kristaps  554:
1.20      kristaps  555:        attr[0].attr = HTML_ATTR_ALIGN;
                    556:        attr[0].val = "right";
1.22      kristaps  557:        attr[1].attr = HTML_ATTR_CLASS;
                    558:        attr[1].val = "header-section";
1.20      kristaps  559:
1.25      kristaps  560:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.18      kristaps  561:                return(0);
1.25      kristaps  562:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.17      kristaps  563:                return(0);
1.25      kristaps  564:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.17      kristaps  565:                return(0);
1.19      kristaps  566:
1.25      kristaps  567:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TR))
1.17      kristaps  568:                return(0);
1.25      kristaps  569:        return(html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TABLE));
1.2       kristaps  570: }
                    571:
                    572:
1.3       kristaps  573: /* ARGSUSED */
1.2       kristaps  574: static int
1.25      kristaps  575: html_end(struct ml_args *p, const struct tm *tm, const char *os,
1.22      kristaps  576:                const char *name, enum roffmsec msec, enum roffvol vol)
1.2       kristaps  577: {
1.22      kristaps  578:        struct html_pair attr[4];
                    579:        int              i;
                    580:        char             ts[64];
                    581:
                    582:        if (0 == strftime(ts, sizeof(ts), "%B %d, %Y", tm)) {
                    583:                warn("strftime");
                    584:                return(0);
                    585:        }
                    586:
                    587:        i = 0;
                    588:
                    589:        attr[0].attr = HTML_ATTR_WIDTH;
                    590:        attr[0].val = "100%";
                    591:        attr[1].attr = HTML_ATTR_CLASS;
                    592:        attr[1].val = "header-footer";
                    593:
1.25      kristaps  594:        if ( ! html_aputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TABLE, 2, attr))
1.22      kristaps  595:                return(0);
1.25      kristaps  596:        if ( ! html_tputln(p->mbuf, ML_OPEN, i++, HTML_TAG_TR))
1.22      kristaps  597:                return(0);
                    598:
                    599:        attr[0].attr = HTML_ATTR_ALIGN;
                    600:        attr[0].val = "left";
                    601:        attr[1].attr = HTML_ATTR_CLASS;
                    602:        attr[1].val = "footer-os";
                    603:
1.25      kristaps  604:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.22      kristaps  605:                return(0);
1.25      kristaps  606:        if ( ! ml_putstring(p->mbuf, os, NULL))
1.22      kristaps  607:                return(0);
1.25      kristaps  608:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.22      kristaps  609:                return(0);
                    610:
                    611:        attr[0].attr = HTML_ATTR_ALIGN;
                    612:        attr[0].val = "right";
                    613:        attr[1].attr = HTML_ATTR_CLASS;
                    614:        attr[1].val = "footer-date";
                    615:
1.25      kristaps  616:        if ( ! html_aputln(p->mbuf, ML_OPEN, i, HTML_TAG_TD, 2, attr))
1.22      kristaps  617:                return(0);
1.25      kristaps  618:        if ( ! ml_putstring(p->mbuf, ts, NULL))
1.22      kristaps  619:                return(0);
1.25      kristaps  620:        if ( ! html_tputln(p->mbuf, ML_CLOSE, i, HTML_TAG_TD))
1.22      kristaps  621:                return(0);
                    622:
1.25      kristaps  623:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TR))
1.22      kristaps  624:                return(0);
1.25      kristaps  625:        if ( ! html_tputln(p->mbuf, ML_CLOSE, --i, HTML_TAG_TABLE))
1.22      kristaps  626:                return(0);
1.2       kristaps  627:
1.25      kristaps  628:        if ( ! html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_DIV))
1.18      kristaps  629:                return(0);
1.25      kristaps  630:        if ( ! html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_BODY))
1.18      kristaps  631:                return(0);
1.25      kristaps  632:        return(html_tputln(p->mbuf, ML_CLOSE, 0, HTML_TAG_HTML));
1.2       kristaps  633: }
                    634:
                    635:
1.3       kristaps  636: /* ARGSUSED */
1.7       kristaps  637: static int
1.12      kristaps  638: html_bodytagname(struct md_mbuf *mbuf,
1.10      kristaps  639:                const struct md_args *args, int tok, struct htmlq *q,
                    640:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  641: {
1.3       kristaps  642:
1.10      kristaps  643:        switch (tok) {
                    644:        case (ROFF_Bl):
                    645:                return(html_Bl_bodytagname(mbuf, q, argc, argv, res));
1.12      kristaps  646:        case (ROFF_Fo):
1.19      kristaps  647:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  648:        case (ROFF_It):
                    649:                return(html_It_bodytagname(mbuf, q, argc, argv, res));
1.12      kristaps  650:        case (ROFF_Oo):
1.19      kristaps  651:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  652:        default:
                    653:                break;
                    654:        }
                    655:
1.19      kristaps  656:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  657: }
                    658:
                    659:
                    660: /* ARGSUSED */
1.7       kristaps  661: static int
1.10      kristaps  662: html_headtagname(struct md_mbuf *mbuf,
                    663:                const struct md_args *args, int tok, struct htmlq *q,
                    664:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  665: {
                    666:
1.10      kristaps  667:        switch (tok) {
                    668:        case (ROFF_It):
                    669:                return(html_It_headtagname(mbuf, q, argc, argv, res));
1.12      kristaps  670:        case (ROFF_Fo):
1.19      kristaps  671:                /* FALLTHROUGH */
1.12      kristaps  672:        case (ROFF_Oo):
1.19      kristaps  673:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  674:        case (ROFF_Sh):
1.19      kristaps  675:                return(html_stput(mbuf, HTML_TAG_H1, res));
1.10      kristaps  676:        case (ROFF_Ss):
1.19      kristaps  677:                return(html_stput(mbuf, HTML_TAG_H2, res));
1.10      kristaps  678:        default:
                    679:                break;
                    680:        }
                    681:
1.19      kristaps  682:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  683: }
                    684:
                    685:
                    686: /* ARGSUSED */
1.7       kristaps  687: static int
1.10      kristaps  688: html_blocktagname(struct md_mbuf *mbuf, const struct md_args *args,
                    689:                int tok, struct htmlq *q, const int *argc,
                    690:                const char **argv, size_t *res)
1.3       kristaps  691: {
                    692:
1.10      kristaps  693:        switch (tok) {
1.12      kristaps  694:        case (ROFF_Fo):
1.19      kristaps  695:                /* FALLTHROUGH */
1.12      kristaps  696:        case (ROFF_Oo):
1.19      kristaps  697:                return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.10      kristaps  698:        case (ROFF_It):
                    699:                return(html_It_blocktagname(mbuf, q, argc, argv, res));
                    700:        default:
                    701:                break;
                    702:        }
                    703:
1.19      kristaps  704:        return(html_stput(mbuf, HTML_TAG_DIV, res));
1.3       kristaps  705: }
                    706:
                    707:
1.9       kristaps  708: /* ARGSUSED */
1.7       kristaps  709: static int
                    710: html_printargs(struct md_mbuf *mbuf, int tok, const char *ns,
                    711:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  712: {
                    713:
1.19      kristaps  714:        /* FIXME: use API in ml.h. */
                    715:
1.7       kristaps  716:        if ( ! ml_puts(mbuf, " class=\"", res))
                    717:                return(0);
                    718:        if ( ! ml_puts(mbuf, ns, res))
                    719:                return(0);
                    720:        if ( ! ml_puts(mbuf, "-", res))
1.3       kristaps  721:                return(0);
1.7       kristaps  722:        if ( ! ml_puts(mbuf, toknames[tok], res))
1.3       kristaps  723:                return(0);
1.9       kristaps  724:        return(ml_puts(mbuf, "\"", res));
1.3       kristaps  725: }
                    726:
                    727:
                    728: /* ARGSUSED */
1.7       kristaps  729: static int
1.10      kristaps  730: html_headtagargs(struct md_mbuf *mbuf,
1.7       kristaps  731:                const struct md_args *args, int tok,
                    732:                const int *argc, const char **argv, size_t *res)
1.3       kristaps  733: {
                    734:
1.7       kristaps  735:        return(html_printargs(mbuf, tok, "head", argc, argv, res));
                    736: }
1.3       kristaps  737:
                    738:
1.7       kristaps  739: /* ARGSUSED */
                    740: static int
1.12      kristaps  741: html_bodytagargs(struct md_mbuf *mbuf,
1.7       kristaps  742:                const struct md_args *args, int tok,
                    743:                const int *argc, const char **argv, size_t *res)
                    744: {
1.3       kristaps  745:
1.7       kristaps  746:        return(html_printargs(mbuf, tok, "body", argc, argv, res));
1.2       kristaps  747: }
                    748:
                    749:
                    750: /* ARGSUSED */
1.7       kristaps  751: static int
                    752: html_blocktagargs(struct md_mbuf *mbuf,
                    753:                const struct md_args *args, int tok,
                    754:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  755: {
1.3       kristaps  756:
1.7       kristaps  757:        return(html_printargs(mbuf, tok, "block", argc, argv, res));
1.2       kristaps  758: }
1.1       kristaps  759:
                    760:
                    761: /* ARGSUSED */
1.7       kristaps  762: static int
                    763: html_inlinetagargs(struct md_mbuf *mbuf,
                    764:                const struct md_args *args, int tok,
                    765:                const int *argc, const char **argv, size_t *res)
1.2       kristaps  766: {
                    767:
1.12      kristaps  768:        if ( ! html_printargs(mbuf, tok, "inline", argc, argv, res))
                    769:                return(0);
                    770:
                    771:        switch (tok) {
1.24      kristaps  772:        case (ROFF_Sh):
                    773:
                    774:                /* FIXME: use API in ml.h. */
                    775:
                    776:                assert(*argv);
                    777:                if ( ! ml_nputs(mbuf, " name=\"", 7, res))
                    778:                        return(0);
                    779:                if ( ! ml_putstring(mbuf, *argv++, res))
                    780:                        return(0);
                    781:                while (*argv) {
                    782:                        if ( ! ml_putstring(mbuf, "_", res))
                    783:                                return(0);
                    784:                        if ( ! ml_putstring(mbuf, *argv++, res))
                    785:                                return(0);
                    786:                }
                    787:                if ( ! ml_nputs(mbuf, "\"", 1, res))
                    788:                        return(0);
                    789:                break;
                    790:
1.12      kristaps  791:        case (ROFF_Sx):
1.19      kristaps  792:
                    793:                /* FIXME: use API in ml.h. */
                    794:
1.12      kristaps  795:                assert(*argv);
                    796:                if ( ! ml_nputs(mbuf, " href=\"#", 8, res))
                    797:                        return(0);
1.24      kristaps  798:                if ( ! ml_putstring(mbuf, *argv++, res))
1.12      kristaps  799:                        return(0);
1.24      kristaps  800:                while (*argv) {
                    801:                        if ( ! ml_putstring(mbuf, "_", res))
                    802:                                return(0);
                    803:                        if ( ! ml_putstring(mbuf, *argv++, res))
                    804:                                return(0);
                    805:                }
1.12      kristaps  806:                if ( ! ml_nputs(mbuf, "\"", 1, res))
                    807:                        return(0);
1.24      kristaps  808:
1.13      kristaps  809:                break;
1.12      kristaps  810:        default:
                    811:                break;
                    812:        }
                    813:
                    814:        return(1);
1.2       kristaps  815: }
                    816:
                    817:
1.3       kristaps  818: /* ARGSUSED */
1.7       kristaps  819: static int
1.2       kristaps  820: html_inlinetagname(struct md_mbuf *mbuf,
1.7       kristaps  821:                const struct md_args *args, int tok, size_t *res)
1.2       kristaps  822: {
                    823:
                    824:        switch (tok) {
1.27    ! kristaps  825:        case (ROFF_Dl):
        !           826:                /* FALLTHROUGH */
        !           827:        case (ROFF_D1):
        !           828:                return(html_stput(mbuf, HTML_TAG_DIV, res));
1.24      kristaps  829:        case (ROFF_Sh):
                    830:                return(html_stput(mbuf, HTML_TAG_A, res));
1.4       kristaps  831:        case (ROFF_Pp):
1.19      kristaps  832:                return(html_stput(mbuf, HTML_TAG_DIV, res));
1.12      kristaps  833:        case (ROFF_Sx):
1.19      kristaps  834:                return(html_stput(mbuf, HTML_TAG_A, res));
1.2       kristaps  835:        default:
1.9       kristaps  836:                break;
1.2       kristaps  837:        }
1.9       kristaps  838:
1.19      kristaps  839:        return(html_stput(mbuf, HTML_TAG_SPAN, res));
1.2       kristaps  840: }
                    841:
                    842:
                    843: static ssize_t
1.25      kristaps  844: html_begintag(struct ml_args *p, enum md_ns ns,
1.8       kristaps  845:                int tok, const int *argc, const char **argv)
1.2       kristaps  846: {
1.7       kristaps  847:        size_t           res;
1.8       kristaps  848:        struct htmlq    *q;
                    849:        struct htmlnode *node;
1.11      kristaps  850:        int              i;
1.2       kristaps  851:
                    852:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  853:        res = 0;
                    854:
1.25      kristaps  855:        q = (struct htmlq *)p->data;
1.8       kristaps  856:
                    857:        if (NULL == (node = calloc(1, sizeof(struct htmlnode)))) {
                    858:                warn("calloc");
                    859:                return(-1);
                    860:        }
                    861:
                    862:        node->parent = q->last;
                    863:        node->tok = tok;
                    864:        node->ns = ns;
                    865:
1.10      kristaps  866:        if (argc)  {
                    867:                /* TODO: argv. */
                    868:
                    869:                assert(argv);
1.13      kristaps  870:                /* LINTED */
1.11      kristaps  871:                for (i = 0; ROFF_ARGMAX != argc[i]
1.10      kristaps  872:                                && i < ROFF_MAXLINEARG; i++)
                    873:                        node->argc[i] = argc[i];
                    874:                assert(i != ROFF_MAXLINEARG);
1.12      kristaps  875:        }
1.10      kristaps  876:
                    877:
1.8       kristaps  878:        q->last = node;
                    879:
1.3       kristaps  880:        switch (ns) {
                    881:        case (MD_NS_BLOCK):
1.25      kristaps  882:                if ( ! html_blocktagname(p->mbuf, p->args, tok,
1.10      kristaps  883:                                        q, argc, argv, &res))
1.7       kristaps  884:                        return(-1);
1.25      kristaps  885:                if ( ! html_blocktagargs(p->mbuf, p->args, tok,
1.7       kristaps  886:                                        argc, argv, &res))
                    887:                        return(-1);
                    888:                break;
1.3       kristaps  889:        case (MD_NS_BODY):
1.25      kristaps  890:                if ( ! html_bodytagname(p->mbuf, p->args, tok,
1.10      kristaps  891:                                        q, argc, argv, &res))
1.7       kristaps  892:                        return(-1);
1.25      kristaps  893:                if ( ! html_bodytagargs(p->mbuf, p->args, tok,
1.7       kristaps  894:                                        argc, argv, &res))
                    895:                        return(-1);
                    896:                break;
1.3       kristaps  897:        case (MD_NS_HEAD):
1.25      kristaps  898:                if ( ! html_headtagname(p->mbuf, p->args, tok, q,
1.10      kristaps  899:                                        argc, argv, &res))
1.7       kristaps  900:                        return(-1);
1.25      kristaps  901:                if ( ! html_headtagargs(p->mbuf, p->args, tok,
1.7       kristaps  902:                                        argc, argv, &res))
                    903:                        return(-1);
                    904:                break;
1.3       kristaps  905:        default:
1.25      kristaps  906:                if ( ! html_inlinetagname(p->mbuf, p->args, tok, &res))
1.7       kristaps  907:                        return(-1);
1.25      kristaps  908:                if ( ! html_inlinetagargs(p->mbuf, p->args, tok,
1.7       kristaps  909:                                        argc, argv, &res))
                    910:                        return(-1);
1.3       kristaps  911:                break;
1.2       kristaps  912:        }
                    913:
1.7       kristaps  914:        return((ssize_t)res);
1.2       kristaps  915: }
                    916:
                    917:
                    918: static ssize_t
1.25      kristaps  919: html_endtag(struct ml_args *p, enum md_ns ns, int tok)
1.2       kristaps  920: {
1.7       kristaps  921:        size_t           res;
1.8       kristaps  922:        struct htmlq    *q;
                    923:        struct htmlnode *node;
1.2       kristaps  924:
                    925:        assert(ns != MD_NS_DEFAULT);
1.7       kristaps  926:        res = 0;
                    927:
1.25      kristaps  928:        q = (struct htmlq *)p->data;
1.10      kristaps  929:        node = q->last;
1.8       kristaps  930:
1.3       kristaps  931:        switch (ns) {
                    932:        case (MD_NS_BLOCK):
1.25      kristaps  933:                if ( ! html_blocktagname(p->mbuf, p->args, tok,
1.10      kristaps  934:                                        q, node->argc,
                    935:                                        (const char **)node->argv, &res))
1.7       kristaps  936:                        return(-1);
                    937:                break;
1.3       kristaps  938:        case (MD_NS_BODY):
1.25      kristaps  939:                if ( ! html_bodytagname(p->mbuf, p->args, tok,
1.10      kristaps  940:                                        q, node->argc,
                    941:                                        (const char **)node->argv, &res))
1.7       kristaps  942:                        return(-1);
                    943:                break;
1.3       kristaps  944:        case (MD_NS_HEAD):
1.25      kristaps  945:                if ( ! html_headtagname(p->mbuf, p->args, tok,
1.10      kristaps  946:                                        q, node->argc,
                    947:                                        (const char **)node->argv, &res))
1.7       kristaps  948:                        return(-1);
                    949:                break;
1.3       kristaps  950:        default:
1.25      kristaps  951:                if ( ! html_inlinetagname(p->mbuf, p->args, tok, &res))
1.7       kristaps  952:                        return(-1);
1.3       kristaps  953:                break;
                    954:        }
1.2       kristaps  955:
1.8       kristaps  956:        q->last = node->parent;
                    957:
1.9       kristaps  958:        free(node);
1.8       kristaps  959:
1.7       kristaps  960:        return((ssize_t)res);
1.2       kristaps  961: }
                    962:
                    963:
1.9       kristaps  964: static int
                    965: html_alloc(void **p)
                    966: {
                    967:
                    968:        if (NULL == (*p = calloc(1, sizeof(struct htmlq)))) {
                    969:                warn("calloc");
                    970:                return(0);
                    971:        }
                    972:        return(1);
                    973: }
                    974:
                    975:
                    976: static void
                    977: html_free(void *p)
                    978: {
                    979:        struct htmlq    *q;
                    980:        struct htmlnode *n;
                    981:
                    982:        assert(p);
                    983:        q = (struct htmlq *)p;
                    984:
1.13      kristaps  985:        /* LINTED */
1.9       kristaps  986:        while ((n = q->last)) {
                    987:                q->last = n->parent;
                    988:                free(n);
                    989:        }
                    990:
                    991:        free(q);
                    992: }
                    993:
                    994:
1.23      kristaps  995: /* ARGSUSED */
1.14      kristaps  996: static ssize_t
                    997: html_beginhttp(struct md_mbuf *mbuf,
                    998:                const struct md_args *args,
                    999:                const char *buf, size_t sz)
                   1000: {
                   1001:        size_t           res;
1.19      kristaps 1002:        struct html_pair pair;
1.14      kristaps 1003:
                   1004:        res = 0;
1.19      kristaps 1005:        pair.attr = HTML_ATTR_HREF;
                   1006:        pair.val = (char *)buf;
1.14      kristaps 1007:
1.19      kristaps 1008:        if ( ! html_aput(mbuf, ML_OPEN, HTML_TAG_A, &res, 1, &pair))
1.14      kristaps 1009:                return(-1);
                   1010:        return((ssize_t)res);
                   1011: }
                   1012:
                   1013:
1.23      kristaps 1014: /* ARGSUSED */
1.14      kristaps 1015: static ssize_t
                   1016: html_endhttp(struct md_mbuf *mbuf,
                   1017:                const struct md_args *args,
                   1018:                const char *buf, size_t sz)
                   1019: {
                   1020:        size_t           res;
                   1021:
                   1022:        res = 0;
1.19      kristaps 1023:        if ( ! html_tput(mbuf, ML_CLOSE, HTML_TAG_A, &res))
1.14      kristaps 1024:                return(-1);
                   1025:        return((ssize_t)res);
                   1026: }
                   1027:
                   1028:
                   1029: /* ARGSUSED */
                   1030: static ssize_t
1.25      kristaps 1031: html_beginstring(struct ml_args *p, const char *buf, size_t sz)
1.14      kristaps 1032: {
                   1033:
                   1034:        if (0 == strncmp(buf, "http://", 7))
1.25      kristaps 1035:                return(html_beginhttp(p->mbuf, p->args, buf, sz));
1.14      kristaps 1036:
                   1037:        return(0);
                   1038: }
                   1039:
                   1040:
                   1041: /* ARGSUSED */
                   1042: static ssize_t
1.25      kristaps 1043: html_endstring(struct ml_args *p, const char *buf, size_t sz)
1.14      kristaps 1044: {
                   1045:
                   1046:        if (0 == strncmp(buf, "http://", 7))
1.25      kristaps 1047:                return(html_endhttp(p->mbuf, p->args, buf, sz));
1.14      kristaps 1048:
                   1049:        return(0);
                   1050: }
                   1051:
                   1052:
1.1       kristaps 1053: int
                   1054: md_line_html(void *data, char *buf)
                   1055: {
                   1056:
1.2       kristaps 1057:        return(mlg_line((struct md_mlg *)data, buf));
1.1       kristaps 1058: }
                   1059:
                   1060:
                   1061: int
                   1062: md_exit_html(void *data, int flush)
                   1063: {
                   1064:
1.2       kristaps 1065:        return(mlg_exit((struct md_mlg *)data, flush));
1.1       kristaps 1066: }
                   1067:
                   1068:
                   1069: void *
                   1070: md_init_html(const struct md_args *args,
                   1071:                struct md_mbuf *mbuf, const struct md_rbuf *rbuf)
                   1072: {
1.9       kristaps 1073:        struct ml_cbs    cbs;
1.8       kristaps 1074:
1.9       kristaps 1075:        cbs.ml_alloc = html_alloc;
                   1076:        cbs.ml_free = html_free;
                   1077:        cbs.ml_begintag = html_begintag;
                   1078:        cbs.ml_endtag = html_endtag;
                   1079:        cbs.ml_begin = html_begin;
                   1080:        cbs.ml_end = html_end;
1.14      kristaps 1081:        cbs.ml_beginstring = html_beginstring;
                   1082:        cbs.ml_endstring = html_endstring;
1.1       kristaps 1083:
1.9       kristaps 1084:        return(mlg_alloc(args, rbuf, mbuf, &cbs));
1.1       kristaps 1085: }

CVSweb