X-Git-Url: https://git.cameronkatri.com/mandoc.git/blobdiff_plain/35c319dedab41299e8ad1ec62697c36315fb88da..ef2d1ed7915b0e62315dcecce1bc447b55254b7c:/term_ascii.c?ds=inline

diff --git a/term_ascii.c b/term_ascii.c
index c4633b3d..368623ca 100644
--- a/term_ascii.c
+++ b/term_ascii.c
@@ -1,7 +1,7 @@
-/*	$Id: term_ascii.c,v 1.51 2015/10/13 22:59:54 schwarze Exp $ */
+/*	$Id: term_ascii.c,v 1.64 2018/11/28 14:23:06 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>
@@ -65,13 +67,14 @@ ascii_init(enum termenc enc, const struct manoutput *outopts)
 #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->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;
@@ -87,12 +90,30 @@ ascii_init(enum termenc enc, const struct manoutput *outopts)
 	p->width = ascii_width;
 
 #if HAVE_WCHAR
-	if (TERMENC_ASCII != enc) {
-		v = TERMENC_LOCALE == enc ?
-		    setlocale(LC_ALL, "") :
-		    setlocale(LC_CTYPE, "en_US.UTF-8");
-		if (NULL != v && MB_CUR_MAX > 1) {
-			p->enc = enc;
+	if (enc != TERMENC_ASCII) {
+
+		/*
+		 * 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 = enc == TERMENC_LOCALE ?
+		    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 = TERMENC_UTF8;
 			p->advance = locale_advance;
 			p->endline = locale_endline;
 			p->letter = locale_letter;
@@ -112,6 +133,8 @@ ascii_init(enum termenc enc, const struct manoutput *outopts)
 	if (outopts->synopsisonly)
 		p->synopsisonly = 1;
 
+	assert(p->defindent < UINT16_MAX);
+	assert(p->defrmargin < UINT16_MAX);
 	return p;
 }
 
@@ -141,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)
@@ -150,30 +173,30 @@ 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 c != ASCII_BREAK;
 }
 
 void
@@ -209,6 +232,8 @@ ascii_endline(struct termp *p)
 {
 
 	p->line++;
+	p->tcol->offset -= p->ti;
+	p->ti = 0;
 	putchar('\n');
 }
 
@@ -217,6 +242,7 @@ ascii_advance(struct termp *p, size_t len)
 {
 	size_t		i;
 
+	assert(len < UINT16_MAX);
 	for (i = 0; i < len; i++)
 		putchar(' ');
 }
@@ -283,18 +309,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",	"-\bL",	"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",
@@ -354,6 +380,7 @@ locale_advance(struct termp *p, size_t len)
 {
 	size_t		i;
 
+	assert(len < UINT16_MAX);
 	for (i = 0; i < len; i++)
 		putwchar(L' ');
 }
@@ -363,6 +390,8 @@ locale_endline(struct termp *p)
 {
 
 	p->line++;
+	p->tcol->offset -= p->ti;
+	p->ti = 0;
 	putwchar(L'\n');
 }