xref: /titanic_51/usr/src/cmd/mandoc/term_ascii.c (revision 260e9a87725c090ba5835b1f9f0b62fa2f96036f)
1*260e9a87SYuri Pankov /*	$Id: term_ascii.c,v 1.43 2015/02/16 14:11:41 schwarze Exp $ */
295c635efSGarrett D'Amore /*
395c635efSGarrett D'Amore  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4*260e9a87SYuri Pankov  * Copyright (c) 2014 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  *
1095c635efSGarrett D'Amore  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1195c635efSGarrett D'Amore  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1295c635efSGarrett D'Amore  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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>
23*260e9a87SYuri 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>
30*260e9a87SYuri Pankov #if HAVE_WCHAR
3195c635efSGarrett D'Amore #include <wchar.h>
3295c635efSGarrett D'Amore #endif
3395c635efSGarrett D'Amore 
3495c635efSGarrett D'Amore #include "mandoc.h"
35*260e9a87SYuri Pankov #include "mandoc_aux.h"
3695c635efSGarrett D'Amore #include "out.h"
3795c635efSGarrett D'Amore #include "term.h"
3895c635efSGarrett D'Amore #include "main.h"
3995c635efSGarrett D'Amore 
40*260e9a87SYuri Pankov static	struct termp	 *ascii_init(enum termenc,
41*260e9a87SYuri Pankov 				const struct mchars *, char *);
4295c635efSGarrett D'Amore static	double		  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*260e9a87SYuri Pankov static	void		  ascii_setwidth(struct termp *, int, size_t);
5195c635efSGarrett D'Amore 
52*260e9a87SYuri 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 
59*260e9a87SYuri Pankov 
6095c635efSGarrett D'Amore static struct termp *
61*260e9a87SYuri Pankov ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts)
6295c635efSGarrett D'Amore {
63*260e9a87SYuri Pankov 	const char	*toks[5];
6495c635efSGarrett D'Amore 	char		*v;
6595c635efSGarrett D'Amore 	struct termp	*p;
66*260e9a87SYuri Pankov 	const char	*errstr;
67*260e9a87SYuri Pankov 	int		num;
6895c635efSGarrett D'Amore 
6995c635efSGarrett D'Amore 	p = mandoc_calloc(1, sizeof(struct termp));
7095c635efSGarrett D'Amore 
71*260e9a87SYuri Pankov 	p->symtab = mchars;
7295c635efSGarrett D'Amore 	p->tabwidth = 5;
73*260e9a87SYuri Pankov 	p->defrmargin = p->lastrmargin = 78;
74*260e9a87SYuri Pankov 	p->fontq = mandoc_reallocarray(NULL,
75*260e9a87SYuri Pankov 	     (p->fontsz = 8), sizeof(enum termfont));
76*260e9a87SYuri Pankov 	p->fontq[0] = p->fontl = TERMFONT_NONE;
7795c635efSGarrett D'Amore 
7895c635efSGarrett D'Amore 	p->begin = ascii_begin;
7995c635efSGarrett D'Amore 	p->end = ascii_end;
8095c635efSGarrett D'Amore 	p->hspan = ascii_hspan;
8195c635efSGarrett D'Amore 	p->type = TERMTYPE_CHAR;
8295c635efSGarrett D'Amore 
8395c635efSGarrett D'Amore 	p->enc = TERMENC_ASCII;
8495c635efSGarrett D'Amore 	p->advance = ascii_advance;
8595c635efSGarrett D'Amore 	p->endline = ascii_endline;
8695c635efSGarrett D'Amore 	p->letter = ascii_letter;
87*260e9a87SYuri Pankov 	p->setwidth = ascii_setwidth;
8895c635efSGarrett D'Amore 	p->width = ascii_width;
8995c635efSGarrett D'Amore 
90*260e9a87SYuri Pankov #if HAVE_WCHAR
9195c635efSGarrett D'Amore 	if (TERMENC_ASCII != enc) {
9295c635efSGarrett D'Amore 		v = TERMENC_LOCALE == enc ?
9395c635efSGarrett D'Amore 		    setlocale(LC_ALL, "") :
94698f87a4SGarrett D'Amore 		    setlocale(LC_CTYPE, "en_US.UTF-8");
9595c635efSGarrett D'Amore 		if (NULL != v && MB_CUR_MAX > 1) {
9695c635efSGarrett D'Amore 			p->enc = enc;
9795c635efSGarrett D'Amore 			p->advance = locale_advance;
9895c635efSGarrett D'Amore 			p->endline = locale_endline;
9995c635efSGarrett D'Amore 			p->letter = locale_letter;
10095c635efSGarrett D'Amore 			p->width = locale_width;
10195c635efSGarrett D'Amore 		}
10295c635efSGarrett D'Amore 	}
10395c635efSGarrett D'Amore #endif
10495c635efSGarrett D'Amore 
10595c635efSGarrett D'Amore 	toks[0] = "indent";
10695c635efSGarrett D'Amore 	toks[1] = "width";
10795c635efSGarrett D'Amore 	toks[2] = "mdoc";
108*260e9a87SYuri Pankov 	toks[3] = "synopsis";
109*260e9a87SYuri Pankov 	toks[4] = NULL;
11095c635efSGarrett D'Amore 
11195c635efSGarrett D'Amore 	while (outopts && *outopts)
11295c635efSGarrett D'Amore 		switch (getsubopt(&outopts, UNCONST(toks), &v)) {
113*260e9a87SYuri Pankov 		case 0:
114*260e9a87SYuri Pankov 			num = strtonum(v, 0, 1000, &errstr);
115*260e9a87SYuri Pankov 			if (!errstr)
116*260e9a87SYuri Pankov 				p->defindent = num;
11795c635efSGarrett D'Amore 			break;
118*260e9a87SYuri Pankov 		case 1:
119*260e9a87SYuri Pankov 			num = strtonum(v, 0, 1000, &errstr);
120*260e9a87SYuri Pankov 			if (!errstr)
121*260e9a87SYuri Pankov 				p->defrmargin = num;
12295c635efSGarrett D'Amore 			break;
123*260e9a87SYuri Pankov 		case 2:
12495c635efSGarrett D'Amore 			/*
12595c635efSGarrett D'Amore 			 * Temporary, undocumented mode
12695c635efSGarrett D'Amore 			 * to imitate mdoc(7) output style.
12795c635efSGarrett D'Amore 			 */
12895c635efSGarrett D'Amore 			p->mdocstyle = 1;
12995c635efSGarrett D'Amore 			p->defindent = 5;
13095c635efSGarrett D'Amore 			break;
131*260e9a87SYuri Pankov 		case 3:
132*260e9a87SYuri Pankov 			p->synopsisonly = 1;
133*260e9a87SYuri Pankov 			break;
13495c635efSGarrett D'Amore 		default:
13595c635efSGarrett D'Amore 			break;
13695c635efSGarrett D'Amore 		}
13795c635efSGarrett D'Amore 
13895c635efSGarrett D'Amore 	/* Enforce a lower boundary. */
13995c635efSGarrett D'Amore 	if (p->defrmargin < 58)
14095c635efSGarrett D'Amore 		p->defrmargin = 58;
14195c635efSGarrett D'Amore 
14295c635efSGarrett D'Amore 	return(p);
14395c635efSGarrett D'Amore }
14495c635efSGarrett D'Amore 
14595c635efSGarrett D'Amore void *
146*260e9a87SYuri Pankov ascii_alloc(const struct mchars *mchars, char *outopts)
14795c635efSGarrett D'Amore {
14895c635efSGarrett D'Amore 
149*260e9a87SYuri Pankov 	return(ascii_init(TERMENC_ASCII, mchars, outopts));
15095c635efSGarrett D'Amore }
15195c635efSGarrett D'Amore 
15295c635efSGarrett D'Amore void *
153*260e9a87SYuri Pankov utf8_alloc(const struct mchars *mchars, char *outopts)
15495c635efSGarrett D'Amore {
15595c635efSGarrett D'Amore 
156*260e9a87SYuri Pankov 	return(ascii_init(TERMENC_UTF8, mchars, outopts));
15795c635efSGarrett D'Amore }
15895c635efSGarrett D'Amore 
15995c635efSGarrett D'Amore void *
160*260e9a87SYuri Pankov locale_alloc(const struct mchars *mchars, char *outopts)
16195c635efSGarrett D'Amore {
16295c635efSGarrett D'Amore 
163*260e9a87SYuri Pankov 	return(ascii_init(TERMENC_LOCALE, mchars, outopts));
16495c635efSGarrett D'Amore }
16595c635efSGarrett D'Amore 
166*260e9a87SYuri Pankov static void
167*260e9a87SYuri Pankov ascii_setwidth(struct termp *p, int iop, size_t width)
168*260e9a87SYuri Pankov {
169*260e9a87SYuri Pankov 
170*260e9a87SYuri Pankov 	p->rmargin = p->defrmargin;
171*260e9a87SYuri Pankov 	if (iop > 0)
172*260e9a87SYuri Pankov 		p->defrmargin += width;
173*260e9a87SYuri Pankov 	else if (iop == 0)
174*260e9a87SYuri Pankov 		p->defrmargin = width ? width : p->lastrmargin;
175*260e9a87SYuri Pankov 	else if (p->defrmargin > width)
176*260e9a87SYuri Pankov 		p->defrmargin -= width;
177*260e9a87SYuri Pankov 	else
178*260e9a87SYuri Pankov 		p->defrmargin = 0;
179*260e9a87SYuri Pankov 	p->lastrmargin = p->rmargin;
180*260e9a87SYuri Pankov 	p->rmargin = p->maxrmargin = p->defrmargin;
181*260e9a87SYuri Pankov }
182*260e9a87SYuri Pankov 
183*260e9a87SYuri Pankov void
184*260e9a87SYuri Pankov ascii_sepline(void *arg)
185*260e9a87SYuri Pankov {
186*260e9a87SYuri Pankov 	struct termp	*p;
187*260e9a87SYuri Pankov 	size_t		 i;
188*260e9a87SYuri Pankov 
189*260e9a87SYuri Pankov 	p = (struct termp *)arg;
190*260e9a87SYuri Pankov 	putchar('\n');
191*260e9a87SYuri Pankov 	for (i = 0; i < p->defrmargin; i++)
192*260e9a87SYuri Pankov 		putchar('-');
193*260e9a87SYuri Pankov 	putchar('\n');
194*260e9a87SYuri Pankov 	putchar('\n');
195*260e9a87SYuri Pankov }
196*260e9a87SYuri Pankov 
19795c635efSGarrett D'Amore static size_t
19895c635efSGarrett D'Amore ascii_width(const struct termp *p, int c)
19995c635efSGarrett D'Amore {
20095c635efSGarrett D'Amore 
20195c635efSGarrett D'Amore 	return(1);
20295c635efSGarrett D'Amore }
20395c635efSGarrett D'Amore 
20495c635efSGarrett D'Amore void
20595c635efSGarrett D'Amore ascii_free(void *arg)
20695c635efSGarrett D'Amore {
20795c635efSGarrett D'Amore 
20895c635efSGarrett D'Amore 	term_free((struct termp *)arg);
20995c635efSGarrett D'Amore }
21095c635efSGarrett D'Amore 
21195c635efSGarrett D'Amore static void
21295c635efSGarrett D'Amore ascii_letter(struct termp *p, int c)
21395c635efSGarrett D'Amore {
21495c635efSGarrett D'Amore 
21595c635efSGarrett D'Amore 	putchar(c);
21695c635efSGarrett D'Amore }
21795c635efSGarrett D'Amore 
21895c635efSGarrett D'Amore static void
21995c635efSGarrett D'Amore ascii_begin(struct termp *p)
22095c635efSGarrett D'Amore {
22195c635efSGarrett D'Amore 
22295c635efSGarrett D'Amore 	(*p->headf)(p, p->argf);
22395c635efSGarrett D'Amore }
22495c635efSGarrett D'Amore 
22595c635efSGarrett D'Amore static void
22695c635efSGarrett D'Amore ascii_end(struct termp *p)
22795c635efSGarrett D'Amore {
22895c635efSGarrett D'Amore 
22995c635efSGarrett D'Amore 	(*p->footf)(p, p->argf);
23095c635efSGarrett D'Amore }
23195c635efSGarrett D'Amore 
23295c635efSGarrett D'Amore static void
23395c635efSGarrett D'Amore ascii_endline(struct termp *p)
23495c635efSGarrett D'Amore {
23595c635efSGarrett D'Amore 
23695c635efSGarrett D'Amore 	putchar('\n');
23795c635efSGarrett D'Amore }
23895c635efSGarrett D'Amore 
23995c635efSGarrett D'Amore static void
24095c635efSGarrett D'Amore ascii_advance(struct termp *p, size_t len)
24195c635efSGarrett D'Amore {
24295c635efSGarrett D'Amore 	size_t		i;
24395c635efSGarrett D'Amore 
24495c635efSGarrett D'Amore 	for (i = 0; i < len; i++)
24595c635efSGarrett D'Amore 		putchar(' ');
24695c635efSGarrett D'Amore }
24795c635efSGarrett D'Amore 
24895c635efSGarrett D'Amore static double
24995c635efSGarrett D'Amore ascii_hspan(const struct termp *p, const struct roffsu *su)
25095c635efSGarrett D'Amore {
25195c635efSGarrett D'Amore 	double		 r;
25295c635efSGarrett D'Amore 
25395c635efSGarrett D'Amore 	/*
254*260e9a87SYuri Pankov 	 * Approximate based on character width.
255*260e9a87SYuri Pankov 	 * None of these will be actually correct given that an inch on
256*260e9a87SYuri Pankov 	 * the screen depends on character size, terminal, etc., etc.
25795c635efSGarrett D'Amore 	 */
25895c635efSGarrett D'Amore 	switch (su->unit) {
259*260e9a87SYuri Pankov 	case SCALE_BU:
260*260e9a87SYuri Pankov 		r = su->scale * 10.0 / 240.0;
26195c635efSGarrett D'Amore 		break;
262*260e9a87SYuri Pankov 	case SCALE_CM:
263*260e9a87SYuri Pankov 		r = su->scale * 10.0 / 2.54;
26495c635efSGarrett D'Amore 		break;
265*260e9a87SYuri Pankov 	case SCALE_FS:
266*260e9a87SYuri Pankov 		r = su->scale * 2730.666;
26795c635efSGarrett D'Amore 		break;
268*260e9a87SYuri Pankov 	case SCALE_IN:
269*260e9a87SYuri Pankov 		r = su->scale * 10.0;
27095c635efSGarrett D'Amore 		break;
271*260e9a87SYuri Pankov 	case SCALE_MM:
272*260e9a87SYuri Pankov 		r = su->scale / 100.0;
27395c635efSGarrett D'Amore 		break;
274*260e9a87SYuri Pankov 	case SCALE_PC:
275*260e9a87SYuri Pankov 		r = su->scale * 10.0 / 6.0;
27695c635efSGarrett D'Amore 		break;
277*260e9a87SYuri Pankov 	case SCALE_PT:
278*260e9a87SYuri Pankov 		r = su->scale * 10.0 / 72.0;
279*260e9a87SYuri Pankov 		break;
280*260e9a87SYuri Pankov 	case SCALE_VS:
281*260e9a87SYuri Pankov 		r = su->scale * 2.0 - 1.0;
282*260e9a87SYuri Pankov 		break;
283*260e9a87SYuri Pankov 	case SCALE_EN:
284*260e9a87SYuri Pankov 		/* FALLTHROUGH */
285*260e9a87SYuri Pankov 	case SCALE_EM:
28695c635efSGarrett D'Amore 		r = su->scale;
28795c635efSGarrett D'Amore 		break;
288*260e9a87SYuri Pankov 	default:
289*260e9a87SYuri Pankov 		abort();
290*260e9a87SYuri Pankov 		/* NOTREACHED */
29195c635efSGarrett D'Amore 	}
29295c635efSGarrett D'Amore 
29395c635efSGarrett D'Amore 	return(r);
29495c635efSGarrett D'Amore }
29595c635efSGarrett D'Amore 
296*260e9a87SYuri Pankov const char *
297*260e9a87SYuri Pankov ascii_uc2str(int uc)
298*260e9a87SYuri Pankov {
299*260e9a87SYuri Pankov 	static const char nbrsp[2] = { ASCII_NBRSP, '\0' };
300*260e9a87SYuri Pankov 	static const char *tab[] = {
301*260e9a87SYuri Pankov 	"<NUL>","<SOH>","<STX>","<ETX>","<EOT>","<ENQ>","<ACK>","<BEL>",
302*260e9a87SYuri Pankov 	"<BS>",	"\t",	"<LF>",	"<VT>",	"<FF>",	"<CR>",	"<SO>",	"<SI>",
303*260e9a87SYuri Pankov 	"<DLE>","<DC1>","<DC2>","<DC3>","<DC4>","<NAK>","<SYN>","<ETB>",
304*260e9a87SYuri Pankov 	"<CAN>","<EM>",	"<SUB>","<ESC>","<FS>",	"<GS>",	"<RS>",	"<US>",
305*260e9a87SYuri Pankov 	" ",	"!",	"\"",	"#",	"$",	"%",	"&",	"'",
306*260e9a87SYuri Pankov 	"(",	")",	"*",	"+",	",",	"-",	".",	"/",
307*260e9a87SYuri Pankov 	"0",	"1",	"2",	"3",	"4",	"5",	"6",	"7",
308*260e9a87SYuri Pankov 	"8",	"9",	":",	";",	"<",	"=",	">",	"?",
309*260e9a87SYuri Pankov 	"@",	"A",	"B",	"C",	"D",	"E",	"F",	"G",
310*260e9a87SYuri Pankov 	"H",	"I",	"J",	"K",	"L",	"M",	"N",	"O",
311*260e9a87SYuri Pankov 	"P",	"Q",	"R",	"S",	"T",	"U",	"V",	"W",
312*260e9a87SYuri Pankov 	"X",	"Y",	"Z",	"[",	"\\",	"]",	"^",	"_",
313*260e9a87SYuri Pankov 	"`",	"a",	"b",	"c",	"d",	"e",	"f",	"g",
314*260e9a87SYuri Pankov 	"h",	"i",	"j",	"k",	"l",	"m",	"n",	"o",
315*260e9a87SYuri Pankov 	"p",	"q",	"r",	"s",	"t",	"u",	"v",	"w",
316*260e9a87SYuri Pankov 	"x",	"y",	"z",	"{",	"|",	"}",	"~",	"<DEL>",
317*260e9a87SYuri Pankov 	"<80>",	"<81>",	"<82>",	"<83>",	"<84>",	"<85>",	"<86>",	"<87>",
318*260e9a87SYuri Pankov 	"<88>",	"<89>",	"<8A>",	"<8B>",	"<8C>",	"<8D>",	"<8E>",	"<8F>",
319*260e9a87SYuri Pankov 	"<90>",	"<91>",	"<92>",	"<93>",	"<94>",	"<95>",	"<96>",	"<97>",
320*260e9a87SYuri Pankov 	"<99>",	"<99>",	"<9A>",	"<9B>",	"<9C>",	"<9D>",	"<9E>",	"<9F>",
321*260e9a87SYuri Pankov 	nbrsp,	"!",	"/\bc",	"GBP",	"o\bx",	"=\bY",	"|",	"<sec>",
322*260e9a87SYuri Pankov 	"\"",	"(C)",	"_\ba",	"<<",	"~",	"",	"(R)",	"-",
323*260e9a87SYuri Pankov 	"<deg>","+-",	"2",	"3",	"'",	",\bu",	"<par>",".",
324*260e9a87SYuri Pankov 	",",	"1",	"_\bo",	">>",	"1/4",	"1/2",	"3/4",	"?",
325*260e9a87SYuri Pankov 	"`\bA",	"'\bA",	"^\bA",	"~\bA",	"\"\bA","o\bA",	"AE",	",\bC",
326*260e9a87SYuri Pankov 	"`\bE",	"'\bE",	"^\bE",	"\"\bE","`\bI",	"'\bI",	"^\bI",	"\"\bI",
327*260e9a87SYuri Pankov 	"-\bD",	"~\bN",	"`\bO",	"'\bO",	"^\bO",	"~\bO",	"\"\bO","x",
328*260e9a87SYuri Pankov 	"/\bO",	"`\bU",	"'\bU",	"^\bU",	"\"\bU","'\bY",	"Th",	"ss",
329*260e9a87SYuri Pankov 	"`\ba",	"'\ba",	"^\ba",	"~\ba",	"\"\ba","o\ba",	"ae",	",\bc",
330*260e9a87SYuri Pankov 	"`\be",	"'\be",	"^\be",	"\"\be","`\bi",	"'\bi",	"^\bi",	"\"\bi",
331*260e9a87SYuri Pankov 	"d",	"~\bn",	"`\bo",	"'\bo",	"^\bo",	"~\bo",	"\"\bo","-:-",
332*260e9a87SYuri Pankov 	"/\bo",	"`\bu",	"'\bu",	"^\bu",	"\"\bu","'\by",	"th",	"\"\by",
333*260e9a87SYuri Pankov 	"A",	"a",	"A",	"a",	"A",	"a",	"'\bC",	"'\bc",
334*260e9a87SYuri Pankov 	"^\bC",	"^\bc",	"C",	"c",	"C",	"c",	"D",	"d",
335*260e9a87SYuri Pankov 	"/\bD",	"/\bd",	"E",	"e",	"E",	"e",	"E",	"e",
336*260e9a87SYuri Pankov 	"E",	"e",	"E",	"e",	"^\bG",	"^\bg",	"G",	"g",
337*260e9a87SYuri Pankov 	"G",	"g",	",\bG",	",\bg",	"^\bH",	"^\bh",	"/\bH",	"/\bh",
338*260e9a87SYuri Pankov 	"~\bI",	"~\bi",	"I",	"i",	"I",	"i",	"I",	"i",
339*260e9a87SYuri Pankov 	"I",	"i",	"IJ",	"ij",	"^\bJ",	"^\bj",	",\bK",	",\bk",
340*260e9a87SYuri Pankov 	"q",	"'\bL",	"'\bl",	",\bL",	",\bl",	"L",	"l",	"L",
341*260e9a87SYuri Pankov 	"l",	"/\bL",	"/\bl",	"'\bN",	"'\bn",	",\bN",	",\bn",	"N",
342*260e9a87SYuri Pankov 	"n",	"'n",	"Ng",	"ng",	"O",	"o",	"O",	"o",
343*260e9a87SYuri Pankov 	"O",	"o",	"OE",	"oe",	"'\bR",	"'\br",	",\bR",	",\br",
344*260e9a87SYuri Pankov 	"R",	"r",	"'\bS",	"'\bs",	"^\bS",	"^\bs",	",\bS",	",\bs",
345*260e9a87SYuri Pankov 	"S",	"s",	",\bT",	",\bt",	"T",	"t",	"/\bT",	"/\bt",
346*260e9a87SYuri Pankov 	"~\bU",	"~\bu",	"U",	"u",	"U",	"u",	"U",	"u",
347*260e9a87SYuri Pankov 	"U",	"u",	"U",	"u",	"^\bW",	"^\bw",	"^\bY",	"^\by",
348*260e9a87SYuri Pankov 	"\"\bY","'\bZ",	"'\bz",	"Z",	"z",	"Z",	"z",	"s",
349*260e9a87SYuri Pankov 	"b",	"B",	"B",	"b",	"6",	"6",	"O",	"C",
350*260e9a87SYuri Pankov 	"c",	"D",	"D",	"D",	"d",	"d",	"3",	"@",
351*260e9a87SYuri Pankov 	"E",	"F",	",\bf",	"G",	"G",	"hv",	"I",	"/\bI",
352*260e9a87SYuri Pankov 	"K",	"k",	"/\bl",	"l",	"W",	"N",	"n",	"~\bO",
353*260e9a87SYuri Pankov 	"O",	"o",	"OI",	"oi",	"P",	"p",	"YR",	"2",
354*260e9a87SYuri Pankov 	"2",	"SH",	"sh",	"t",	"T",	"t",	"T",	"U",
355*260e9a87SYuri Pankov 	"u",	"Y",	"V",	"Y",	"y",	"/\bZ",	"/\bz",	"ZH",
356*260e9a87SYuri Pankov 	"ZH",	"zh",	"zh",	"/\b2",	"5",	"5",	"ts",	"w",
357*260e9a87SYuri Pankov 	"|",	"||",	"|=",	"!",	"DZ",	"Dz",	"dz",	"LJ",
358*260e9a87SYuri Pankov 	"Lj",	"lj",	"NJ",	"Nj",	"nj",	"A",	"a",	"I",
359*260e9a87SYuri Pankov 	"i",	"O",	"o",	"U",	"u",	"U",	"u",	"U",
360*260e9a87SYuri Pankov 	"u",	"U",	"u",	"U",	"u",	"@",	"A",	"a",
361*260e9a87SYuri Pankov 	"A",	"a",	"AE",	"ae",	"/\bG",	"/\bg",	"G",	"g",
362*260e9a87SYuri Pankov 	"K",	"k",	"O",	"o",	"O",	"o",	"ZH",	"zh",
363*260e9a87SYuri Pankov 	"j",	"DZ",	"Dz",	"dz",	"'\bG",	"'\bg",	"HV",	"W",
364*260e9a87SYuri Pankov 	"`\bN",	"`\bn",	"A",	"a",	"'\bAE","'\bae","O",	"o"};
365*260e9a87SYuri Pankov 
366*260e9a87SYuri Pankov 	assert(uc >= 0);
367*260e9a87SYuri Pankov 	if ((size_t)uc < sizeof(tab)/sizeof(tab[0]))
368*260e9a87SYuri Pankov 		return(tab[uc]);
369*260e9a87SYuri Pankov 	return(mchars_uc2str(uc));
370*260e9a87SYuri Pankov }
371*260e9a87SYuri Pankov 
372*260e9a87SYuri Pankov #if HAVE_WCHAR
37395c635efSGarrett D'Amore static size_t
37495c635efSGarrett D'Amore locale_width(const struct termp *p, int c)
37595c635efSGarrett D'Amore {
37695c635efSGarrett D'Amore 	int		rc;
37795c635efSGarrett D'Amore 
378*260e9a87SYuri Pankov 	if (c == ASCII_NBRSP)
379*260e9a87SYuri Pankov 		c = ' ';
380*260e9a87SYuri Pankov 	rc = wcwidth(c);
381*260e9a87SYuri Pankov 	if (rc < 0)
382*260e9a87SYuri Pankov 		rc = 0;
383*260e9a87SYuri Pankov 	return(rc);
38495c635efSGarrett D'Amore }
38595c635efSGarrett D'Amore 
38695c635efSGarrett D'Amore static void
38795c635efSGarrett D'Amore locale_advance(struct termp *p, size_t len)
38895c635efSGarrett D'Amore {
38995c635efSGarrett D'Amore 	size_t		i;
39095c635efSGarrett D'Amore 
39195c635efSGarrett D'Amore 	for (i = 0; i < len; i++)
39295c635efSGarrett D'Amore 		putwchar(L' ');
39395c635efSGarrett D'Amore }
39495c635efSGarrett D'Amore 
39595c635efSGarrett D'Amore static void
39695c635efSGarrett D'Amore locale_endline(struct termp *p)
39795c635efSGarrett D'Amore {
39895c635efSGarrett D'Amore 
39995c635efSGarrett D'Amore 	putwchar(L'\n');
40095c635efSGarrett D'Amore }
40195c635efSGarrett D'Amore 
40295c635efSGarrett D'Amore static void
40395c635efSGarrett D'Amore locale_letter(struct termp *p, int c)
40495c635efSGarrett D'Amore {
40595c635efSGarrett D'Amore 
40695c635efSGarrett D'Amore 	putwchar(c);
40795c635efSGarrett D'Amore }
40895c635efSGarrett D'Amore #endif
409