]> git.cameronkatri.com Git - mandoc.git/blobdiff - term_ascii.c
disable some tests that expose wcwidth(3) differences among systems
[mandoc.git] / term_ascii.c
index 6ec27be012c5c17309605ada2dbd599a4db4204b..df5ff13901c26b3c8bc738deb3475fccd63b617f 100644 (file)
@@ -1,15 +1,15 @@
-/*     $Id: term_ascii.c,v 1.38 2014/10/28 17:36:19 schwarze Exp $ */
+/*     $Id: term_ascii.c,v 1.54 2016/07/31 09:29:13 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
  *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
@@ -19,6 +19,7 @@
 
 #include <sys/types.h>
 
+#include <assert.h>
 #if HAVE_WCHAR
 #include <locale.h>
 #endif
 #include "mandoc_aux.h"
 #include "out.h"
 #include "term.h"
+#include "manconf.h"
 #include "main.h"
 
-static struct termp     *ascii_init(enum termenc,
-                               const struct mchars *, char *);
-static double            ascii_hspan(const struct termp *,
+static struct termp     *ascii_init(enum termenc, const struct manoutput *);
+static int               ascii_hspan(const struct termp *,
                                const struct roffsu *);
 static size_t            ascii_width(const struct termp *, int);
 static void              ascii_advance(struct termp *, size_t);
@@ -46,7 +47,7 @@ static        void              ascii_begin(struct termp *);
 static void              ascii_end(struct termp *);
 static void              ascii_endline(struct termp *);
 static void              ascii_letter(struct termp *, int);
-static void              ascii_setwidth(struct termp *, int, size_t);
+static void              ascii_setwidth(struct termp *, int, int);
 
 #if HAVE_WCHAR
 static void              locale_advance(struct termp *, size_t);
@@ -57,17 +58,21 @@ static      size_t            locale_width(const struct termp *, int);
 
 
 static struct termp *
-ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
+ascii_init(enum termenc enc, const struct manoutput *outopts)
 {
-       const char      *toks[5];
+#if HAVE_WCHAR
        char            *v;
+#endif
        struct termp    *p;
 
        p = mandoc_calloc(1, sizeof(struct termp));
 
-       p->symtab = mchars;
+       p->line = 1;
        p->tabwidth = 5;
        p->defrmargin = p->lastrmargin = 78;
+       p->fontq = mandoc_reallocarray(NULL,
+            (p->fontsz = 8), sizeof(enum termfont));
+       p->fontq[0] = p->fontl = TERMFONT_NONE;
 
        p->begin = ascii_begin;
        p->end = ascii_end;
@@ -83,9 +88,17 @@ ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
 
 #if HAVE_WCHAR
        if (TERMENC_ASCII != enc) {
+
+               /*
+                * Do not change any of this to LC_ALL.  It might break
+                * the formatting by subtly changing the behaviour of
+                * various functions, for example strftime(3).  As a
+                * worst case, it might even cause buffer overflows.
+                */
+
                v = TERMENC_LOCALE == enc ?
-                   setlocale(LC_ALL, "") :
-                   setlocale(LC_CTYPE, "en_US.UTF-8");
+                   setlocale(LC_CTYPE, "") :
+                   setlocale(LC_CTYPE, UTF8_LOCALE);
                if (NULL != v && MB_CUR_MAX > 1) {
                        p->enc = enc;
                        p->advance = locale_advance;
@@ -96,83 +109,78 @@ ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
        }
 #endif
 
-       toks[0] = "indent";
-       toks[1] = "width";
-       toks[2] = "mdoc";
-       toks[3] = "synopsis";
-       toks[4] = NULL;
-
-       while (outopts && *outopts)
-               switch (getsubopt(&outopts, UNCONST(toks), &v)) {
-               case 0:
-                       p->defindent = (size_t)atoi(v);
-                       break;
-               case 1:
-                       p->defrmargin = (size_t)atoi(v);
-                       break;
-               case 2:
-                       /*
-                        * Temporary, undocumented mode
-                        * to imitate mdoc(7) output style.
-                        */
-                       p->mdocstyle = 1;
-                       p->defindent = 5;
-                       break;
-               case 3:
-                       p->synopsisonly = 1;
-                       break;
-               default:
-                       break;
-               }
-
-       /* Enforce a lower boundary. */
-       if (p->defrmargin < 58)
-               p->defrmargin = 58;
-
-       return(p);
+       if (outopts->mdoc) {
+               p->mdocstyle = 1;
+               p->defindent = 5;
+       }
+       if (outopts->indent)
+               p->defindent = outopts->indent;
+       if (outopts->width)
+               p->defrmargin = outopts->width;
+       if (outopts->synopsisonly)
+               p->synopsisonly = 1;
+
+       return p;
 }
 
 void *
