]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdoc_html.c
Removed need for superfluous `os' value in overstep calculation (thanks Ingo Schwarze).
[mandoc.git] / mdoc_html.c
index e2bb3d3c925138fe48aaae647956f4012158fc30..5dbad7c2ee97805c42522b6f93209fe3b312b777 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_html.c,v 1.23 2009/10/07 12:35:24 kristaps Exp $ */
+/*     $Id: mdoc_html.c,v 1.37 2009/10/24 05:52:13 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -29,6 +29,7 @@
 #include "out.h"
 #include "html.h"
 #include "mdoc.h"
+#include "main.h"
 
 #define        INDENT           5
 #define        HALFINDENT       3
@@ -49,16 +50,11 @@ static      void              print_mdoc_nodelist(MDOC_ARGS);
 
 static void              a2width(const char *, struct roffsu *);
 static void              a2offs(const char *, struct roffsu *);
+
 static int               a2list(const struct mdoc_node *);
 
 static void              mdoc_root_post(MDOC_ARGS);
 static int               mdoc_root_pre(MDOC_ARGS);
-static int               mdoc_it_block_pre(MDOC_ARGS, int, 
-                               struct roffsu *, int, 
-                               struct roffsu *);
-static int               mdoc_it_head_pre(MDOC_ARGS, int, 
-                               struct roffsu *);
-static int               mdoc_it_body_pre(MDOC_ARGS, int);
 
 static void              mdoc__x_post(MDOC_ARGS);
 static int               mdoc__x_pre(MDOC_ARGS);
@@ -96,6 +92,11 @@ static       void              mdoc_fo_post(MDOC_ARGS);
 static int               mdoc_fo_pre(MDOC_ARGS);
 static int               mdoc_ic_pre(MDOC_ARGS);
 static int               mdoc_in_pre(MDOC_ARGS);
+static int               mdoc_it_block_pre(MDOC_ARGS, int, int,
+                               struct roffsu *, struct roffsu *);
+static int               mdoc_it_head_pre(MDOC_ARGS, int, 
+                               struct roffsu *);
+static int               mdoc_it_body_pre(MDOC_ARGS, int);
 static int               mdoc_it_pre(MDOC_ARGS);
 static int               mdoc_lb_pre(MDOC_ARGS);
 static int               mdoc_li_pre(MDOC_ARGS);
@@ -253,6 +254,7 @@ static      const struct htmlmdoc mdocs[MDOC_MAX] = {
        {mdoc__x_pre, mdoc__x_post}, /* %Q */ 
        {mdoc_sp_pre, NULL}, /* br */
        {mdoc_sp_pre, NULL}, /* sp */ 
+       {mdoc__x_pre, mdoc__x_post}, /* %U */ 
 };
 
 
@@ -326,8 +328,10 @@ static void
 a2width(const char *p, struct roffsu *su)
 {
 
-       if ( ! a2roffsu(p, su))
-               SCALE_HS_INIT(su, (int)strlen(p));
+       if ( ! a2roffsu(p, su, SCALE_MAX)) {
+               su->unit = SCALE_EM;
+               su->scale = (int)strlen(p);
+       }
 }
 
 
@@ -340,14 +344,18 @@ static void
 a2offs(const char *p, struct roffsu *su)
 {
 
+       /* FIXME: "right"? */
+
        if (0 == strcmp(p, "left"))
                SCALE_HS_INIT(su, 0);
        else if (0 == strcmp(p, "indent"))
                SCALE_HS_INIT(su, INDENT);
        else if (0 == strcmp(p, "indent-two"))
                SCALE_HS_INIT(su, INDENT * 2);
-       else if ( ! a2roffsu(p, su))
-               SCALE_HS_INIT(su, (int)strlen(p));
+       else if ( ! a2roffsu(p, su, SCALE_MAX)) {
+               su->unit = SCALE_EM;
+               su->scale = (int)strlen(p);
+       }
 }
 
 
@@ -449,10 +457,11 @@ print_mdoc_node(MDOC_ARGS)
 static void
 mdoc_root_post(MDOC_ARGS)
 {
-       struct tm        tm;
        struct htmlpair  tag[2];
        struct tag      *t, *tt;
-       char             b[BUFSIZ];
+       char             b[DATESIZ];
+
+       time2a(m->date, b, DATESIZ);
 
        /*
         * XXX: this should use divs, but in Firefox, divs with nested
@@ -460,11 +469,6 @@ mdoc_root_post(MDOC_ARGS)
         * below.  So I use tables, instead.
         */
 
-       (void)localtime_r(&m->date, &tm);
-
-       if (0 == strftime(b, BUFSIZ - 1, "%B %e, %Y", &tm))
-               err(EXIT_FAILURE, "strftime");
-
        PAIR_CLASS_INIT(&tag[0], "footer");
        bufcat_style(h, "width", "100%");
        PAIR_STYLE_INIT(&tag[1], h);
@@ -548,7 +552,7 @@ mdoc_sh_pre(MDOC_ARGS)
 {
        struct htmlpair          tag[2];
        const struct mdoc_node  *nn;
-       char                     link[BUFSIZ];
+       char                     lbuf[BUFSIZ];
        struct roffsu            su;
 
        if (MDOC_BODY == n->type) {
@@ -575,11 +579,11 @@ mdoc_sh_pre(MDOC_ARGS)
                return(1);
        }
 
-       link[0] = 0;
+       lbuf[0] = 0;
        for (nn = n->child; nn; nn = nn->next) {
-               (void)strlcat(link, nn->string, BUFSIZ);
+               (void)strlcat(lbuf, nn->string, BUFSIZ);
                if (nn->next)
-                       (void)strlcat(link, "_", BUFSIZ);
+                       (void)strlcat(lbuf, "_", BUFSIZ);
        }
 
        /* 
@@ -589,7 +593,7 @@ mdoc_sh_pre(MDOC_ARGS)
 
        PAIR_CLASS_INIT(&tag[0], "sec-head");
        tag[1].key = ATTR_ID;
-       tag[1].val = link;
+       tag[1].val = lbuf;
        print_otag(h, TAG_DIV, 2, tag);
        return(1);
 }
@@ -601,7 +605,7 @@ mdoc_ss_pre(MDOC_ARGS)
 {
        struct htmlpair          tag[3];
        const struct mdoc_node  *nn;
-       char                     link[BUFSIZ];
+       char                     lbuf[BUFSIZ];
        struct roffsu            su;
 
        SCALE_VS_INIT(&su, 1);
@@ -628,11 +632,11 @@ mdoc_ss_pre(MDOC_ARGS)
 
        /* TODO: see note in mdoc_sh_pre() about duplicates. */
 
-       link[0] = 0;
+       lbuf[0] = 0;
        for (nn = n->child; nn; nn = nn->next) {
-               (void)strlcat(link, nn->string, BUFSIZ);
+               (void)strlcat(lbuf, nn->string, BUFSIZ);
                if (nn->next)
-                       (void)strlcat(link, "_", BUFSIZ);
+                       (void)strlcat(lbuf, "_", BUFSIZ);
        }
 
        SCALE_HS_INIT(&su, INDENT - HALFINDENT);
@@ -642,7 +646,7 @@ mdoc_ss_pre(MDOC_ARGS)
        PAIR_CLASS_INIT(&tag[0], "ssec-head");
        PAIR_STYLE_INIT(&tag[1], h);
        tag[2].key = ATTR_ID;
-       tag[2].val = link;
+       tag[2].val = lbuf;
        print_otag(h, TAG_DIV, 3, tag);
        return(1);
 }
@@ -673,7 +677,8 @@ mdoc_nd_pre(MDOC_ARGS)
        if (MDOC_BODY != n->type)
                return(1);
 
-       /* XXX - this can contain block elements! */
+       /* XXX: this tag in theory can contain block elements. */
+
        print_text(h, "\\(em");
        PAIR_CLASS_INIT(&tag, "desc-body");
        print_otag(h, TAG_SPAN, 1, &tag);
@@ -690,7 +695,8 @@ mdoc_op_pre(MDOC_ARGS)
        if (MDOC_BODY != n->type)
                return(1);
 
-       /* XXX - this can contain block elements! */
+       /* XXX: this tag in theory can contain block elements. */
+
        print_text(h, "\\(lB");
        h->flags |= HTML_NOSPACE;
        PAIR_CLASS_INIT(&tag, "opt");
@@ -849,8 +855,8 @@ mdoc_bx_pre(MDOC_ARGS)
 
 /* ARGSUSED */
 static int
-mdoc_it_block_pre(MDOC_ARGS, int type, struct roffsu *offs, 
-               int comp, struct roffsu *width)
+mdoc_it_block_pre(MDOC_ARGS, int type, int comp,
+               struct roffsu *offs, struct roffsu *width)
 {
        struct htmlpair          tag;
        const struct mdoc_node  *nn;
@@ -859,12 +865,20 @@ mdoc_it_block_pre(MDOC_ARGS, int type, struct roffsu *offs,
        nn = n->parent->parent;
        assert(nn->args);
 
-       if (MDOC_Column == type)
-               comp = 0;
+       /* XXX: see notes in mdoc_it_pre(). */
+
+       if (MDOC_Column == type) {
+               /* Don't width-pad on the left. */
+               SCALE_HS_INIT(width, 0);
+               /* Also disallow non-compact. */
+               comp = 1;
+       }
        if (MDOC_Diag == type)
+               /* Mandate non-compact with empty prior. */
                if (n->prev && NULL == n->prev->body->child)
                        comp = 1;
 
+       bufcat_style(h, "clear", "both");
        if (offs->scale > 0)
                bufcat_su(h, "margin-left", offs);
        if (width->scale > 0)
@@ -872,6 +886,8 @@ mdoc_it_block_pre(MDOC_ARGS, int type, struct roffsu *offs,
 
        PAIR_STYLE_INIT(&tag, h);
 
+       /* Mandate compact following `Ss' and `Sh' starts. */
+
        for (nn = n; nn && ! comp; nn = nn->parent) {
                if (MDOC_BLOCK != nn->type)
                        continue;
@@ -892,6 +908,7 @@ mdoc_it_block_pre(MDOC_ARGS, int type, struct roffsu *offs,
 }
 
 
+/* ARGSUSED */
 static int
 mdoc_it_body_pre(MDOC_ARGS, int type)
 {
@@ -906,6 +923,10 @@ mdoc_it_body_pre(MDOC_ARGS, int type)
        case (MDOC_Column):
                break;
        default:
+               /* 
+                * XXX: this tricks CSS into aligning the bodies with
+                * the right-padding in the head. 
+                */
                SCALE_HS_INIT(&su, 2);
                bufcat_su(h, "margin-left", &su);
                PAIR_STYLE_INIT(&tag, h);
@@ -917,6 +938,7 @@ mdoc_it_body_pre(MDOC_ARGS, int type)
 }
 
 
+/* ARGSUSED */
 static int
 mdoc_it_head_pre(MDOC_ARGS, int type, struct roffsu *width)
 {
@@ -944,6 +966,8 @@ mdoc_it_head_pre(MDOC_ARGS, int type, struct roffsu *width)
                bufcat_su(h, "margin-left", width);
                if (n->next && n->next->child)
                        bufcat_style(h, "float", "left");
+
+               /* XXX: buffer if we run into body. */
                SCALE_HS_INIT(width, 1);
                bufcat_su(h, "margin-right", width);
                PAIR_STYLE_INIT(&tag, h);
@@ -987,7 +1011,11 @@ mdoc_it_pre(MDOC_ARGS)
        const struct mdoc_node  *bl, *nn;
        struct roffsu            width, offs;
 
-       /* This is the `Bl' block parent. */
+       /* 
+        * XXX: be very careful in changing anything, here.  Lists in
+        * mandoc have many peculiarities; furthermore, they don't
+        * translate well into HTML and require a bit of mangling.
+        */
 
        bl = n->parent->parent;
        if (MDOC_BLOCK != n->type)
@@ -997,6 +1025,8 @@ mdoc_it_pre(MDOC_ARGS)
 
        /* Set default width and offset. */
 
+       SCALE_HS_INIT(&offs, 0);
+
        switch (type) {
        case (MDOC_Enum):
                /* FALLTHROUGH */
@@ -1012,14 +1042,14 @@ mdoc_it_pre(MDOC_ARGS)
                break;
        }
 
-       SCALE_HS_INIT(&offs, 0);
-
        /* Get width, offset, and compact arguments. */
 
        for (wp = -1, comp = i = 0; i < (int)bl->args->argc; i++) 
                switch (bl->args->argv[i].arg) {
+               case (MDOC_Column):
+                       wp = i; /* Save for later. */
+                       break;
                case (MDOC_Width):
-                       wp = i; /* Save offset. */
                        a2width(bl->args->argv[i].value[0], &width);
                        break;
                case (MDOC_Offset):
@@ -1035,6 +1065,8 @@ mdoc_it_pre(MDOC_ARGS)
        /* Override width in some cases. */
 
        switch (type) {
+       case (MDOC_Item):
+               /* FALLTHROUGH */
        case (MDOC_Inset):
                /* FALLTHROUGH */
        case (MDOC_Diag):
@@ -1051,8 +1083,8 @@ mdoc_it_pre(MDOC_ARGS)
        if (MDOC_BODY == n->type)
                return(mdoc_it_body_pre(m, n, h, type));
        if (MDOC_BLOCK == n->type)
-               return(mdoc_it_block_pre(m, n, h, type, 
-                                       &offs, comp, &width));
+               return(mdoc_it_block_pre(m, n, h, type, comp,
+                                       &offs, &width));
 
        /* Override column widths. */
 
@@ -1060,7 +1092,7 @@ mdoc_it_pre(MDOC_ARGS)
                nn = n->parent->child;
                for (i = 0; nn && nn != n; nn = nn->next, i++)
                        /* Counter... */ ;
-               if (wp >= 0 && i < (int)bl->args[wp].argv->sz)
+               if (i < (int)bl->args->argv[wp].sz)
                        a2width(bl->args->argv[wp].value[i], &width);
        }
 
@@ -1239,6 +1271,8 @@ mdoc_d1_pre(MDOC_ARGS)
        if (MDOC_BLOCK != n->type)
                return(1);
 
+       /* FIXME: D1 shouldn't be literal. */
+
        SCALE_VS_INIT(&su, INDENT - 2);
        bufcat_su(h, "margin-left", &su);
        PAIR_CLASS_INIT(&tag[0], "lit");
@@ -1254,20 +1288,20 @@ mdoc_sx_pre(MDOC_ARGS)
 {
        struct htmlpair          tag[2];
        const struct mdoc_node  *nn;
-       char                     link[BUFSIZ];
+       char                     buf[BUFSIZ];
 
        /* FIXME: duplicates? */
 
-       (void)strlcpy(link, "#", BUFSIZ);
+       (void)strlcpy(buf, "#", BUFSIZ);
        for (nn = n->child; nn; nn = nn->next) {
-               (void)strlcat(link, nn->string, BUFSIZ);
+               (void)strlcat(buf, nn->string, BUFSIZ);
                if (nn->next)
-                       (void)strlcat(link, "_", BUFSIZ);
+                       (void)strlcat(buf, "_", BUFSIZ);
        }
 
        PAIR_CLASS_INIT(&tag[0], "link-sec");
        tag[1].key = ATTR_HREF;
-       tag[1].val = link;
+       tag[1].val = buf;
 
        print_otag(h, TAG_A, 2, tag);
        return(1);
@@ -1315,16 +1349,19 @@ mdoc_bd_pre(MDOC_ARGS)
        else
                bl = n->parent;
 
+       SCALE_VS_INIT(&su, 0);
+
        type = comp = 0;
        for (i = 0; i < (int)bl->args->argc; i++) 
                switch (bl->args->argv[i].arg) {
                case (MDOC_Offset):
                        a2offs(bl->args->argv[i].value[0], &su);
-                       bufcat_su(h, "margin-left", &su);
                        break;
                case (MDOC_Compact):
                        comp = 1;
                        break;
+               case (MDOC_Centred):
+                       /* FALLTHROUGH */
                case (MDOC_Ragged):
                        /* FALLTHROUGH */
                case (MDOC_Filled):
@@ -1334,9 +1371,14 @@ mdoc_bd_pre(MDOC_ARGS)
                case (MDOC_Literal):
                        type = bl->args->argv[i].arg;
                        break;
+               default:
+                       break;
                }
 
+       /* FIXME: -centered, etc. formatting. */
+
        if (MDOC_BLOCK == n->type) {
+               bufcat_su(h, "margin-left", &su);
                for (nn = n; nn && ! comp; nn = nn->parent) {
                        if (MDOC_BLOCK != nn->type)
                                continue;
@@ -1423,6 +1465,7 @@ mdoc_cd_pre(MDOC_ARGS)
 {
        struct htmlpair tag;
 
+       print_otag(h, TAG_DIV, 0, NULL);
        PAIR_CLASS_INIT(&tag, "config");
        print_otag(h, TAG_SPAN, 1, &tag);
        return(1);
@@ -1592,7 +1635,8 @@ mdoc_fn_pre(MDOC_ARGS)
        assert(n->child->string);
        sp = n->child->string;
 
-       if ((ep = strchr(sp, ' '))) {
+       ep = strchr(sp, ' ');
+       if (NULL != ep) {
                PAIR_CLASS_INIT(&tag[0], "ftype");
                t = print_otag(h, TAG_SPAN, 1, tag);
        
@@ -1797,6 +1841,8 @@ mdoc_in_pre(MDOC_ARGS)
                        print_otag(h, TAG_DIV, 0, NULL);
        }
 
+       /* FIXME: there's a buffer bug in here somewhere. */
+
        PAIR_CLASS_INIT(&tag[0], "includes");
        print_otag(h, TAG_SPAN, 1, tag);
 
@@ -2103,6 +2149,8 @@ mdoc__x_pre(MDOC_ARGS)
 {
        struct htmlpair tag;
 
+       /* TODO: %U. */
+
        switch (n->tok) {
        case(MDOC__A):
                PAIR_CLASS_INIT(&tag, "ref-auth");