=================================================================== RCS file: /cvs/mandoc/term_ascii.c,v retrieving revision 1.59 retrieving revision 1.69 diff -u -p -r1.59 -r1.69 --- mandoc/term_ascii.c 2017/08/23 10:50:15 1.59 +++ mandoc/term_ascii.c 2023/11/13 19:13:01 1.69 @@ -1,7 +1,7 @@ -/* $Id: term_ascii.c,v 1.59 2017/08/23 10:50:15 schwarze Exp $ */ +/* $Id: term_ascii.c,v 1.69 2023/11/13 19:13:01 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons - * Copyright (c) 2014, 2015, 2017 Ingo Schwarze + * Copyright (c) 2014,2015,2017,2018,2020 Ingo Schwarze * * 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 #if HAVE_WCHAR +#include #include #endif #include #include #include +#include #include #if HAVE_WCHAR #include @@ -70,6 +72,7 @@ ascii_init(enum termenc enc, const struct manoutput *o p->maxtcol = 1; p->line = 1; + p->defindent = 5; p->defrmargin = p->lastrmargin = 78; p->fontq = mandoc_reallocarray(NULL, (p->fontsz = 8), sizeof(*p->fontq)); @@ -88,7 +91,7 @@ ascii_init(enum termenc enc, const struct manoutput *o p->width = ascii_width; #if HAVE_WCHAR - if (TERMENC_ASCII != enc) { + if (enc != TERMENC_ASCII) { /* * Do not change any of this to LC_ALL. It might break @@ -97,11 +100,21 @@ ascii_init(enum termenc enc, const struct manoutput *o * worst case, it might even cause buffer overflows. */ - v = TERMENC_LOCALE == enc ? + v = enc == TERMENC_LOCALE ? setlocale(LC_CTYPE, "") : setlocale(LC_CTYPE, UTF8_LOCALE); - if (NULL != v && MB_CUR_MAX > 1) { - p->enc = enc; + + /* + * 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; @@ -110,10 +123,8 @@ ascii_init(enum termenc enc, const struct manoutput *o } #endif - if (outopts->mdoc) { + if (outopts->mdoc) p->mdocstyle = 1; - p->defindent = 5; - } if (outopts->indent) p->defindent = outopts->indent; if (outopts->width) @@ -121,6 +132,8 @@ ascii_init(enum termenc enc, const struct manoutput *o if (outopts->synopsisonly) p->synopsisonly = 1; + assert(p->defindent < UINT16_MAX); + assert(p->defrmargin < UINT16_MAX); return p; } @@ -159,6 +172,8 @@ ascii_setwidth(struct termp *p, int iop, int width) p->defrmargin -= width; else p->defrmargin = 0; + if (p->defrmargin > 1000) + p->defrmargin = 1000; p->lastrmargin = p->tcol->rmargin; p->tcol->rmargin = p->maxrmargin = p->defrmargin; } @@ -180,8 +195,7 @@ terminal_sepline(void *arg) static size_t ascii_width(const struct termp *p, int c) { - - return 1; + return c != ASCII_BREAK && c != ASCII_NBRZW && c != ASCII_TABREF; } void @@ -217,7 +231,10 @@ ascii_endline(struct termp *p) { p->line++; - p->tcol->offset -= p->ti; + if ((int)p->tcol->offset > p->ti) + p->tcol->offset -= p->ti; + else + p->tcol->offset = 0; p->ti = 0; putchar('\n'); } @@ -227,6 +244,14 @@ ascii_advance(struct termp *p, size_t len) { size_t i; + /* + * XXX We used to have "assert(len < UINT16_MAX)" here. + * that is not quite right because the input document + * can trigger that by merely providing large input. + * For now, simply truncate. + */ + if (len > 256) + len = 256; for (i = 0; i < len; i++) putchar(' '); } @@ -294,7 +319,7 @@ ascii_uc2str(int uc) "<88>", "<89>", "<8A>", "<8B>", "<8C>", "<8D>", "<8E>", "<8F>", "<90>", "<91>", "<92>", "<93>", "<94>", "<95>", "<96>", "<97>", "<98>", "<99>", "<9A>", "<9B>", "<9C>", "<9D>", "<9E>", "<9F>", - nbrsp, "!", "/\bc", "GBP", "o\bx", "=\bY", "|", "
", + nbrsp, "!", "/\bc", "-\bL", "o\bx", "=\bY", "|", "
", "\"", "(C)", "_\ba", "<<", "~", "", "(R)", "-", "","+-","^2", "^3", "'","","",".", ",", "^1", "_\bo", ">>", "1/4", "1/2", "3/4", "?", @@ -364,6 +389,14 @@ locale_advance(struct termp *p, size_t len) { size_t i; + /* + * XXX We used to have "assert(len < UINT16_MAX)" here. + * that is not quite right because the input document + * can trigger that by merely providing large input. + * For now, simply truncate. + */ + if (len > 256) + len = 256; for (i = 0; i < len; i++) putwchar(L' '); } @@ -373,7 +406,10 @@ locale_endline(struct termp *p) { p->line++; - p->tcol->offset -= p->ti; + if ((int)p->tcol->offset > p->ti) + p->tcol->offset -= p->ti; + else + p->tcol->offset = 0; p->ti = 0; putwchar(L'\n'); }