]> git.cameronkatri.com Git - mandoc.git/blobdiff - mdoc_action.c
`Cd' in -Thtml -mdoc correctly breaks lines.
[mandoc.git] / mdoc_action.c
index d162373c29ce2d8a16978ad7bc7b10c443db4594..844e1bf646ed9a08d235fd18f2d2e36afbafee1d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_action.c,v 1.37 2009/09/16 20:49:06 kristaps Exp $ */
+/*     $Id: mdoc_action.c,v 1.41 2009/09/25 13:03:25 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
@@ -32,6 +32,15 @@ struct       actions {
        int     (*post)(POST_ARGS);
 };
 
+static int       concat(struct mdoc *, 
+                       const struct mdoc_node *, 
+                       char *, size_t);
+static inline int order_rs(int);
+
+#ifdef __linux__
+extern size_t    strlcat(char *, const char *, size_t);
+#endif
+
 static int       post_ar(POST_ARGS);
 static int       post_at(POST_ARGS);
 static int       post_bl(POST_ARGS);
@@ -45,13 +54,16 @@ static      int       post_lb(POST_ARGS);
 static int       post_nm(POST_ARGS);
 static int       post_os(POST_ARGS);
 static int       post_prol(POST_ARGS);
+static int       post_rs(POST_ARGS);
 static int       post_sh(POST_ARGS);
 static int       post_st(POST_ARGS);
 static int       post_std(POST_ARGS);
 static int       post_tilde(POST_ARGS);
 
 static int       pre_bd(PRE_ARGS);
+static int       pre_bl(PRE_ARGS);
 static int       pre_dl(PRE_ARGS);
+static int       pre_offset(PRE_ARGS);
 
 static const struct actions mdoc_actions[MDOC_MAX] = {
        { NULL, NULL }, /* Ap */
@@ -65,7 +77,7 @@ static        const struct actions mdoc_actions[MDOC_MAX] = {
        { pre_dl, post_display }, /* Dl */
        { pre_bd, post_display }, /* Bd */ 
        { NULL, NULL }, /* Ed */
-       { NULL, post_bl }, /* Bl */ 
+       { pre_bl, post_bl }, /* Bl */ 
        { NULL, NULL }, /* El */
        { NULL, NULL }, /* It */
        { NULL, NULL }, /* Ad */ 
@@ -139,7 +151,7 @@ static      const struct actions mdoc_actions[MDOC_MAX] = {
        { NULL, NULL }, /* Qo */
        { NULL, NULL }, /* Qq */
        { NULL, NULL }, /* Re */
-       { NULL, NULL }, /* Rs */
+       { NULL, post_rs }, /* Rs */
        { NULL, NULL }, /* Sc */
        { NULL, NULL }, /* So */
        { NULL, NULL }, /* Sq */
@@ -176,12 +188,23 @@ static    const struct actions mdoc_actions[MDOC_MAX] = {
        { NULL, NULL }, /* sp */
 };
 
-static int       concat(struct mdoc *, const struct mdoc_node *, 
-                       char *, size_t);
-
-#ifdef __linux__
-extern size_t    strlcat(char *, const char *, size_t);
-#endif
+#define        RSORD_MAX 13
+
+static const int rsord[RSORD_MAX] = {
+       MDOC__A,
+       MDOC__T,
+       MDOC__B,
+       MDOC__I,
+       MDOC__J,
+       MDOC__R,
+       MDOC__N,
+       MDOC__V,
+       MDOC__P,
+       MDOC__Q,
+       MDOC__D,
+       MDOC__O,
+       MDOC__C
+};
 
 
 int
@@ -824,29 +847,64 @@ pre_dl(PRE_ARGS)
 }
 
 
+static int
+pre_offset(PRE_ARGS)
+{
+       int              i;
+
+       /* 
+        * Make sure that an empty offset produces an 8n length space as
+        * stipulated by mdoc.samples. 
+        */
+
+       assert(n->args);
+       for (i = 0; i < (int)n->args->argc; i++) {
+               if (MDOC_Offset != n->args->argv[i].arg) 
+                       continue;
+               if (n->args->argv[i].sz)
+                       break;
+               assert(1 == n->args->refcnt);
+               /* If no value set, length of <string>. */
+               n->args->argv[i].value = 
+               calloc(1, sizeof(char *));
+               if (NULL == n->args->argv[i].value)
+                       return(mdoc_nerr(m, n, EMALLOC));
+               n->args->argv[i].sz++;
+               n->args->argv[i].value[0] = strdup("8n");
+               if (NULL == n->args->argv[i].value[0])
+                       return(mdoc_nerr(m, n, EMALLOC));
+               break;
+       }
+
+       return(1);
+}
+
+
+static int
+pre_bl(PRE_ARGS)
+{
+
+       return(MDOC_BLOCK == n->type ? pre_offset(m, n) : 1);
+}
+
+
 static int
 pre_bd(PRE_ARGS)
 {
        int              i;
 
+       if (MDOC_BLOCK == n->type)
+               return(pre_offset(m, n));
        if (MDOC_BODY != n->type)
                return(1);
 
        /* Enter literal context if `Bd -literal' or `-unfilled'. */
 
-       /* 
-        * TODO: `-offset' without an argument should be the width of
-        * the literal "<string>".
-        */
-
        for (n = n->parent, i = 0; i < (int)n->args->argc; i++)
                if (MDOC_Literal == n->args->argv[i].arg)
-                       break;
+                       m->flags |= MDOC_LITERAL;
                else if (MDOC_Unfilled == n->args->argv[i].arg)
-                       break;
-
-       if (i < (int)n->args->argc)
-               m->flags |= MDOC_LITERAL;
+                       m->flags |= MDOC_LITERAL;
 
        return(1);
 }
@@ -862,3 +920,65 @@ post_display(POST_ARGS)
 }
 
 
+static inline int
+order_rs(int t)
+{
+       int             i;
+
+       for (i = 0; i < RSORD_MAX; i++)
+               if (rsord[i] == t)
+                       return(i);
+
+       abort();
+       /* NOTREACHED */
+}
+
+
+/* ARGSUSED */
+static int
+post_rs(POST_ARGS)
+{
+       struct mdoc_node        *nn, *next, *prev;
+       int                      o;
+
+       if (MDOC_BLOCK != n->type)
+               return(1);
+
+       assert(n->body->child);
+       for (next = NULL, nn = n->body->child->next; nn; nn = next) {
+               o = order_rs(nn->tok);
+
+               /* Remove `nn' from the chain. */
+               next = nn->next;
+               if (next)
+                       next->prev = nn->prev;
+
+               prev = nn->prev;
+               if (prev)
+                       prev->next = nn->next;
+
+               nn->prev = nn->next = NULL;
+
+               /* 
+                * Scan back until we reach a node that's ordered before
+                * us, then set ourselves as being the next. 
+                */
+               for ( ; prev; prev = prev->prev)
+                       if (order_rs(prev->tok) <= o)
+                               break;
+
+               nn->prev = prev;
+               if (prev) {
+                       if (prev->next)
+                               prev->next->prev = nn;
+                       nn->next = prev->next;
+                       prev->next = nn;
+                       continue;
+               } 
+
+               n->body->child->prev = nn;
+               nn->next = n->body->child;
+               n->body->child = nn;
+       }
+       return(1);
+}