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 *
ascii_init(enum termenc enc,const struct mchars * mchars,char * outopts)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 *
ascii_alloc(const struct mchars * mchars,char * outopts)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 *
utf8_alloc(const struct mchars * mchars,char * outopts)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 *
locale_alloc(const struct mchars * mchars,char * outopts)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
ascii_setwidth(struct termp * p,int iop,size_t width)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
ascii_sepline(void * arg)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
ascii_width(const struct termp * p,int c)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
ascii_free(void * arg)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
ascii_letter(struct termp * p,int c)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
ascii_begin(struct termp * p)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
ascii_end(struct termp * p)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
ascii_endline(struct termp * p)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
ascii_advance(struct termp * p,size_t len)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
ascii_hspan(const struct termp * p,const struct roffsu * su)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 *
ascii_uc2str(int uc)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
locale_width(const struct termp * p,int c)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
locale_advance(struct termp * p,size_t len)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
locale_endline(struct termp * p)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
locale_letter(struct termp * p,int c)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