tc.nls.c revision 316957
1316957Sdchagin/* $Header: /p/tcsh/cvsroot/tcsh/tc.nls.c,v 3.27 2016/07/17 15:02:44 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
35316957SdchaginRCSID("$tcsh: tc.nls.c,v 3.27 2016/07/17 15:02:44 christos Exp $")
36145479Smp
37231990Smp
38167465Smp#ifdef WIDE_STRINGS
39231990Smp# ifdef HAVE_WCWIDTH
40231990Smp#  ifdef UTF16_STRINGS
41145479Smpint
42231990Smpxwcwidth (wint_t wchar)
43231990Smp{
44231990Smp  wchar_t ws[2];
45231990Smp
46231990Smp  if (wchar <= 0xffff)
47231990Smp    return wcwidth ((wchar_t) wchar);
48231990Smp  /* UTF-16 systems can't handle these values directly in calls to wcwidth.
49231990Smp     However, they can handle them as surrogate pairs in calls to wcswidth.
50231990Smp     What we do here is to convert UTF-32 values >= 0x10000 into surrogate
51231990Smp     pairs and compute the width by calling wcswidth. */
52231990Smp  wchar -= 0x10000;
53231990Smp  ws[0] = 0xd800 | (wchar >> 10);
54231990Smp  ws[1] = 0xdc00 | (wchar & 0x3ff);
55231990Smp  return wcswidth (ws, 2);
56231990Smp}
57231990Smp#  else
58231990Smp#define xwcwidth wcwidth
59231990Smp#  endif /* !UTF16_STRINGS */
60231990Smp# endif /* HAVE_WCWIDTH */
61231990Smp
62231990Smpint
63167465SmpNLSWidth(Char c)
64145479Smp{
65145479Smp# ifdef HAVE_WCWIDTH
66167465Smp    int l;
67316957Sdchagin#if INVALID_BYTE != 0
68316957Sdchagin    if ((c & INVALID_BYTE) == INVALID_BYTE)	/* c >= INVALID_BYTE */
69316957Sdchagin#else
70167465Smp    if (c & INVALID_BYTE)
71316957Sdchagin#endif
72145479Smp	return 1;
73231990Smp    l = xwcwidth((wchar_t) c);
74145479Smp    return l >= 0 ? l : 0;
75145479Smp# else
76167465Smp    return iswprint(c) != 0;
77145479Smp# endif
78145479Smp}
79167465Smp
80167465Smpint
81167465SmpNLSStringWidth(const Char *s)
82167465Smp{
83167465Smp    int w = 0, l;
84167465Smp    Char c;
85167465Smp
86167465Smp    while (*s) {
87167465Smp	c = *s++;
88167465Smp#ifdef HAVE_WCWIDTH
89231990Smp	if ((l = xwcwidth((wchar_t) c)) < 0)
90167465Smp		l = 2;
91167465Smp#else
92167465Smp	l = iswprint(c) != 0;
93145479Smp#endif
94167465Smp	w += l;
95167465Smp    }
96167465Smp    return w;
97167465Smp}
98167465Smp#endif
99145479Smp
100145479SmpChar *
101167465SmpNLSChangeCase(const Char *p, int mode)
102145479Smp{
103167465Smp    Char c, *n, c2 = 0;
104167465Smp    const Char *op = p;
105167465Smp
106145479Smp    for (; (c = *p) != 0; p++) {
107145479Smp        if (mode == 0 && Islower(c)) {
108145479Smp	    c2 = Toupper(c);
109145479Smp	    break;
110145479Smp        } else if (mode && Isupper(c)) {
111145479Smp	    c2 = Tolower(c);
112145479Smp	    break;
113145479Smp	}
114145479Smp    }
115145479Smp    if (!*p)
116145479Smp	return 0;
117145479Smp    n = Strsave(op);
118145479Smp    n[p - op] = c2;
119145479Smp    return n;
120145479Smp}
121145479Smp
122145479Smpint
123316957SdchaginNLSClassify(Char c, int nocomb, int drawPrompt)
124145479Smp{
125145479Smp    int w;
126316957Sdchagin#ifndef SHORT_STRINGS
127316957Sdchagin    if ((c & 0x80) != 0)		/* c >= 0x80 */
128145479Smp	return NLSCLASS_ILLEGAL;
129316957Sdchagin#endif
130316957Sdchagin    if (!drawPrompt) {			/* draw command-line */
131316957Sdchagin#if INVALID_BYTE != 0
132316957Sdchagin	if ((c & INVALID_BYTE) == INVALID_BYTE)		/* c >= INVALID_BYTE */
133316957Sdchagin	    return NLSCLASS_ILLEGAL;
134316957Sdchagin	if ((c & INVALID_BYTE) == QUOTE && (c & 0x80) == 0)	/* c >= QUOTE */
135316957Sdchagin	    return 1;
136316957Sdchagin	if (c >= 0x10000000)		/* U+10000000 = FC 90 80 80 80 80 */
137316957Sdchagin	    return NLSCLASS_ILLEGAL5;
138316957Sdchagin	if (c >= 0x1000000)		/*  U+1000000 = F9 80 80 80 80 */
139316957Sdchagin	    return NLSCLASS_ILLEGAL4;
140316957Sdchagin	if (c >= 0x100000)		/*   U+100000 = F4 80 80 80 */
141316957Sdchagin	    return NLSCLASS_ILLEGAL3;
142316957Sdchagin#endif
143316957Sdchagin	if (c >= 0x10000)		/*    U+10000 = F0 90 80 80 */
144316957Sdchagin	    return NLSCLASS_ILLEGAL2;
145316957Sdchagin    }
146167465Smp    if (Iscntrl(c) && (c & CHAR) < 0x100) {
147145479Smp	if (c == '\n')
148145479Smp	    return NLSCLASS_NL;
149145479Smp	if (c == '\t')
150145479Smp	    return NLSCLASS_TAB;
151145479Smp	return NLSCLASS_CTRL;
152145479Smp    }
153316957Sdchagin    w = NLSWidth(c);
154316957Sdchagin    if (drawPrompt) {			/* draw prompt */
155316957Sdchagin	if (w > 0)
156316957Sdchagin	    return w;
157316957Sdchagin	if (w == 0)
158316957Sdchagin	    return 1;
159316957Sdchagin    }
160316957Sdchagin    if ((w > 0 && !(Iscntrl(c) && (c & CHAR) < 0x100)) || (Isprint(c) && !nocomb))
161316957Sdchagin	return w;
162145479Smp    return NLSCLASS_ILLEGAL;
163145479Smp}
164