-ascii_alloc(const struct mchars *mchars, char *outopts)
+ascii_alloc(const struct manoutput *outopts)
 {
 
-       return(ascii_init(TERMENC_ASCII, mchars, outopts));
+       return ascii_init(TERMENC_ASCII, outopts);
 }
 
 void *
-utf8_alloc(const struct mchars *mchars, char *outopts)
+utf8_alloc(const struct manoutput *outopts)
 {
 
-       return(ascii_init(TERMENC_UTF8, mchars, outopts));
+       return ascii_init(TERMENC_UTF8, outopts);
 }
 
 void *
-locale_alloc(const struct mchars *mchars, char *outopts)
+locale_alloc(const struct manoutput *outopts)
 {
 
-       return(ascii_init(TERMENC_LOCALE, mchars, outopts));
+       return ascii_init(TERMENC_LOCALE, outopts);
 }
 
 static void
-ascii_setwidth(struct termp *p, int iop, size_t width)
+ascii_setwidth(struct termp *p, int iop, int width)
 {
 
+       width /= 24;
        p->rmargin = p->defrmargin;
-       if (0 < iop)
+       if (iop > 0)
                p->defrmargin += width;
-       else if (0 > iop)
+       else if (iop == 0)
+               p->defrmargin = width ? (size_t)width : p->lastrmargin;
+       else if (p->defrmargin > (size_t)width)
                p->defrmargin -= width;
        else
-               p->defrmargin = width ? width : p->lastrmargin;
+               p->defrmargin = 0;
        p->lastrmargin = p->rmargin;
        p->rmargin = p->maxrmargin = p->defrmargin;
 }
 
+void
+terminal_sepline(void *arg)
+{
+       struct termp    *p;
+       size_t           i;
+
+       p = (struct termp *)arg;
+       (*p->endline)(p);
+       for (i = 0; i < p->defrmargin; i++)
+               (*p->letter)(p, '-');
+       (*p->endline)(p);
+       (*p->endline)(p);
+}
+
 static size_t
 ascii_width(const struct termp *p, int c)
 {
 
-       return(1);
+       return 1;
 }
 
 void
@@ -207,6 +215,7 @@ static void
 ascii_endline(struct termp *p)
 {
 
+       p->line++;
        putchar('\n');
 }
 
@@ -219,52 +228,42 @@ ascii_advance(struct termp *p, size_t len)
                putchar(' ');
 }
 
-static double
+static int
 ascii_hspan(const struct termp *p, const struct roffsu *su)
 {
        double           r;
 
-       /*
-        * Approximate based on character width.
-        * None of these will be actually correct given that an inch on
-        * the screen depends on character size, terminal, etc., etc.
-        */
        switch (su->unit) {
        case SCALE_BU:
-               r = su->scale * 10.0 / 240.0;
+               r = su->scale;
                break;
        case SCALE_CM:
-               r = su->scale * 10.0 / 2.54;
+               r = su->scale * 240.0 / 2.54;
                break;
        case SCALE_FS:
-               r = su->scale * 2730.666;
+               r = su->scale * 65536.0;
                break;
        case SCALE_IN:
-               r = su->scale * 10.0;
+               r = su->scale * 240.0;
                break;
        case SCALE_MM:
-               r = su->scale / 100.0;
+               r = su->scale * 0.24;
                break;
+       case SCALE_VS:
        case SCALE_PC:
-               r = su->scale * 10.0 / 6.0;
+               r = su->scale * 40.0;
                break;
        case SCALE_PT:
-               r = su->scale * 10.0 / 72.0;
-               break;
-       case SCALE_VS:
-               r = su->scale * 2.0 - 1.0;
+               r = su->scale * 10.0 / 3.0;
                break;
        case SCALE_EN:
-               /* FALLTHROUGH */
        case SCALE_EM:
-               r = su->scale;
+               r = su->scale * 24.0;
                break;
        default:
                abort();
-               /* NOTREACHED */
        }
-
-       return(r);
+       return r > 0.0 ? r + 0.01 : r - 0.01;
 }
 
 const char *
@@ -337,11 +336,10 @@ ascii_uc2str(int uc)
        "j",    "DZ",   "Dz",   "dz",   "'\bG", "'\bg", "HV",   "W",
        "`\bN", "`\bn", "A",    "a",    "'\bAE","'\bae","O",    "o"};
 
-       if (uc < 0)
-               return("<?>");
+       assert(uc >= 0);
        if ((size_t)uc < sizeof(tab)/sizeof(tab[0]))
-               return(tab[uc]);
-       return(mchars_uc2str(uc));
+               return tab[uc];
+       return mchars_uc2str(uc);
 }
 
 #if HAVE_WCHAR
@@ -355,7 +353,7 @@ locale_width(const struct termp *p, int c)
        rc = wcwidth(c);
        if (rc < 0)
                rc = 0;
-       return(rc);
+       return rc;
 }
 
 static void
@@ -371,6 +369,7 @@ static void
 locale_endline(struct termp *p)
 {
 
+       p->line++;
        putwchar(L'\n');
 }