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