tc.nls.c revision 145479
1145479Smp/* $Header: /src/pub/tcsh/tc.nls.c,v 3.6 2005/02/15 21:09:02 christos Exp $ */
2145479Smp/*
3145479Smp * tc.nls.c: NLS handling
4145479Smp */
5145479Smp/*-
6145479Smp * Copyright (c) 1980, 1991 The Regents of the University of California.
7145479Smp * All rights reserved.
8145479Smp *
9145479Smp * Redistribution and use in source and binary forms, with or without
10145479Smp * modification, are permitted provided that the following conditions
11145479Smp * are met:
12145479Smp * 1. Redistributions of source code must retain the above copyright
13145479Smp *    notice, this list of conditions and the following disclaimer.
14145479Smp * 2. Redistributions in binary form must reproduce the above copyright
15145479Smp *    notice, this list of conditions and the following disclaimer in the
16145479Smp *    documentation and/or other materials provided with the distribution.
17145479Smp * 3. Neither the name of the University nor the names of its contributors
18145479Smp *    may be used to endorse or promote products derived from this software
19145479Smp *    without specific prior written permission.
20145479Smp *
21145479Smp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22145479Smp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23145479Smp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24145479Smp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25145479Smp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26145479Smp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27145479Smp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28145479Smp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29145479Smp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30145479Smp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31145479Smp * SUCH DAMAGE.
32145479Smp */
33145479Smp#include "sh.h"
34145479Smp
35145479SmpRCSID("$Id: tc.nls.c,v 3.6 2005/02/15 21:09:02 christos Exp $")
36145479Smp
37145479Smp#ifdef SHORT_STRINGS
38145479Smpint
39145479SmpNLSWidth(c)
40145479Smp    NLSChar c;
41145479Smp{
42145479Smp# ifdef HAVE_WCWIDTH
43145479Smp    int l;
44145479Smp    if (c & NLS_ILLEGAL)
45145479Smp	return 1;
46145479Smp    l = wcwidth(c);
47145479Smp    return l >= 0 ? l : 0;
48145479Smp# else
49145479Smp    return c != 0;
50145479Smp# endif
51145479Smp}
52145479Smp#endif
53145479Smp
54145479Smp#if defined (WIDE_STRINGS) || !defined (SHORT_STRINGS)
55145479SmpChar *
56145479SmpNLSChangeCase(Char *p, int mode)
57145479Smp{
58145479Smp    Char c, *op = p, *n, c2 = 0;
59145479Smp    for (; (c = *p) != 0; p++) {
60145479Smp        if (mode == 0 && Islower(c)) {
61145479Smp	    c2 = Toupper(c);
62145479Smp	    break;
63145479Smp        } else if (mode && Isupper(c)) {
64145479Smp	    c2 = Tolower(c);
65145479Smp	    break;
66145479Smp	}
67145479Smp    }
68145479Smp    if (!*p)
69145479Smp	return 0;
70145479Smp    n = Strsave(op);
71145479Smp    n[p - op] = c2;
72145479Smp    return n;
73145479Smp}
74145479Smp
75145479Smpint
76145479SmpNLSExtend(Char *from, int max, int num)
77145479Smp{
78145479Smp    (void)from;
79145479Smp    num = abs (num);
80145479Smp    if (num > max)
81145479Smp	num = max;
82145479Smp    return num;
83145479Smp}
84145479Smp#endif
85145479Smp
86145479Smp#ifdef WIDE_STRINGS
87145479Smp
88145479Smpint
89145479SmpNLSStringWidth(Char *s)
90145479Smp{
91145479Smp    int w = 0;
92145479Smp    while (*s)
93145479Smp	w += wcwidth(*s++);
94145479Smp    return w;
95145479Smp}
96145479Smp
97145479Smp#elif defined (SHORT_STRINGS)
98145479Smp
99145479Smpint
100145479SmpNLSFrom(const Char *p, size_t l, NLSChar *cp)
101145479Smp{
102145479Smp    size_t i;
103145479Smp    int len;
104145479Smp    wchar_t c;
105145479Smp    char b[MB_LEN_MAX];
106145479Smp
107145479Smp    if (l == NLSZEROT) {
108145479Smp        for (i = 0; i < MB_CUR_MAX && *p; i++)
109145479Smp	    b[i] = p[i] & CHAR;
110145479Smp    } else {
111145479Smp        for (i = 0; i < MB_CUR_MAX && i < l; i++)
112145479Smp	    b[i] = p[i] & CHAR;
113145479Smp    }
114145479Smp    mbtowc(0, 0, 0);
115145479Smp    len = rt_mbtowc(&c, b, i);
116145479Smp    if (len <= 0) {
117145479Smp	if (cp)
118145479Smp	  *cp = *p ? *p | NLS_ILLEGAL : 0;
119145479Smp        return 1;
120145479Smp    }
121145479Smp    if (cp)
122145479Smp        *cp = (int)c;
123145479Smp    return len;
124145479Smp}
125145479Smp
126145479Smpint
127145479SmpNLSFinished(Char *p, size_t l, eChar extra)
128145479Smp{
129145479Smp    size_t i, r;
130145479Smp    wchar_t c;
131145479Smp    char b[MB_LEN_MAX + 1], back[MB_LEN_MAX];
132145479Smp    mbstate_t state;
133145479Smp    for (i = 0; i < MB_CUR_MAX && i < l; i++)
134145479Smp	b[i] = p[i];
135145479Smp    if (extra != CHAR_ERR)
136145479Smp        b[i++] = extra;
137145479Smp    memset(&state, 0, sizeof(state));
138145479Smp    r = mbrtowc((wchar_t *)&c, b, i, (mbstate_t *)&state);
139145479Smp    if (r == (size_t)-2)
140145479Smp	return 0;
141145479Smp    if (r == (size_t)-1 || (size_t)wctomb(back, c) != r ||
142145479Smp	memcmp(b, back, r) != 0)
143145479Smp	return -1;
144145479Smp    return r == i ? 1 : 2;
145145479Smp}
146145479Smp
147145479Smpint
148145479SmpNLSChars(Char *s)
149145479Smp{
150145479Smp    int l;
151145479Smp    for (l = 0; *s; l++)
152145479Smp        s += NLSSize(s, -1);
153145479Smp    return l;
154145479Smp}
155145479Smp
156145479Smpint
157145479SmpNLSStringWidth(Char *s)
158145479Smp{
159145479Smp    int w = 0;
160145479Smp    NLSChar c;
161145479Smp    while (*s) {
162145479Smp        s += NLSFrom(s, NLSZEROT, &c);
163145479Smp	w += NLSWidth(c);
164145479Smp    }
165145479Smp    return w;
166145479Smp}
167145479Smp
168145479Smpint
169145479SmpNLSTo(Char *p, NLSChar c)
170145479Smp{
171145479Smp    char b[MB_LEN_MAX];
172145479Smp    int i, j;
173145479Smp
174145479Smp    if (c & NLS_ILLEGAL) {
175145479Smp        if (p)
176145479Smp	    *p = c;
177145479Smp	return 1;
178145479Smp    }
179145479Smp    i = wctomb(b, (wchar_t)c);
180145479Smp    if (i == -1)
181145479Smp        return 0;
182145479Smp    if (p)
183145479Smp        for (j = 0; j < i; j++)
184145479Smp            p[j] = b[j];
185145479Smp    return i;
186145479Smp}
187145479Smp
188145479Smp
189145479Smpint
190145479SmpNLSExtend(Char *from, int max, int num)
191145479Smp{
192145479Smp    int l, n, i;
193145479Smp    Char *p;
194145479Smp
195145479Smp    if (num == 0)
196145479Smp	return 0;
197145479Smp    if (num > 0) {
198145479Smp	n = 0;
199145479Smp	while (num > 0 && max > 0) {
200145479Smp	    l = NLSSize(from, max);
201145479Smp	    n += l;
202145479Smp	    from += l;
203145479Smp	    max -= l;
204145479Smp	    num--;
205145479Smp	}
206145479Smp	return n;
207145479Smp    }
208145479Smp    from -= max;
209145479Smp    p = from;
210145479Smp    i = max;
211145479Smp    n = 0;
212145479Smp    while (i > 0) {
213145479Smp	l = NLSSize(p, i);
214145479Smp	p += l;
215145479Smp        i -= l;
216145479Smp	n++;
217145479Smp    }
218145479Smp    if (n >= -num)
219145479Smp	n += num;
220145479Smp    else
221145479Smp	n = 0;
222145479Smp    i = max;
223145479Smp    while (n > 0) {
224145479Smp	l = NLSSize(from, max);
225145479Smp	from += l;
226145479Smp	max -= l;
227145479Smp	i -= l;
228145479Smp	n--;
229145479Smp    }
230145479Smp    return i;
231145479Smp}
232145479Smp
233145479Smpvoid
234145479SmpNLSQuote(Char *cp)
235145479Smp{
236145479Smp    int l;
237145479Smp    while (*cp) {
238145479Smp	l = NLSSize(cp, -1);
239145479Smp	cp++;
240145479Smp	while (l-- > 1)
241145479Smp	    *cp++ |= QUOTE;
242145479Smp    }
243145479Smp}
244145479Smp
245145479SmpChar *
246145479SmpNLSChangeCase(Char *p, int mode)
247145479Smp{
248145479Smp    Char *n, *op = p;
249145479Smp    NLSChar c, c2 = 0;
250145479Smp    int l, l2;
251145479Smp
252145479Smp    while (*p) {
253145479Smp       l = NLSFrom(p, NLSZEROT, &c);
254145479Smp       if (mode == 0 && iswlower((wint_t)c)) {
255145479Smp	   c2 = (int)towupper((wint_t)c);
256145479Smp	   break;
257145479Smp       } else if (mode && iswupper((wint_t)c)) {
258145479Smp	   c2 = (int)towlower((wint_t)c);
259145479Smp	   break;
260145479Smp       }
261145479Smp	p += l;
262145479Smp    }
263145479Smp    if (!*p)
264145479Smp	return 0;
265145479Smp    l2 = NLSTo((Char *)0, c2);
266145479Smp    n = (Char *)xmalloc((size_t)((op - p + l2 + Strlen(p + l) + 1) * sizeof(Char)));
267145479Smp    if (p != op)
268145479Smp	memcpy(n, op, (p - op) * sizeof(Char));
269145479Smp    NLSTo(n + (p - op), c2);
270145479Smp    memcpy(n + (p - op + l2), p + l, (Strlen(p + l) + 1) * sizeof(Char));
271145479Smp    return n;
272145479Smp}
273145479Smp#endif
274145479Smp
275145479Smpint
276145479SmpNLSClassify(c, nocomb)
277145479Smp    NLSChar c;
278145479Smp    int nocomb;
279145479Smp{
280145479Smp    int w;
281145479Smp    if (c & NLS_ILLEGAL)
282145479Smp	return NLSCLASS_ILLEGAL;
283145479Smp    w = NLSWidth(c);
284145479Smp    if (w > 0 || (Iswprint(c) && !nocomb))
285145479Smp	return w;
286145479Smp    if (Iswcntrl(c) && c < 0x100) {
287145479Smp	if (c == '\n')
288145479Smp	    return NLSCLASS_NL;
289145479Smp	if (c == '\t')
290145479Smp	    return NLSCLASS_TAB;
291145479Smp#ifndef ASCII
292145479Smp	if (!Isupper(_toebcdic[_toascii[c]|0100]) && !strchr("@[\\]^_", _toebcdic[_toascii[c]|0100]))
293145479Smp	    return NLSCLASS_ILLEGAL;
294145479Smp#endif
295145479Smp	return NLSCLASS_CTRL;
296145479Smp    }
297145479Smp    if (c >= 0x1000000)
298145479Smp	return NLSCLASS_ILLEGAL4;
299145479Smp    if (c >= 0x10000)
300145479Smp	return NLSCLASS_ILLEGAL3;
301145479Smp    if (c >= 0x100)
302145479Smp	return NLSCLASS_ILLEGAL2;
303145479Smp    return NLSCLASS_ILLEGAL;
304145479Smp}
305