]> git.cameronkatri.com Git - mandoc.git/blobdiff - term.c
Fixed overstep patch.
[mandoc.git] / term.c
diff --git a/term.c b/term.c
index fa9d8d685f726470ab414e7b66b8f30c1f85c1b8..d4171aa3d7cc210141ec1c595afa9edb9e70d3c3 100644 (file)
--- a/term.c
+++ b/term.c
@@ -1,4 +1,4 @@
-/*     $Id: term.c,v 1.94 2009/07/27 12:02:49 kristaps Exp $ */
+/*     $Id: term.c,v 1.111 2009/10/26 07:18:23 kristaps Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
  *
 #include <stdlib.h>
 #include <string.h>
 
+#include "chars.h"
+#include "out.h"
 #include "term.h"
 #include "man.h"
 #include "mdoc.h"
+#include "main.h"
 
-extern int               man_run(struct termp *, 
-                               const struct man *);
-extern int               mdoc_run(struct termp *, 
-                               const struct mdoc *);
+/* FIXME: accomodate non-breaking, non-collapsing white-space. */
+/* FIXME: accomodate non-breaking, collapsing white-space. */
 
 static struct termp     *term_alloc(enum termenc);
 static void              term_free(struct termp *);
-static void              term_pescape(struct termp *, const char **);
-static void              term_nescape(struct termp *,
+
+static void              do_escaped(struct termp *, const char **);
+static void              do_special(struct termp *,
                                const char *, size_t);
-static void              term_sescape(struct termp *,
+static void              do_reserved(struct termp *,
                                const char *, size_t);
-static void              term_chara(struct termp *, char);
-static void              term_encodea(struct termp *, char);
-static int               term_isopendelim(const char *);
-static int               term_isclosedelim(const char *);
+static void              buffer(struct termp *, char);
+static void              encode(struct termp *, char);
 
 
 void *
@@ -50,32 +50,6 @@ ascii_alloc(void)
 }
 
 
-int
-terminal_man(void *arg, const struct man *man)
-{
-       struct termp    *p;
-
-       p = (struct termp *)arg;
-       if (NULL == p->symtab)
-               p->symtab = term_ascii2htab();
-
-       return(man_run(p, man));
-}
-
-
-int
-terminal_mdoc(void *arg, const struct mdoc *mdoc)
-{
-       struct termp    *p;
-
-       p = (struct termp *)arg;
-       if (NULL == p->symtab)
-               p->symtab = term_ascii2htab();
-
-       return(mdoc_run(p, mdoc));
-}
-
-
 void
 terminal_free(void *arg)
 {
@@ -90,8 +64,8 @@ term_free(struct termp *p)
 
        if (p->buf)
                free(p->buf);
-       if (TERMENC_ASCII == p->enc && p->symtab)
-               term_asciifree(p->symtab);
+       if (p->symtab)
+               chars_free(p->symtab);
 
        free(p);
 }
@@ -103,7 +77,7 @@ term_alloc(enum termenc enc)
        struct termp *p;
 
        if (NULL == (p = malloc(sizeof(struct termp))))
-               err(1, "malloc");
+               return(NULL);
        bzero(p, sizeof(struct termp));
        p->maxrmargin = 78;
        p->enc = enc;
@@ -111,62 +85,6 @@ term_alloc(enum termenc enc)
 }
 
 
