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