1145479Smp/* 2145479Smp * tc.nls.c: NLS handling 3145479Smp */ 4145479Smp/*- 5145479Smp * Copyright (c) 1980, 1991 The Regents of the University of California. 6145479Smp * All rights reserved. 7145479Smp * 8145479Smp * Redistribution and use in source and binary forms, with or without 9145479Smp * modification, are permitted provided that the following conditions 10145479Smp * are met: 11145479Smp * 1. Redistributions of source code must retain the above copyright 12145479Smp * notice, this list of conditions and the following disclaimer. 13145479Smp * 2. Redistributions in binary form must reproduce the above copyright 14145479Smp * notice, this list of conditions and the following disclaimer in the 15145479Smp * documentation and/or other materials provided with the distribution. 16145479Smp * 3. Neither the name of the University nor the names of its contributors 17145479Smp * may be used to endorse or promote products derived from this software 18145479Smp * without specific prior written permission. 19145479Smp * 20145479Smp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21145479Smp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22145479Smp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23145479Smp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24145479Smp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25145479Smp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26145479Smp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27145479Smp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28145479Smp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29145479Smp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30145479Smp * SUCH DAMAGE. 31145479Smp */ 32145479Smp#include "sh.h" 33145479Smp 34167465Smp#ifdef WIDE_STRINGS 35231990Smp# ifdef HAVE_WCWIDTH 36231990Smp# ifdef UTF16_STRINGS 37145479Smpint 38231990Smpxwcwidth (wint_t wchar) 39231990Smp{ 40231990Smp wchar_t ws[2]; 41231990Smp 42231990Smp if (wchar <= 0xffff) 43231990Smp return wcwidth ((wchar_t) wchar); 44231990Smp /* UTF-16 systems can't handle these values directly in calls to wcwidth. 45231990Smp However, they can handle them as surrogate pairs in calls to wcswidth. 46231990Smp What we do here is to convert UTF-32 values >= 0x10000 into surrogate 47231990Smp pairs and compute the width by calling wcswidth. */ 48231990Smp wchar -= 0x10000; 49231990Smp ws[0] = 0xd800 | (wchar >> 10); 50231990Smp ws[1] = 0xdc00 | (wchar & 0x3ff); 51231990Smp return wcswidth (ws, 2); 52231990Smp} 53231990Smp# else 54231990Smp#define xwcwidth wcwidth 55231990Smp# endif /* !UTF16_STRINGS */ 56231990Smp# endif /* HAVE_WCWIDTH */ 57231990Smp 58231990Smpint 59167465SmpNLSWidth(Char c) 60145479Smp{ 61145479Smp# ifdef HAVE_WCWIDTH 62167465Smp int l; 63316957Sdchagin#if INVALID_BYTE != 0 64316957Sdchagin if ((c & INVALID_BYTE) == INVALID_BYTE) /* c >= INVALID_BYTE */ 65316957Sdchagin#else 66167465Smp if (c & INVALID_BYTE) 67316957Sdchagin#endif 68145479Smp return 1; 69231990Smp 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 85231990Smp 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 119316957SdchaginNLSClassify(Char c, int nocomb, int drawPrompt) 120145479Smp{ 121145479Smp int w; 122316957Sdchagin#ifndef SHORT_STRINGS 123316957Sdchagin if ((c & 0x80) != 0) /* c >= 0x80 */ 124145479Smp return NLSCLASS_ILLEGAL; 125316957Sdchagin#endif 126316957Sdchagin if (!drawPrompt) { /* draw command-line */ 127316957Sdchagin#if INVALID_BYTE != 0 128316957Sdchagin if ((c & INVALID_BYTE) == INVALID_BYTE) /* c >= INVALID_BYTE */ 129316957Sdchagin return NLSCLASS_ILLEGAL; 130316957Sdchagin if ((c & INVALID_BYTE) == QUOTE && (c & 0x80) == 0) /* c >= QUOTE */ 131316957Sdchagin return 1; 132316957Sdchagin if (c >= 0x10000000) /* U+10000000 = FC 90 80 80 80 80 */ 133316957Sdchagin return NLSCLASS_ILLEGAL5; 134316957Sdchagin if (c >= 0x1000000) /* U+1000000 = F9 80 80 80 80 */ 135316957Sdchagin return NLSCLASS_ILLEGAL4; 136316957Sdchagin if (c >= 0x100000) /* U+100000 = F4 80 80 80 */ 137316957Sdchagin return NLSCLASS_ILLEGAL3; 138316957Sdchagin#endif 139316957Sdchagin if (c >= 0x10000) /* U+10000 = F0 90 80 80 */ 140316957Sdchagin return NLSCLASS_ILLEGAL2; 141316957Sdchagin } 142167465Smp if (Iscntrl(c) && (c & CHAR) < 0x100) { 143145479Smp if (c == '\n') 144145479Smp return NLSCLASS_NL; 145145479Smp if (c == '\t') 146145479Smp return NLSCLASS_TAB; 147145479Smp return NLSCLASS_CTRL; 148145479Smp } 149316957Sdchagin w = NLSWidth(c); 150316957Sdchagin if (drawPrompt) { /* draw prompt */ 151316957Sdchagin if (w > 0) 152316957Sdchagin return w; 153316957Sdchagin if (w == 0) 154316957Sdchagin return 1; 155316957Sdchagin } 156316957Sdchagin if ((w > 0 && !(Iscntrl(c) && (c & CHAR) < 0x100)) || (Isprint(c) && !nocomb)) 157316957Sdchagin return w; 158145479Smp return NLSCLASS_ILLEGAL; 159145479Smp} 160