-static int
-term_isclosedelim(const char *p)
-{
-
-       if ( ! (*p && 0 == *(p + 1)))
-               return(0);
-
-       switch (*p) {
-       case('.'):
-               /* FALLTHROUGH */
-       case(','):
-               /* FALLTHROUGH */
-       case(';'):
-               /* FALLTHROUGH */
-       case(':'):
-               /* FALLTHROUGH */
-       case('?'):
-               /* FALLTHROUGH */
-       case('!'):
-               /* FALLTHROUGH */
-       case(')'):
-               /* FALLTHROUGH */
-       case(']'):
-               /* FALLTHROUGH */
-       case('}'):
-               return(1);
-       default:
-               break;
-       }
-
-       return(0);
-}
-
-
-static int
-term_isopendelim(const char *p)
-{
-
-       if ( ! (*p && 0 == *(p + 1)))
-               return(0);
-
-       switch (*p) {
-       case('('):
-               /* FALLTHROUGH */
-       case('['):
-               /* FALLTHROUGH */
-       case('{'):
-               return(1);
-       default:
-               break;
-       }
-
-       return(0);
-}
-
-
 /*
  * Flush a line of text.  A "line" is loosely defined as being something
  * that should be followed by a newline, regardless of whether it's
@@ -207,12 +125,6 @@ term_isopendelim(const char *p)
  *  Otherwise, the line will break at the right margin.  Extremely long
  *  lines will cause the system to emit a warning (TODO: hyphenate, if
  *  possible).
- *
- *  FIXME: newline breaks occur (in groff) also occur when a single
- *  space follows a NOBREAK (try `Bl -tag')
- *
- *  FIXME: there's a newline error where a `Bl -diag' will have a
- *  trailing newline if the line is exactly 73 chars long.
  */
 void
 term_flushln(struct termp *p)
@@ -238,7 +150,6 @@ term_flushln(struct termp *p)
 
        bp = TERMP_NOBREAK & p->flags ? mmax : maxvis;
        vis = 0;
-       overstep = 0;
 
        /*
         * If in the standard case (left-justified), then begin with our
@@ -292,6 +203,9 @@ term_flushln(struct termp *p)
                                        putchar(' ');
                                vis = 0;
                        }
+                       /* Remove the overstep width. */
+                       bp += overstep;
+                       overstep = 0;
                } else {
                        for (j = 0; j < (int)vbl; j++)
                                putchar(' ');
@@ -308,7 +222,9 @@ term_flushln(struct termp *p)
                }
                vis += vsz;
        }
+
        p->col = 0;
+       overstep = 0;
 
        if ( ! (TERMP_NOBREAK & p->flags)) {
                putchar('\n');
@@ -387,40 +303,49 @@ term_vspace(struct termp *p)
 }
 
 
-/*
- * Determine the symbol indicated by an escape sequences, that is, one
- * starting with a backslash.  Once done, we pass this value into the
- * output buffer by way of the symbol table.
- */
 static void
-term_nescape(struct termp *p, const char *word, size_t len)
+do_special(struct termp *p, const char *word, size_t len)
 {
        const char      *rhs;
        size_t           sz;
        int              i;
 
-       rhs = term_a2ascii(p->symtab, word, len, &sz);
+       rhs = chars_a2ascii(p->symtab, word, len, &sz);
 
-       if (NULL == rhs)
+       if (NULL == rhs) {
+#if 0
+               fputs("Unknown special character: ", stderr);
+               for (i = 0; i < (int)len; i++)
+                       fputc(word[i], stderr);
+               fputc('\n', stderr);
+#endif
                return;
+       }
        for (i = 0; i < (int)sz; i++) 
-               term_encodea(p, rhs[i]);
+               encode(p, rhs[i]);
 }
 
 
 static void
-term_sescape(struct termp *p, const char *word, size_t len)
+do_reserved(struct termp *p, const char *word, size_t len)
 {
        const char      *rhs;
        size_t           sz;
        int              i;
 
-       rhs = term_a2res(p->symtab, word, len, &sz);
+       rhs = chars_a2res(p->symtab, word, len, &sz);
 
-       if (NULL == rhs)
+       if (NULL == rhs) {
+#if 0
+               fputs("Unknown reserved word: ", stderr);
+               for (i = 0; i < (int)len; i++)
+                       fputc(word[i], stderr);
+               fputc('\n', stderr);
+#endif
                return;
+       }
        for (i = 0; i < (int)sz; i++) 
-               term_encodea(p, rhs[i]);
+               encode(p, rhs[i]);
 }
 
 
