1145479Smp/*
2145479Smp * tc.nls.c: NLS handling
3145479Smp */
4145479Smp/*-
5145479Smp * Copyright (c) 1980, 1991 The Regents of the University of California.
6145479Smp * All rights reserved.
7145479Smp *
8145479Smp * Redistribution and use in source and binary forms, with or without
9145479Smp * modification, are permitted provided that the following conditions
10145479Smp * are met:
11145479Smp * 1. Redistributions of source code must retain the above copyright
12145479Smp *    notice, this list of conditions and the following disclaimer.
13145479Smp * 2. Redistributions in binary form must reproduce the above copyright
14145479Smp *    notice, this list of conditions and the following disclaimer in the
15145479Smp *    documentation and/or other materials provided with the distribution.
16145479Smp * 3. Neither the name of the University nor the names of its contributors
17145479Smp *    may be used to endorse or promote products derived from this software
18145479Smp *    without specific prior written permission.
19145479Smp *
20145479Smp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21145479Smp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22145479Smp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23145479Smp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24145479Smp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25145479Smp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26145479Smp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27145479Smp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28145479Smp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29145479Smp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30145479Smp * SUCH DAMAGE.
31145479Smp */
32145479Smp#include "sh.h"
33145479Smp
34167465Smp#ifdef WIDE_STRINGS
35231990Smp# ifdef HAVE_WCWIDTH
36231990Smp#  ifdef UTF16_STRINGS
37145479Smpint
38231990Smpxwcwidth (wint_t wchar)
39231990Smp{
40231990Smp  wchar_t ws[2];
41231990Smp
42231990Smp  if (wchar <= 0xffff)
43231990Smp    return wcwidth ((wchar_t) wchar);
44231990Smp  /* UTF-16 systems can't handle these values directly in calls to wcwidth.
45231990Smp     However, they can handle them as surrogate pairs in calls to wcswidth.
46231990Smp     What we do here is to convert UTF-32 values >= 0x10000 into surrogate
47231990Smp     pairs and compute the width by calling wcswidth. */
48231990Smp  wchar -= 0x10000;
49231990Smp  ws[0] = 0xd800 | (wchar >> 10);
50231990Smp  ws[1] = 0xdc00 | (wchar & 0x3ff);
51231990Smp  return wcswidth (ws, 2);
52231990Smp}
53231990Smp#  else
54231990Smp#define xwcwidth wcwidth
55231990Smp#  endif /* !UTF16_STRINGS */
56231990Smp# endif /* HAVE_WCWIDTH */
57231990Smp
58231990Smpint
59167465SmpNLSWidth(Char c)
60145479Smp{
61145479Smp# ifdef HAVE_WCWIDTH
62167465Smp    int l;
63316957Sdchagin#if INVALID_BYTE != 0
64316957Sdchagin    if ((c & INVALID_BYTE) == INVALID_BYTE)	/* c >= INVALID_BYTE */
65316957Sdchagin#else
66167465Smp    if (c & INVALID_BYTE)
67316957Sdchagin#endif
68145479Smp	return 1;
69231990Smp    l = xwcwidth((wchar_t) c);
70145479Smp    return l >= 0 ? l : 0;
71145479Smp# else
72167465Smp    return iswprint(c) != 0;
73145479Smp# endif
74145479Smp}
75167465Smp
76167465Smpint
77167465SmpNLSStringWidth(const Char *s)
78167465Smp{
79167465Smp    int w = 0, l;
80167465Smp    Char c;
81167465Smp
82167465Smp    while (*s) {
83167465Smp	c = *s++;
84167465Smp#ifdef HAVE_WCWIDTH
85231990Smp	if ((l = xwcwidth((wchar_t) c)) < 0)
86167465Smp		l = 2;
87167465Smp#else
88167465Smp	l = iswprint(c) != 0;
89145479Smp#endif
90167465Smp	w += l;
91167465Smp    }
92167465Smp    return w;
93167465Smp}
94167465Smp#endif
95145479Smp
96145479SmpChar *
97167465SmpNLSChangeCase(const Char *p, int mode)
98145479Smp{
99167465Smp    Char c, *n, c2 = 0;
100167465Smp    const Char *op = p;
101167465Smp
102145479Smp    for (; (c = *p) != 0; p++) {
103145479Smp        if (mode == 0 && Islower(c)) {
104145479Smp	    c2 = Toupper(c);
105145479Smp	    break;
106145479Smp        } else if (mode && Isupper(c)) {
107145479Smp	    c2 = Tolower(c);
108145479Smp	    break;
109145479Smp	}
110145479Smp    }
111145479Smp    if (!*p)
112145479Smp	return 0;
113145479Smp    n = Strsave(op);
114145479Smp    n[p - op] = c2;
115145479Smp    return n;
116145479Smp}
117145479Smp
118145479Smpint
119316957SdchaginNLSClassify(Char c, int nocomb, int drawPrompt)
120145479Smp{
121145479Smp    int w;
122316957Sdchagin#ifndef SHORT_STRINGS
123316957Sdchagin    if ((c & 0x80) != 0)		/* c >= 0x80 */
124145479Smp	return NLSCLASS_ILLEGAL;
125316957Sdchagin#endif
126316957Sdchagin    if (!drawPrompt) {			/* draw command-line */
127316957Sdchagin#if INVALID_BYTE != 0
128316957Sdchagin	if ((c & INVALID_BYTE) == INVALID_BYTE)		/* c >= INVALID_BYTE */
129316957Sdchagin	    return NLSCLASS_ILLEGAL;
130316957Sdchagin	if ((c & INVALID_BYTE) == QUOTE && (c & 0x80) == 0)	/* c >= QUOTE */
131316957Sdchagin	    return 1;
132316957Sdchagin	if (c >= 0x10000000)		/* U+10000000 = FC 90 80 80 80 80 */
133316957Sdchagin	    return NLSCLASS_ILLEGAL5;
134316957Sdchagin	if (c >= 0x1000000)		/*  U+1000000 = F9 80 80 80 80 */
135316957Sdchagin	    return NLSCLASS_ILLEGAL4;
136316957Sdchagin	if (c >= 0x100000)		/*   U+100000 = F4 80 80 80 */
137316957Sdchagin	    return NLSCLASS_ILLEGAL3;
138316957Sdchagin#endif
139316957Sdchagin	if (c >= 0x10000)		/*    U+10000 = F0 90 80 80 */
140316957Sdchagin	    return NLSCLASS_ILLEGAL2;
141316957Sdchagin    }
142167465Smp    if (Iscntrl(c) && (c & CHAR) < 0x100) {
143145479Smp	if (c == '\n')
144145479Smp	    return NLSCLASS_NL;
145145479Smp	if (c == '\t')
146145479Smp	    return NLSCLASS_TAB;
147145479Smp	return NLSCLASS_CTRL;
148145479Smp    }
149316957Sdchagin    w = NLSWidth(c);
150316957Sdchagin    if (drawPrompt) {			/* draw prompt */
151316957Sdchagin	if (w > 0)
152316957Sdchagin	    return w;
153316957Sdchagin	if (w == 0)
154316957Sdchagin	    return 1;
155316957Sdchagin    }
156316957Sdchagin    if ((w > 0 && !(Iscntrl(c) && (c & CHAR) < 0x100)) || (Isprint(c) && !nocomb))
157316957Sdchagin	return w;
158145479Smp    return NLSCLASS_ILLEGAL;
159145479Smp}
160