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