@@ -430,12 +355,13 @@ term_sescape(struct termp *p, const char *word, size_t len)
  * the escape sequence (we assert upon badly-formed escape sequences).
  */
 static void
-term_pescape(struct termp *p, const char **word)
+do_escaped(struct termp *p, const char **word)
 {
-       int              j;
+       int              j, type;
        const char      *wp;
 
        wp = *word;
+       type = 1;
 
        if (0 == *(++wp)) {
                *word = wp;
@@ -449,7 +375,7 @@ term_pescape(struct termp *p, const char **word)
                        return;
                }
 
-               term_nescape(p, wp, 2);
+               do_special(p, wp, 2);
                *word = ++wp;
                return;
 
@@ -467,13 +393,14 @@ term_pescape(struct termp *p, const char **word)
                                return;
                        }
 
-                       term_sescape(p, wp, 2);
+                       do_reserved(p, wp, 2);
                        *word = ++wp;
                        return;
                case ('['):
+                       type = 0;
                        break;
                default:
-                       term_sescape(p, wp, 1);
+                       do_reserved(p, wp, 1);
                        *word = wp;
                        return;
                }
@@ -486,15 +413,15 @@ term_pescape(struct termp *p, const char **word)
 
                switch (*wp) {
                case ('B'):
-                       p->flags |= TERMP_BOLD;
+                       p->bold++;
                        break;
                case ('I'):
-                       p->flags |= TERMP_UNDER;
+                       p->under++;
                        break;
                case ('P'):
                        /* FALLTHROUGH */
                case ('R'):
-                       p->flags &= ~TERMP_STYLE;
+                       p->bold = p->under = 0;
                        break;
                default:
                        break;
@@ -504,7 +431,7 @@ term_pescape(struct termp *p, const char **word)
                return;
 
        } else if ('[' != *wp) {
-               term_nescape(p, wp, 1);
+               do_special(p, wp, 1);
                *word = wp;
                return;
        }
@@ -518,7 +445,10 @@ term_pescape(struct termp *p, const char **word)
                return;
        }
 
-       term_nescape(p, wp - j, (size_t)j);
+       if (type)
+               do_special(p, wp - j, (size_t)j);
+       else
+               do_reserved(p, wp - j, (size_t)j);
        *word = wp;
 }
 
@@ -533,29 +463,58 @@ term_word(struct termp *p, const char *word)
 {
        const char       *sv;
 
-       if (term_isclosedelim(word))
-               if ( ! (TERMP_IGNDELIM & p->flags))
-                       p->flags |= TERMP_NOSPACE;
+       sv = word;
+
+       if (word[0] && 0 == word[1])
+               switch (word[0]) {
+               case('.'):
+                       /* FALLTHROUGH */
+               case(','):
+                       /* FALLTHROUGH */
+               case(';'):
+                       /* FALLTHROUGH */
+               case(':'):
+                       /* FALLTHROUGH */
+               case('?'):
+                       /* FALLTHROUGH */
+               case('!'):
+                       /* FALLTHROUGH */
+               case(')'):
+                       /* FALLTHROUGH */
+               case(']'):
+                       /* FALLTHROUGH */
+               case('}'):
+                       if ( ! (TERMP_IGNDELIM & p->flags))
+                               p->flags |= TERMP_NOSPACE;
+                       break;
+               default:
+                       break;
+               }
 
        if ( ! (TERMP_NOSPACE & p->flags))
-               term_chara(p, ' ');
+               buffer(p, ' ');
 
        if ( ! (p->flags & TERMP_NONOSPACE))
                p->flags &= ~TERMP_NOSPACE;
 
-       /* 
-        * If ANSI (word-length styling), then apply our style now,
-        * before the word.
-        */
-
-       for (sv = word; *word; word++)
+       for ( ; *word; word++)
                if ('\\' != *word)
-                       term_encodea(p, *word);
+                       encode(p, *word);
                else
-                       term_pescape(p, &word);
+                       do_escaped(p, &word);
 
-       if (term_isopendelim(sv))
-               p->flags |= TERMP_NOSPACE;
+       if (sv[0] && 0 == sv[1])
+               switch (sv[0]) {
+               case('('):
+                       /* FALLTHROUGH */
+               case('['):
+                       /* FALLTHROUGH */
+               case('{'):
+                       p->flags |= TERMP_NOSPACE;
+                       break;
+               default:
+                       break;
+               }
 }
 
 
