xref: /illumos-gate/usr/src/cmd/mandoc/term_ascii.c (revision 371584c2eae4cf827fd406ba26c14f021adaaa70)
1*371584c2SYuri Pankov /*	$Id: term_ascii.c,v 1.53 2016/07/08 22:29:05 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*371584c2SYuri Pankov  * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
595c635efSGarrett D'Amore  *
695c635efSGarrett D'Amore  * Permission to use, copy, modify, and distribute this software for any
795c635efSGarrett D'Amore  * purpose with or without fee is hereby granted, provided that the above
895c635efSGarrett D'Amore  * copyright notice and this permission notice appear in all copies.
995c635efSGarrett D'Amore  *
10*371584c2SYuri Pankov  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
1195c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*371584c2SYuri Pankov  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
1395c635efSGarrett D'Amore  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1495c635efSGarrett D'Amore  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1595c635efSGarrett D'Amore  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1695c635efSGarrett D'Amore  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1795c635efSGarrett D'Amore  */
1895c635efSGarrett D'Amore #include "config.h"
1995c635efSGarrett D'Amore 
2095c635efSGarrett D'Amore #include <sys/types.h>
2195c635efSGarrett D'Amore 
2295c635efSGarrett D'Amore #include <assert.h>
23260e9a87SYuri Pankov #if HAVE_WCHAR
2495c635efSGarrett D'Amore #include <locale.h>
2595c635efSGarrett D'Amore #endif
2695c635efSGarrett D'Amore #include <stdint.h>
2795c635efSGarrett D'Amore #include <stdio.h>
2895c635efSGarrett D'Amore #include <stdlib.h>
2995c635efSGarrett D'Amore #include <unistd.h>
30260e9a87SYuri Pankov #if HAVE_WCHAR
3195c635efSGarrett D'Amore #include <wchar.h>
3295c635efSGarrett D'Amore #endif
3395c635efSGarrett D'Amore 
3495c635efSGarrett D'Amore #include "mandoc.h"
35260e9a87SYuri Pankov #include "mandoc_aux.h"
3695c635efSGarrett D'Amore #include "out.h"
3795c635efSGarrett D'Amore #include "term.h"
38*371584c2SYuri Pankov #include "manconf.h"
3995c635efSGarrett D'Amore #include "main.h"
4095c635efSGarrett D'Amore 
41*371584c2SYuri Pankov static	struct termp	 *ascii_init(enum termenc, const struct manoutput *);
42*371584c2SYuri Pankov static	int		  ascii_hspan(const struct termp *,
4395c635efSGarrett D'Amore 				const struct roffsu *);
4495c635efSGarrett D'Amore static	size_t		  ascii_width(const struct termp *, int);
4595c635efSGarrett D'Amore static	void		  ascii_advance(struct termp *, size_t);
4695c635efSGarrett D'Amore static	void		  ascii_begin(struct termp *);
4795c635efSGarrett D'Amore static	void		  ascii_end(struct termp *);
4895c635efSGarrett D'Amore static	void		  ascii_endline(struct termp *);
4995c635efSGarrett D'Amore static	void		  ascii_letter(struct termp *, int);
50*371584c2SYuri Pankov static	void		  ascii_setwidth(struct termp *, int, int);
5195c635efSGarrett D'Amore 
52260e9a87SYuri Pankov #if HAVE_WCHAR
5395c635efSGarrett D'Amore static	void		  locale_advance(struct termp *, size_t);
5495c635efSGarrett D'Amore static	void		  locale_endline(struct termp *);
5595c635efSGarrett D'Amore static	void		  locale_letter(struct termp *, int);
5695c635efSGarrett D'Amore static	size_t		  locale_width(const struct termp *, int);
5795c635efSGarrett D'Amore #endif
5895c635efSGarrett D'Amore 
59260e9a87SYuri Pankov 
6095c635efSGarrett D'Amore static struct termp *
61*371584c2SYuri Pankov ascii_init(enum termenc enc, const struct manoutput *outopts)
6295c635efSGarrett D'Amore {
63*371584c2SYuri Pankov #if HAVE_WCHAR
6495c635efSGarrett D'Amore 	char		*v;
65*371584c2SYuri Pankov #endif
6695c635efSGarrett D'Amore 	struct termp	*p;
6795c635efSGarrett D'Amore 
6895c635efSGarrett D'Amore 	p = mandoc_calloc(1, sizeof(struct termp));
6995c635efSGarrett D'Amore 
70*371584c2SYuri Pankov 	p->line = 1;
7195c635efSGarrett D'Amore 	p->tabwidth = 5;
72260e9a87SYuri Pankov 	p->defrmargin = p->lastrmargin = 78;
73260e9a87SYuri Pankov 	p->fontq = mandoc_reallocarray(NULL,
74260e9a87SYuri Pankov 	     (p->fontsz = 8), sizeof(enum termfont));
75260e9a87SYuri Pankov 	p->fontq[0] = p->fontl = TERMFONT_NONE;
7695c635efSGarrett D'Amore 
7795c635efSGarrett D'Amore 	p->begin = ascii_begin;
7895c635efSGarrett D'Amore 	p->end = ascii_end;
7995c635efSGarrett D'Amore 	p->hspan = ascii_hspan;
8095c635efSGarrett D'Amore 	p->type = TERMTYPE_CHAR;
8195c635efSGarrett D'Amore 
8295c635efSGarrett D'Amore 	p->enc = TERMENC_ASCII;
8395c635efSGarrett D'Amore 	p->advance = ascii_advance;
8495c635efSGarrett D'Amore 	p->endline = ascii_endline;
8595c635efSGarrett D'Amore 	p->letter = ascii_letter;
86260e9a87SYuri Pankov 	p->setwidth = ascii_setwidth;
8795c635efSGarrett D'Amore 	p->width = ascii_width;
8895c635efSGarrett D'Amore 
89260e9a87SYuri Pankov #if HAVE_WCHAR
9095c635efSGarrett D'Amore 	if (TERMENC_ASCII != enc) {
91*371584c2SYuri Pankov 
92*371584c2SYuri Pankov 		/*
93*371584c2SYuri Pankov 		 * Do not change any of this to LC_ALL.  It might break
94*371584c2SYuri Pankov 		 * the formatting by subtly changing the behaviour of
95*371584c2SYuri Pankov 		 * various functions, for example strftime(3).  As a
96*371584c2SYuri Pankov 		 * worst case, it might even cause buffer overflows.
97*371584c2SYuri Pankov 		 */
98*371584c2SYuri Pankov 
9995c635efSGarrett D'Amore 		v = TERMENC_LOCALE == enc ?
100*371584c2SYuri Pankov 		    setlocale(LC_CTYPE, "") :
101698f87a4SGarrett D'Amore 		    setlocale(LC_CTYPE, "en_US.UTF-8");
10295c635efSGarrett D'Amore 		if (NULL != v && MB_CUR_MAX > 1) {
10395c635efSGarrett D'Amore 			p->enc = enc;
10495c635efSGarrett D'Amore 			p->advance = locale_advance;
10595c635efSGarrett D'Amore 			p->endline = locale_endline;
10695c635efSGarrett D'Amore 			p->letter = locale_letter;
10795c635efSGarrett D'Amore 			p->width = locale_width;
10895c635efSGarrett D'Amore 		}
10995c635efSGarrett D'Amore 	}
11095c635efSGarrett D'Amore #endif
11195c635efSGarrett D'Amore 
112*371584c2SYuri Pankov 	if (outopts->mdoc) {
11395c635efSGarrett D'Amore 		p->mdocstyle = 1;
11495c635efSGarrett D'Amore 		p->defindent = 5;
115*371584c2SYuri Pankov 	}
116*371584c2SYuri Pankov 	if (outopts->indent)
117*371584c2SYuri Pankov 		p->defindent = outopts->indent;
118*371584c2SYuri Pankov 	if (outopts->width)
119*371584c2SYuri Pankov 		p->defrmargin = outopts->width;
120*371584c2SYuri Pankov 	if (outopts->synopsisonly)
121260e9a87SYuri Pankov 		p->synopsisonly = 1;
12295c635efSGarrett D'Amore 
123*371584c2SYuri Pankov 	return p;
12495c635efSGarrett D'Amore }
12595c635efSGarrett D'Amore 
12695c635efSGarrett D'Amore void *
127*371584c2SYuri Pankov ascii_alloc(const struct manoutput *outopts)
12895c635efSGarrett D'Amore {
12995c635efSGarrett D'Amore 
130*371584c2SYuri Pankov 	return ascii_init(TERMENC_ASCII, outopts);
13195c635efSGarrett D'Amore }
13295c635efSGarrett D'Amore 
13395c635efSGarrett D'Amore void *
134*371584c2SYuri Pankov utf8_alloc(const struct manoutput *outopts)
13595c635efSGarrett D'Amore {
13695c635efSGarrett D'Amore 
137*371584c2SYuri Pankov 	return ascii_init(TERMENC_UTF8, outopts);
13895c635efSGarrett D'Amore }
13995c635efSGarrett D'Amore 
14095c635efSGarrett D'Amore void *
141*371584c2SYuri Pankov locale_alloc(const struct manoutput *outopts)
14295c635efSGarrett D'Amore {
14395c635efSGarrett D'Amore 
144*371584c2SYuri Pankov 	return ascii_init(TERMENC_LOCALE, outopts);
14595c635efSGarrett D'Amore }
14695c635efSGarrett D'Amore 
147260e9a87SYuri Pankov static void
148*371584c2SYuri Pankov ascii_setwidth(struct termp *p, int iop, int width)
149260e9a87SYuri Pankov {
150260e9a87SYuri Pankov 
151*371584c2SYuri Pankov 	width /= 24;
152260e9a87SYuri Pankov 	p->rmargin = p->defrmargin;
153260e9a87SYuri Pankov 	if (iop > 0)
154260e9a87SYuri Pankov 		p->defrmargin += width;
155260e9a87SYuri Pankov 	else if (iop == 0)
156*371584c2SYuri Pankov 		p->defrmargin = width ? (size_t)width : p->lastrmargin;
157*371584c2SYuri Pankov 	else if (p->defrmargin > (size_t)width)
158260e9a87SYuri Pankov 		p->defrmargin -= width;
159260e9a87SYuri Pankov 	else
160260e9a87SYuri Pankov 		p->defrmargin = 0;
161260e9a87SYuri Pankov 	p->lastrmargin = p->rmargin;
162260e9a87SYuri Pankov 	p->rmargin = p->maxrmargin = p->defrmargin;
163260e9a87SYuri Pankov }
164260e9a87SYuri Pankov 
165260e9a87SYuri Pankov void
166*371584c2SYuri Pankov terminal_sepline(void *arg)
167260e9a87SYuri Pankov {
168260e9a87SYuri Pankov 	struct termp	*p;
169260e9a87SYuri Pankov 	size_t		 i;
170260e9a87SYuri Pankov 
171260e9a87SYuri Pankov 	p = (struct termp *)arg;
172*371584c2SYuri Pankov 	(*p->endline)(p);
173260e9a87SYuri Pankov 	for (i = 0; i < p->defrmargin; i++)
174*371584c2SYuri Pankov 		(*p->letter)(p, '-');
175*371584c2SYuri Pankov 	(*p->endline)(p);
176*371584c2SYuri Pankov 	(*p->endline)(p);
177260e9a87SYuri Pankov }
178260e9a87SYuri Pankov 
17995c635efSGarrett D'Amore static size_t
18095c635efSGarrett D'Amore ascii_width(const struct termp *p, int c)
18195c635efSGarrett D'Amore {
18295c635efSGarrett D'Amore 
183*371584c2SYuri Pankov 	return 1;
18495c635efSGarrett D'Amore }
18595c635efSGarrett D'Amore 
18695c635efSGarrett D'Amore void
18795c635efSGarrett D'Amore ascii_free(void *arg)
18895c635efSGarrett D'Amore {
18995c635efSGarrett D'Amore 
19095c635efSGarrett D'Amore 	term_free((struct termp *)arg);
19195c635efSGarrett D'Amore }
19295c635efSGarrett D'Amore 
19395c635efSGarrett D'Amore static void
19495c635efSGarrett D'Amore ascii_letter(struct termp *p, int c)
19595c635efSGarrett D'Amore {
19695c635efSGarrett D'Amore 
19795c635efSGarrett D'Amore 	putchar(c);
19895c635efSGarrett D'Amore }
19995c635efSGarrett D'Amore 
20095c635efSGarrett D'Amore static void
20195c635efSGarrett D'Amore ascii_begin(struct termp *p)
20295c635efSGarrett D'Amore {
20395c635efSGarrett D'Amore 
20495c635efSGarrett D'Amore 	(*p->headf)(p, p->argf);
20595c635efSGarrett D'Amore }
20695c635efSGarrett D'Amore 
20795c635efSGarrett D'Amore static void
20895c635efSGarrett D'Amore ascii_end(struct termp *p)
20995c635efSGarrett D'Amore {
21095c635efSGarrett D'Amore 
21195c635efSGarrett D'Amore 	(*p->footf)(p, p->argf);
21295c635efSGarrett D'Amore }
21395c635efSGarrett D'Amore 
21495c635efSGarrett D'Amore static void
21595c635efSGarrett D'Amore ascii_endline(struct termp *p)
21695c635efSGarrett D'Amore {
21795c635efSGarrett D'Amore 
218*371584c2SYuri Pankov 	p->line++;
21995c635efSGarrett D'Amore 	putchar('\n');
22095c635efSGarrett D'Amore }
22195c635efSGarrett D'Amore 
22295c635efSGarrett D'Amore static void
22395c635efSGarrett D'Amore ascii_advance(struct termp *p, size_t len)
22495c635efSGarrett D'Amore {
22595c635efSGarrett D'Amore 	size_t		i;
22695c635efSGarrett D'Amore 
22795c635efSGarrett D'Amore 	for (i = 0; i < len; i++)
22895c635efSGarrett D'Amore 		putchar(' ');
22995c635efSGarrett D'Amore }
23095c635efSGarrett D'Amore 
231*371584c2SYuri Pankov static int
23295c635efSGarrett D'Amore ascii_hspan(const struct termp *p, const struct roffsu *su)
23395c635efSGarrett D'Amore {
23495c635efSGarrett D'Amore 	double		 r;
23595c635efSGarrett D'Amore 
23695c635efSGarrett D'Amore 	switch (su->unit) {
237260e9a87SYuri Pankov 	case SCALE_BU:
238*371584c2SYuri Pankov 		r = su->scale;
23995c635efSGarrett D'Amore 		break;
240260e9a87SYuri Pankov 	case SCALE_CM:
241*371584c2SYuri Pankov 		r = su->scale * 240.0 / 2.54;
24295c635efSGarrett D'Amore 		break;
243260e9a87SYuri Pankov 	case SCALE_FS:
244*371584c2SYuri Pankov 		r = su->scale * 65536.0;
24595c635efSGarrett D'Amore 		break;
246260e9a87SYuri Pankov 	case SCALE_IN:
247*371584c2SYuri Pankov 		r = su->scale * 240.0;
24895c635efSGarrett D'Amore 		break;
249260e9a87SYuri Pankov 	case SCALE_MM:
250*371584c2SYuri Pankov 		r = su->scale * 0.24;
251260e9a87SYuri Pankov 		break;
252260e9a87SYuri Pankov 	case SCALE_VS:
253*371584c2SYuri Pankov 	case SCALE_PC:
254*371584c2SYuri Pankov 		r = su->scale * 40.0;
255*371584c2SYuri Pankov 		break;
256*371584c2SYuri Pankov 	case SCALE_PT:
257*371584c2SYuri Pankov 		r = su->scale * 10.0 / 3.0;
258260e9a87SYuri Pankov 		break;
259260e9a87SYuri Pankov 	case SCALE_EN:
260260e9a87SYuri Pankov 	case SCALE_EM:
261*371584c2SYuri Pankov 		r = su->scale * 24.0;
26295c635efSGarrett D'Amore 		break;
263260e9a87SYuri Pankov 	default:
264260e9a87SYuri Pankov 		abort();
26595c635efSGarrett D'Amore 	}
266*371584c2SYuri Pankov 	return r > 0.0 ? r + 0.01 : r - 0.01;
26795c635efSGarrett D'Amore }
26895c635efSGarrett D'Amore 
269260e9a87SYuri Pankov const char *
270260e9a87SYuri Pankov ascii_uc2str(int uc)
271260e9a87SYuri Pankov {
272260e9a87SYuri Pankov 	static const char nbrsp[2] = { ASCII_NBRSP, '\0' };
273260e9a87SYuri Pankov 	static const char *tab[] = {
274260e9a87SYuri Pankov 	"<NUL>","<SOH>","<STX>","<ETX>","<EOT>","<ENQ>","<ACK>","<BEL>",
275260e9a87SYuri Pankov 	"<BS>",	"\t",	"<LF>",	"<VT>",	"<FF>",	"<CR>",	"<SO>",	"<SI>",
276260e9a87SYuri Pankov 	"<DLE>","<DC1>","<DC2>","<DC3>","<DC4>","<NAK>","<SYN>","<ETB>",
277260e9a87SYuri Pankov 	"<CAN>","<EM>",	"<SUB>","<ESC>","<FS>",	"<GS>",	"<RS>",	"<US>",
278260e9a87SYuri Pankov 	" ",	"!",	"\"",	"#",	"$",	"%",	"&",	"'",
279260e9a87SYuri Pankov 	"(",	")",	"*",	"+",	",",	"-",	".",	"/",
280260e9a87SYuri Pankov 	"0",	"1",	"2",	"3",	"4",	"5",	"6",	"7",
281260e9a87SYuri Pankov 	"8",	"9",	":",	";",	"<",	"=",	">",	"?",
282260e9a87SYuri Pankov 	"@",	"A",	"B",	"C",	"D",	"E",	"F",	"G",
283260e9a87SYuri Pankov 	"H",	"I",	"J",	"K",	"L",	"M",	"N",	"O",
284260e9a87SYuri Pankov 	"P",	"Q",	"R",	"S",	"T",	"U",	"V",	"W",
285260e9a87SYuri Pankov 	"X",	"Y",	"Z",	"[",	"\\",	"]",	"^",	"_",
286260e9a87SYuri Pankov 	"`",	"a",	"b",	"c",	"d",	"e",	"f",	"g",
287260e9a87SYuri Pankov 	"h",	"i",	"j",	"k",	"l",	"m",	"n",	"o",
288260e9a87SYuri Pankov 	"p",	"q",	"r",	"s",	"t",	"u",	"v",	"w",
289260e9a87SYuri Pankov 	"x",	"y",	"z",	"{",	"|",	"}",	"~",	"<DEL>",
290260e9a87SYuri Pankov 	"<80>",	"<81>",	"<82>",	"<83>",	"<84>",	"<85>",	"<86>",	"<87>",
291260e9a87SYuri Pankov 	"<88>",	"<89>",	"<8A>",	"<8B>",	"<8C>",	"<8D>",	"<8E>",	"<8F>",
292260e9a87SYuri Pankov 	"<90>",	"<91>",	"<92>",	"<93>",	"<94>",	"<95>",	"<96>",	"<97>",
293260e9a87SYuri Pankov 	"<99>",	"<99>",	"<9A>",	"<9B>",	"<9C>",	"<9D>",	"<9E>",	"<9F>",
294260e9a87SYuri Pankov 	nbrsp,	"!",	"/\bc",	"GBP",	"o\bx",	"=\bY",	"|",	"<sec>",
295260e9a87SYuri Pankov 	"\"",	"(C)",	"_\ba",	"<<",	"~",	"",	"(R)",	"-",
296260e9a87SYuri Pankov 	"<deg>","+-",	"2",	"3",	"'",	",\bu",	"<par>",".",
297260e9a87SYuri Pankov 	",",	"1",	"_\bo",	">>",	"1/4",	"1/2",	"3/4",	"?",
298260e9a87SYuri Pankov 	"`\bA",	"'\bA",	"^\bA",	"~\bA",	"\"\bA","o\bA",	"AE",	",\bC",
299260e9a87SYuri Pankov 	"`\bE",	"'\bE",	"^\bE",	"\"\bE","`\bI",	"'\bI",	"^\bI",	"\"\bI",
300260e9a87SYuri Pankov 	"-\bD",	"~\bN",	"`\bO",	"'\bO",	"^\bO",	"~\bO",	"\"\bO","x",
301260e9a87SYuri Pankov 	"/\bO",	"`\bU",	"'\bU",	"^\bU",	"\"\bU","'\bY",	"Th",	"ss",
302260e9a87SYuri Pankov 	"`\ba",	"'\ba",	"^\ba",	"~\ba",	"\"\ba","o\ba",	"ae",	",\bc",
303260e9a87SYuri Pankov 	"`\be",	"'\be",	"^\be",	"\"\be","`\bi",	"'\bi",	"^\bi",	"\"\bi",
304260e9a87SYuri Pankov 	"d",	"~\bn",	"`\bo",	"'\bo",	"^\bo",	"~\bo",	"\"\bo","-:-",
305260e9a87SYuri Pankov 	"/\bo",	"`\bu",	"'\bu",	"^\bu",	"\"\bu","'\by",	"th",	"\"\by",
306260e9a87SYuri Pankov 	"A",	"a",	"A",	"a",	"A",	"a",	"'\bC",	"'\bc",
307260e9a87SYuri Pankov 	"^\bC",	"^\bc",	"C",	"c",	"C",	"c",	"D",	"d",
308260e9a87SYuri Pankov 	"/\bD",	"/\bd",	"E",	"e",	"E",	"e",	"E",	"e",
309260e9a87SYuri Pankov 	"E",	"e",	"E",	"e",	"^\bG",	"^\bg",	"G",	"g",
310260e9a87SYuri Pankov 	"G",	"g",	",\bG",	",\bg",	"^\bH",	"^\bh",	"/\bH",	"/\bh",
311260e9a87SYuri Pankov 	"~\bI",	"~\bi",	"I",	"i",	"I",	"i",	"I",	"i",
312260e9a87SYuri Pankov 	"I",	"i",	"IJ",	"ij",	"^\bJ",	"^\bj",	",\bK",	",\bk",
313260e9a87SYuri Pankov 	"q",	"'\bL",	"'\bl",	",\bL",	",\bl",	"L",	"l",	"L",
314260e9a87SYuri Pankov 	"l",	"/\bL",	"/\bl",	"'\bN",	"'\bn",	",\bN",	",\bn",	"N",
315260e9a87SYuri Pankov 	"n",	"'n",	"Ng",	"ng",	"O",	"o",	"O",	"o",
316260e9a87SYuri Pankov 	"O",	"o",	"OE",	"oe",	"'\bR",	"'\br",	",\bR",	",\br",
317260e9a87SYuri Pankov 	"R",	"r",	"'\bS",	"'\bs",	"^\bS",	"^\bs",	",\bS",	",\bs",
318260e9a87SYuri Pankov 	"S",	"s",	",\bT",	",\bt",	"T",	"t",	"/\bT",	"/\bt",
319260e9a87SYuri Pankov 	"~\bU",	"~\bu",	"U",	"u",	"U",	"u",	"U",	"u",
320260e9a87SYuri Pankov 	"U",	"u",	"U",	"u",	"^\bW",	"^\bw",	"^\bY",	"^\by",
321260e9a87SYuri Pankov 	"\"\bY","'\bZ",	"'\bz",	"Z",	"z",	"Z",	"z",	"s",
322260e9a87SYuri Pankov 	"b",	"B",	"B",	"b",	"6",	"6",	"O",	"C",
323260e9a87SYuri Pankov 	"c",	"D",	"D",	"D",	"d",	"d",	"3",	"@",
324260e9a87SYuri Pankov 	"E",	"F",	",\bf",	"G",	"G",	"hv",	"I",	"/\bI",
325260e9a87SYuri Pankov 	"K",	"k",	"/\bl",	"l",	"W",	"N",	"n",	"~\bO",
326260e9a87SYuri Pankov 	"O",	"o",	"OI",	"oi",	"P",	"p",	"YR",	"2",
327260e9a87SYuri Pankov 	"2",	"SH",	"sh",	"t",	"T",	"t",	"T",	"U",
328260e9a87SYuri Pankov 	"u",	"Y",	"V",	"Y",	"y",	"/\bZ",	"/\bz",	"ZH",
329260e9a87SYuri Pankov 	"ZH",	"zh",	"zh",	"/\b2",	"5",	"5",	"ts",	"w",
330260e9a87SYuri Pankov 	"|",	"||",	"|=",	"!",	"DZ",	"Dz",	"dz",	"LJ",
331260e9a87SYuri Pankov 	"Lj",	"lj",	"NJ",	"Nj",	"nj",	"A",	"a",	"I",
332260e9a87SYuri Pankov 	"i",	"O",	"o",	"U",	"u",	"U",	"u",	"U",
333260e9a87SYuri Pankov 	"u",	"U",	"u",	"U",	"u",	"@",	"A",	"a",
334260e9a87SYuri Pankov 	"A",	"a",	"AE",	"ae",	"/\bG",	"/\bg",	"G",	"g",
335260e9a87SYuri Pankov 	"K",	"k",	"O",	"o",	"O",	"o",	"ZH",	"zh",
336260e9a87SYuri Pankov 	"j",	"DZ",	"Dz",	"dz",	"'\bG",	"'\bg",	"HV",	"W",
337260e9a87SYuri Pankov 	"`\bN",	"`\bn",	"A",	"a",	"'\bAE","'\bae","O",	"o"};
338260e9a87SYuri Pankov 
339260e9a87SYuri Pankov 	assert(uc >= 0);
340260e9a87SYuri Pankov 	if ((size_t)uc < sizeof(tab)/sizeof(tab[0]))
341*371584c2SYuri Pankov 		return tab[uc];
342*371584c2SYuri Pankov 	return mchars_uc2str(uc);
343260e9a87SYuri Pankov }
344260e9a87SYuri Pankov 
345260e9a87SYuri Pankov #if HAVE_WCHAR
34695c635efSGarrett D'Amore static size_t
34795c635efSGarrett D'Amore locale_width(const struct termp *p, int c)
34895c635efSGarrett D'Amore {
34995c635efSGarrett D'Amore 	int		rc;
35095c635efSGarrett D'Amore 
351260e9a87SYuri Pankov 	if (c == ASCII_NBRSP)
352260e9a87SYuri Pankov 		c = ' ';
353260e9a87SYuri Pankov 	rc = wcwidth(c);
354260e9a87SYuri Pankov 	if (rc < 0)
355260e9a87SYuri Pankov 		rc = 0;
356*371584c2SYuri Pankov 	return rc;
35795c635efSGarrett D'Amore }
35895c635efSGarrett D'Amore 
35995c635efSGarrett D'Amore static void
36095c635efSGarrett D'Amore locale_advance(struct termp *p, size_t len)
36195c635efSGarrett D'Amore {
36295c635efSGarrett D'Amore 	size_t		i;
36395c635efSGarrett D'Amore 
36495c635efSGarrett D'Amore 	for (i = 0; i < len; i++)
36595c635efSGarrett D'Amore 		putwchar(L' ');
36695c635efSGarrett D'Amore }
36795c635efSGarrett D'Amore 
36895c635efSGarrett D'Amore static void
36995c635efSGarrett D'Amore locale_endline(struct termp *p)
37095c635efSGarrett D'Amore {
37195c635efSGarrett D'Amore 
372*371584c2SYuri Pankov 	p->line++;
37395c635efSGarrett D'Amore 	putwchar(L'\n');
37495c635efSGarrett D'Amore }
37595c635efSGarrett D'Amore 
37695c635efSGarrett D'Amore static void
37795c635efSGarrett D'Amore locale_letter(struct termp *p, int c)
37895c635efSGarrett D'Amore {
37995c635efSGarrett D'Amore 
38095c635efSGarrett D'Amore 	putwchar(c);
38195c635efSGarrett D'Amore }
38295c635efSGarrett D'Amore #endif
383