1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/tc.nls.c,v 3.23 2010/02/12 22:17:20 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
35232633SmpRCSID("$tcsh: tc.nls.c,v 3.23 2010/02/12 22:17:20 christos Exp $")
36145479Smp
37232633Smp
38167465Smp#ifdef WIDE_STRINGS
39232633Smp# ifdef HAVE_WCWIDTH
40232633Smp#  ifdef UTF16_STRINGS
41145479Smpint
42232633Smpxwcwidth (wint_t wchar)
43232633Smp{
44232633Smp  wchar_t ws[2];
45232633Smp
46232633Smp  if (wchar <= 0xffff)
47232633Smp    return wcwidth ((wchar_t) wchar);
48232633Smp  /* UTF-16 systems can't handle these values directly in calls to wcwidth.
49232633Smp     However, they can handle them as surrogate pairs in calls to wcswidth.
50232633Smp     What we do here is to convert UTF-32 values >= 0x10000 into surrogate
51232633Smp     pairs and compute the width by calling wcswidth. */
52232633Smp  wchar -= 0x10000;
53232633Smp  ws[0] = 0xd800 | (wchar >> 10);
54232633Smp  ws[1] = 0xdc00 | (wchar & 0x3ff);
55232633Smp  return wcswidth (ws, 2);
56232633Smp}
57232633Smp#  else
58232633Smp#define xwcwidth wcwidth
59232633Smp#  endif /* !UTF16_STRINGS */
60232633Smp# endif /* HAVE_WCWIDTH */
61232633Smp
62232633Smpint
63167465SmpNLSWidth(Char c)
64145479Smp{
65145479Smp# ifdef HAVE_WCWIDTH
66167465Smp    int l;
67167465Smp    if (c & INVALID_BYTE)
68145479Smp	return 1;
69232633Smp    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
85232633Smp	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
119167465SmpNLSClassify(Char c, int nocomb)
120145479Smp{
121145479Smp    int w;
122167465Smp    if (c & INVALID_BYTE)
123145479Smp	return NLSCLASS_ILLEGAL;
124145479Smp    w = NLSWidth(c);
125167465Smp    if ((w > 0 && !(Iscntrl(c) && (c & CHAR) < 0x100)) || (Isprint(c) && !nocomb))
126145479Smp	return w;
127167465Smp    if (Iscntrl(c) && (c & CHAR) < 0x100) {
128145479Smp	if (c == '\n')
129145479Smp	    return NLSCLASS_NL;
130145479Smp	if (c == '\t')
131145479Smp	    return NLSCLASS_TAB;
132145479Smp	return NLSCLASS_CTRL;
133145479Smp    }
134167465Smp#ifdef WIDE_STRINGS
135145479Smp    if (c >= 0x1000000)
136145479Smp	return NLSCLASS_ILLEGAL4;
137145479Smp    if (c >= 0x10000)
138145479Smp	return NLSCLASS_ILLEGAL3;
139167465Smp#endif
140145479Smp    if (c >= 0x100)
141145479Smp	return NLSCLASS_ILLEGAL2;
142145479Smp    return NLSCLASS_ILLEGAL;
143145479Smp}
144