@@ -565,7 +524,7 @@ term_word(struct termp *p, const char *word)
  * size.
  */
 static void
-term_chara(struct termp *p, char c)
+buffer(struct termp *p, char c)
 {
        size_t           s;
 
@@ -575,7 +534,7 @@ term_chara(struct termp *p, char c)
                s = p->maxcols * 2;
                p->buf = realloc(p->buf, s);
                if (NULL == p->buf)
-                       err(1, "realloc");
+                       err(1, "realloc"); /* FIXME: shouldn't be here! */
                p->maxcols = s;
        }
        p->buf[(int)(p->col)++] = c;
@@ -583,18 +542,95 @@ term_chara(struct termp *p, char c)
 
 
 static void
-term_encodea(struct termp *p, char c)
+encode(struct termp *p, char c)
 {
        
-       if (' ' != c && TERMP_STYLE & p->flags) {
-               if (TERMP_BOLD & p->flags) {
-                       term_chara(p, c);
-                       term_chara(p, 8);
+       if (' ' != c) {
+               if (p->under) {
+                       buffer(p, '_');
+                       buffer(p, 8);
                }
-               if (TERMP_UNDER & p->flags) {
-                       term_chara(p, '_');
-                       term_chara(p, 8);
+               if (p->bold) {
+                       buffer(p, c);
+                       buffer(p, 8);
                }
        }
-       term_chara(p, c);
+       buffer(p, c);
 }
+
+
+size_t
+term_vspan(const struct roffsu *su)
+{
+       double           r;
+
+       switch (su->unit) {
+       case (SCALE_CM):
+               r = su->scale * 2;
+               break;
+       case (SCALE_IN):
+               r = su->scale * 6;
+               break;
+       case (SCALE_PC):
+               r = su->scale;
+               break;
+       case (SCALE_PT):
+               r = su->scale / 8;
+               break;
+       case (SCALE_MM):
+               r = su->scale / 1000;
+               break;
+       case (SCALE_VS):
+               r = su->scale;
+               break;
+       default:
+               r = su->scale - 1;
+               break;
+       }
+
+       if (r < 0.0)
+               r = 0.0;
+       return(/* LINTED */(size_t)
+                       r);
+}
+
+
+size_t
+term_hspan(const struct roffsu *su)
+{
+       double           r;
+
+       /* XXX: CM, IN, and PT are approximations. */
+
+       switch (su->unit) {
+       case (SCALE_CM):
+               r = 4 * su->scale;
+               break;
+       case (SCALE_IN):
+               /* XXX: this is an approximation. */
+               r = 10 * su->scale;
+               break;
+       case (SCALE_PC):
+               r = (10 * su->scale) / 6;
+               break;
+       case (SCALE_PT):
+               r = (10 * su->scale) / 72;
+               break;
+       case (SCALE_MM):
+               r = su->scale / 1000; /* FIXME: double-check. */
+               break;
+       case (SCALE_VS):
+               r = su->scale * 2 - 1; /* FIXME: double-check. */
+               break;
+       default:
+               r = su->scale;
+               break;
+       }
+
+       if (r < 0.0)
+               r = 0.0;
+       return((size_t)/* LINTED */
+                       r);
+}
+
+