X-Git-Url: https://git.cameronkatri.com/mandoc.git/blobdiff_plain/3e6a72ed7b563e04635c28fcb556c3203eb58f58..9ee4ba1339669e18191c1be3ccbcaa3ce73d5de1:/term_ascii.c?ds=sidebyside

diff --git a/term_ascii.c b/term_ascii.c
index a36a1a69..f47ffd75 100644
--- a/term_ascii.c
+++ b/term_ascii.c
@@ -1,7 +1,7 @@
-/*	$Id: term_ascii.c,v 1.48 2015/09/26 00:54:04 schwarze Exp $ */
+/*	$Id: term_ascii.c,v 1.61 2018/05/20 21:37:34 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015, 2017, 2018 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
@@ -21,11 +21,13 @@
 
 #include <assert.h>
 #if HAVE_WCHAR
+#include <langinfo.h>
 #include <locale.h>
 #endif
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #if HAVE_WCHAR
 #include <wchar.h>
@@ -38,8 +40,7 @@
 #include "manconf.h"
 #include "main.h"
 
-static	struct termp	 *ascii_init(enum termenc, const struct mchars *,
-				const struct manoutput *);
+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);
@@ -59,22 +60,21 @@ static	size_t		  locale_width(const struct termp *, int);
 
 
 static struct termp *
-ascii_init(enum termenc enc, const struct mchars *mchars,
-	const struct manoutput *outopts)
+ascii_init(enum termenc enc, const struct manoutput *outopts)
 {
 #if HAVE_WCHAR
 	char		*v;
 #endif
 	struct termp	*p;
 
-	p = mandoc_calloc(1, sizeof(struct termp));
+	p = mandoc_calloc(1, sizeof(*p));
+	p->tcol = p->tcols = mandoc_calloc(1, sizeof(*p->tcol));
+	p->maxtcol = 1;
 
-	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->fontsz = 8), sizeof(*p->fontq));
 	p->fontq[0] = p->fontl = TERMFONT_NONE;
 
 	p->begin = ascii_begin;
@@ -91,10 +91,28 @@ ascii_init(enum termenc enc, const struct mchars *mchars,
 
 #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");
-		if (NULL != v && MB_CUR_MAX > 1) {
+		    setlocale(LC_CTYPE, "") :
+		    setlocale(LC_CTYPE, UTF8_LOCALE);
+
+		/*
+		 * We only support UTF-8,
+		 * so revert to ASCII for anything else.
+		 */
+
+		if (v != NULL &&
+		    strcmp(nl_langinfo(CODESET), "UTF-8") != 0)
+			v = setlocale(LC_CTYPE, "C");
+
+		if (v != NULL && MB_CUR_MAX > 1) {
 			p->enc = enc;
 			p->advance = locale_advance;
 			p->endline = locale_endline;
@@ -115,28 +133,30 @@ ascii_init(enum termenc enc, const struct mchars *mchars,
 	if (outopts->synopsisonly)
 		p->synopsisonly = 1;
 
-	return(p);
+	assert(p->defindent < UINT16_MAX);
+	assert(p->defrmargin < UINT16_MAX);
+	return p;
 }
 
 void *
-ascii_alloc(const struct mchars *mchars, const struct manoutput *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, const struct manoutput *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, const struct manoutput *outopts)
+locale_alloc(const struct manoutput *outopts)
 {
 
-	return(ascii_init(TERMENC_LOCALE, mchars, outopts));
+	return ascii_init(TERMENC_LOCALE, outopts);
 }
 
 static void
@@ -144,7 +164,7 @@ ascii_setwidth(struct termp *p, int iop, int width)
 {
 
 	width /= 24;
-	p->rmargin = p->defrmargin;
+	p->tcol->rmargin = p->defrmargin;
 	if (iop > 0)
 		p->defrmargin += width;
 	else if (iop == 0)
@@ -153,30 +173,31 @@ ascii_setwidth(struct termp *p, int iop, int width)
 		p->defrmargin -= width;
 	else
 		p->defrmargin = 0;
-	p->lastrmargin = p->rmargin;
-	p->rmargin = p->maxrmargin = p->defrmargin;
+	if (p->defrmargin > 1000)
+		p->defrmargin = 1000;
+	p->lastrmargin = p->tcol->rmargin;
+	p->tcol->rmargin = p->maxrmargin = p->defrmargin;
 }
 
 void
-ascii_sepline(void *arg)
+terminal_sepline(void *arg)
 {
 	struct termp	*p;
 	size_t		 i;
 
 	p = (struct termp *)arg;
-	p->line += 3;
-	putchar('\n');
+	(*p->endline)(p);
 	for (i = 0; i < p->defrmargin; i++)
-		putchar('-');
-	putchar('\n');
-	putchar('\n');
+		(*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
@@ -212,6 +233,8 @@ ascii_endline(struct termp *p)
 {
 
 	p->line++;
+	p->tcol->offset -= p->ti;
+	p->ti = 0;
 	putchar('\n');
 }
 
@@ -220,6 +243,7 @@ ascii_advance(struct termp *p, size_t len)
 {
 	size_t		i;
 
+	assert(len < UINT16_MAX);
 	for (i = 0; i < len; i++)
 		putchar(' ');
 }
@@ -246,7 +270,6 @@ ascii_hspan(const struct termp *p, const struct roffsu *su)
 		r = su->scale * 0.24;
 		break;
 	case SCALE_VS:
-		/* FALLTHROUGH */
 	case SCALE_PC:
 		r = su->scale * 40.0;
 		break;
@@ -254,14 +277,13 @@ ascii_hspan(const struct termp *p, const struct roffsu *su)
 		r = su->scale * 10.0 / 3.0;
 		break;
 	case SCALE_EN:
-		/* FALLTHROUGH */
 	case SCALE_EM:
 		r = su->scale * 24.0;
 		break;
 	default:
 		abort();
 	}
-	return(r > 0.0 ? r + 0.01 : r - 0.01);
+	return r > 0.0 ? r + 0.01 : r - 0.01;
 }
 
 const char *
@@ -288,18 +310,18 @@ ascii_uc2str(int uc)
 	"<80>",	"<81>",	"<82>",	"<83>",	"<84>",	"<85>",	"<86>",	"<87>",
 	"<88>",	"<89>",	"<8A>",	"<8B>",	"<8C>",	"<8D>",	"<8E>",	"<8F>",
 	"<90>",	"<91>",	"<92>",	"<93>",	"<94>",	"<95>",	"<96>",	"<97>",
-	"<99>",	"<99>",	"<9A>",	"<9B>",	"<9C>",	"<9D>",	"<9E>",	"<9F>",
-	nbrsp,	"!",	"/\bc",	"GBP",	"o\bx",	"=\bY",	"|",	"<sec>",
+	"<98>",	"<99>",	"<9A>",	"<9B>",	"<9C>",	"<9D>",	"<9E>",	"<9F>",
+	nbrsp,	"!",	"/\bc",	"GBP",	"o\bx",	"=\bY",	"|",	"<section>",
 	"\"",	"(C)",	"_\ba",	"<<",	"~",	"",	"(R)",	"-",
-	"<deg>","+-",	"2",	"3",	"'",	",\bu",	"<par>",".",
-	",",	"1",	"_\bo",	">>",	"1/4",	"1/2",	"3/4",	"?",
+	"<degree>","+-","^2",	"^3",	"'","<micro>","<paragraph>",".",
+	",",	"^1",	"_\bo",	">>",	"1/4",	"1/2",	"3/4",	"?",
 	"`\bA",	"'\bA",	"^\bA",	"~\bA",	"\"\bA","o\bA",	"AE",	",\bC",
 	"`\bE",	"'\bE",	"^\bE",	"\"\bE","`\bI",	"'\bI",	"^\bI",	"\"\bI",
-	"-\bD",	"~\bN",	"`\bO",	"'\bO",	"^\bO",	"~\bO",	"\"\bO","x",
+	"Dh",	"~\bN",	"`\bO",	"'\bO",	"^\bO",	"~\bO",	"\"\bO","x",
 	"/\bO",	"`\bU",	"'\bU",	"^\bU",	"\"\bU","'\bY",	"Th",	"ss",
 	"`\ba",	"'\ba",	"^\ba",	"~\ba",	"\"\ba","o\ba",	"ae",	",\bc",
 	"`\be",	"'\be",	"^\be",	"\"\be","`\bi",	"'\bi",	"^\bi",	"\"\bi",
-	"d",	"~\bn",	"`\bo",	"'\bo",	"^\bo",	"~\bo",	"\"\bo","-:-",
+	"dh",	"~\bn",	"`\bo",	"'\bo",	"^\bo",	"~\bo",	"\"\bo","/",
 	"/\bo",	"`\bu",	"'\bu",	"^\bu",	"\"\bu","'\by",	"th",	"\"\by",
 	"A",	"a",	"A",	"a",	"A",	"a",	"'\bC",	"'\bc",
 	"^\bC",	"^\bc",	"C",	"c",	"C",	"c",	"D",	"d",
@@ -336,8 +358,8 @@ ascii_uc2str(int uc)
 
 	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
@@ -351,7 +373,7 @@ locale_width(const struct termp *p, int c)
 	rc = wcwidth(c);
 	if (rc < 0)
 		rc = 0;
-	return(rc);
+	return rc;
 }
 
 static void
@@ -359,6 +381,7 @@ locale_advance(struct termp *p, size_t len)
 {
 	size_t		i;
 
+	assert(len < UINT16_MAX);
 	for (i = 0; i < len; i++)
 		putwchar(L' ');
 }
@@ -368,6 +391,8 @@ locale_endline(struct termp *p)
 {
 
 	p->line++;
+	p->tcol->offset -= p->ti;
+	p->ti = 0;
 	putwchar(L'\n');
 }