tc.nls.c revision 145479
1/* $Header: /src/pub/tcsh/tc.nls.c,v 3.6 2005/02/15 21:09:02 christos Exp $ */
2/*
3 * tc.nls.c: NLS handling
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33#include "sh.h"
34
35RCSID("$Id: tc.nls.c,v 3.6 2005/02/15 21:09:02 christos Exp $")
36
37#ifdef SHORT_STRINGS
38int
39NLSWidth(c)
40    NLSChar c;
41{
42# ifdef HAVE_WCWIDTH
43    int l;
44    if (c & NLS_ILLEGAL)
45	return 1;
46    l = wcwidth(c);
47    return l >= 0 ? l : 0;
48# else
49    return c != 0;
50# endif
51}
52#endif
53
54#if defined (WIDE_STRINGS) || !defined (SHORT_STRINGS)
55Char *
56NLSChangeCase(Char *p, int mode)
57{
58    Char c, *op = p, *n, c2 = 0;
59    for (; (c = *p) != 0; p++) {
60        if (mode == 0 && Islower(c)) {
61	    c2 = Toupper(c);
62	    break;
63        } else if (mode && Isupper(c)) {
64	    c2 = Tolower(c);
65	    break;
66	}
67    }
68    if (!*p)
69	return 0;
70    n = Strsave(op);
71    n[p - op] = c2;
72    return n;
73}
74
75int
76NLSExtend(Char *from, int max, int num)
77{
78    (void)from;
79    num = abs (num);
80    if (num > max)
81	num = max;
82    return num;
83}
84#endif
85
86#ifdef WIDE_STRINGS
87
88int
89NLSStringWidth(Char *s)
90{
91    int w = 0;
92    while (*s)
93	w += wcwidth(*s++);
94    return w;
95}
96
97#elif defined (SHORT_STRINGS)
98
99int
100NLSFrom(const Char *p, size_t l, NLSChar *cp)
101{
102    size_t i;
103    int len;
104    wchar_t c;
105    char b[MB_LEN_MAX];
106
107    if (l == NLSZEROT) {
108        for (i = 0; i < MB_CUR_MAX && *p; i++)
109	    b[i] = p[i] & CHAR;
110    } else {
111        for (i = 0; i < MB_CUR_MAX && i < l; i++)
112	    b[i] = p[i] & CHAR;
113    }
114    mbtowc(0, 0, 0);
115    len = rt_mbtowc(&c, b, i);
116    if (len <= 0) {
117	if (cp)
118	  *cp = *p ? *p | NLS_ILLEGAL : 0;
119        return 1;
120    }
121    if (cp)
122        *cp = (int)c;
123    return len;
124}
125
126int
127NLSFinished(Char *p, size_t l, eChar extra)
128{
129    size_t i, r;
130    wchar_t c;
131    char b[MB_LEN_MAX + 1], back[MB_LEN_MAX];
132    mbstate_t state;
133    for (i = 0; i < MB_CUR_MAX && i < l; i++)
134	b[i] = p[i];
135    if (extra != CHAR_ERR)
136        b[i++] = extra;
137    memset(&state, 0, sizeof(state));
138    r = mbrtowc((wchar_t *)&c, b, i, (mbstate_t *)&state);
139    if (r == (size_t)-2)
140	return 0;
141    if (r == (size_t)-1 || (size_t)wctomb(back, c) != r ||
142	memcmp(b, back, r) != 0)
143	return -1;
144    return r == i ? 1 : 2;
145}
146
147int
148NLSChars(Char *s)
149{
150    int l;
151    for (l = 0; *s; l++)
152        s += NLSSize(s, -1);
153    return l;
154}
155
156int
157NLSStringWidth(Char *s)
158{
159    int w = 0;
160    NLSChar c;
161    while (*s) {
162        s += NLSFrom(s, NLSZEROT, &c);
163	w += NLSWidth(c);
164    }
165    return w;
166}
167
168int
169NLSTo(Char *p, NLSChar c)
170{
171    char b[MB_LEN_MAX];
172    int i, j;
173
174    if (c & NLS_ILLEGAL) {
175        if (p)
176	    *p = c;
177	return 1;
178    }
179    i = wctomb(b, (wchar_t)c);
180    if (i == -1)
181        return 0;
182    if (p)
183        for (j = 0; j < i; j++)
184            p[j] = b[j];
185    return i;
186}
187
188
189int
190NLSExtend(Char *from, int max, int num)
191{
192    int l, n, i;
193    Char *p;
194
195    if (num == 0)
196	return 0;
197    if (num > 0) {
198	n = 0;
199	while (num > 0 && max > 0) {
200	    l = NLSSize(from, max);
201	    n += l;
202	    from += l;
203	    max -= l;
204	    num--;
205	}
206	return n;
207    }
208    from -= max;
209    p = from;
210    i = max;
211    n = 0;
212    while (i > 0) {
213	l = NLSSize(p, i);
214	p += l;
215        i -= l;
216	n++;
217    }
218    if (n >= -num)
219	n += num;
220    else
221	n = 0;
222    i = max;
223    while (n > 0) {
224	l = NLSSize(from, max);
225	from += l;
226	max -= l;
227	i -= l;
228	n--;
229    }
230    return i;
231}
232
233void
234NLSQuote(Char *cp)
235{
236    int l;
237    while (*cp) {
238	l = NLSSize(cp, -1);
239	cp++;
240	while (l-- > 1)
241	    *cp++ |= QUOTE;
242    }
243}
244
245Char *
246NLSChangeCase(Char *p, int mode)
247{
248    Char *n, *op = p;
249    NLSChar c, c2 = 0;
250    int l, l2;
251
252    while (*p) {
253       l = NLSFrom(p, NLSZEROT, &c);
254       if (mode == 0 && iswlower((wint_t)c)) {
255	   c2 = (int)towupper((wint_t)c);
256	   break;
257       } else if (mode && iswupper((wint_t)c)) {
258	   c2 = (int)towlower((wint_t)c);
259	   break;
260       }
261	p += l;
262    }
263    if (!*p)
264	return 0;
265    l2 = NLSTo((Char *)0, c2);
266    n = (Char *)xmalloc((size_t)((op - p + l2 + Strlen(p + l) + 1) * sizeof(Char)));
267    if (p != op)
268	memcpy(n, op, (p - op) * sizeof(Char));
269    NLSTo(n + (p - op), c2);
270    memcpy(n + (p - op + l2), p + l, (Strlen(p + l) + 1) * sizeof(Char));
271    return n;
272}
273#endif
274
275int
276NLSClassify(c, nocomb)
277    NLSChar c;
278    int nocomb;
279{
280    int w;
281    if (c & NLS_ILLEGAL)
282	return NLSCLASS_ILLEGAL;
283    w = NLSWidth(c);
284    if (w > 0 || (Iswprint(c) && !nocomb))
285	return w;
286    if (Iswcntrl(c) && c < 0x100) {
287	if (c == '\n')
288	    return NLSCLASS_NL;
289	if (c == '\t')
290	    return NLSCLASS_TAB;
291#ifndef ASCII
292	if (!Isupper(_toebcdic[_toascii[c]|0100]) && !strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]))
293	    return NLSCLASS_ILLEGAL;
294#endif
295	return NLSCLASS_CTRL;
296    }
297    if (c >= 0x1000000)
298	return NLSCLASS_ILLEGAL4;
299    if (c >= 0x10000)
300	return NLSCLASS_ILLEGAL3;
301    if (c >= 0x100)
302	return NLSCLASS_ILLEGAL2;
303    return NLSCLASS_ILLEGAL;
304}
305