From 48d6402e65f87427d83a516e5296d677735f0022 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 3 Aug 2006 15:37:49 +0000 Subject: rationalise mb<->wc conversions to use restartable form --- ChangeLog | 7 +++++- Src/Zle/complist.c | 5 +++- Src/Zle/zle.h | 4 ---- Src/Zle/zle_tricky.c | 14 ++++++++---- Src/Zle/zle_utils.c | 6 ++++- Src/prompt.c | 1 + Src/utils.c | 64 +++++++++++++++++++++++++--------------------------- 7 files changed, 56 insertions(+), 45 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5776e62d4..41371caba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2006-08-03 Peter Stephenson + * 22581: Src/prompt.c, Src/utils.c, Src/Zle/complist.c, + Src/Zle/zle.h, Src/Zle/zle_tricky.c, Src/Zle/zle_utils.c: + rationalise multibyte conversions to and from wide characters + to use restartable form. + * unposted: Completion/Unix/Command/_subversion: import directory is optional, so complete URLs also on first argument. @@ -58,7 +63,7 @@ accept-and-menu-complete, perhaps. * 22562: Src/glob.c, Test/D07multibyte.ztst: make ${...#...} etc. - understand multibyte characters. + understand multibyte characters. 2006-07-29 Barton E. Schaefer diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c index 0bea231c5..8c6937b4a 100644 --- a/Src/Zle/complist.c +++ b/Src/Zle/complist.c @@ -588,6 +588,7 @@ clnicezputs(Listcols colors, char *s, int ml) if (colors) initiscol(colors); + mb_metacharinit(); while (umleft > 0) { size_t cnt = eol ? MB_INVALID : mbrtowc(&cc, uptr, umleft, &mbs); @@ -1964,7 +1965,9 @@ msearch(Cmatch **ptr, int ins, int back, int rep, int *wrapp) #ifdef MULTIBYTE_SUPPORT if (lastchar_wide_valid) { - int len = wctomb(s, lastchar_wide); + mbstate_t mbs; + memset(&mbs, 0, sizeof(mbs)); + int len = wcrtomb(s, lastchar_wide, &mbs); if (len < 0) len = 0; s[len] = '\0'; diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index f56960734..200804c7d 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -71,8 +71,6 @@ typedef wint_t ZLE_INT_T; #define ZC_tolower towlower #define ZC_toupper towupper -#define ZC_nicechar(c) wcs_nicechar(c, NULL, NULL) - #define LASTFULLCHAR lastchar_wide #else /* Not MULTIBYTE_SUPPORT: old single-byte code */ @@ -100,8 +98,6 @@ typedef int ZLE_INT_T; */ #define ZMB_nicewidth niceztrlen -#define ZC_nicechar nicechar - #ifdef __GNUC__ static inline size_t ZS_strlen(ZLE_STRING_T s) { return strlen((char*)s); } diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index fb0ebad2a..4b7d3126d 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -2464,16 +2464,20 @@ magicspace(char **args) ZLE_STRING_T bangq; ZLE_CHAR_T zlebangchar[1]; int ret; +#ifdef MULTIBYTE_SUPPORT + mbstate_t mbs; +#endif + fixmagicspace(); #ifdef MULTIBYTE_SUPPORT /* - * TODO: bangchar should really be a multibyte string representing - * a single character, since there's no fundamental reason why - * it shouldn't be a Unicode character. In practice this is - * very minor, however. + * Use mbrtowc() here for consistency and to ensure the + * state is initialised properly. bangchar is unsigned char, + * but must be ASCII, so we simply cast the pointer. */ - if (mbtowc(zlebangchar, (char *)&bangchar, 1) < 0) + memset(&mbs, 0, sizeof(mbs)); + if (mbrtowc(zlebangchar, (char *)&bangchar, 1, &mbs) < 0) return selfinsert(args); #else zlebangchar[0] = bangchar; diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index cce162fa0..6275e74d3 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -135,17 +135,20 @@ zlelineasstring(ZLE_STRING_T instr, int inll, int incs, int *outllp, char *s; int i, j; size_t mb_len = 0; + mbstate_t mbs; s = zalloc(inll * MB_CUR_MAX + 1); outcs = 0; + memset(&mbs, 0, sizeof(mbs)); for (i=0; i < inll; i++, incs--) { if (incs == 0) outcs = mb_len; - j = wctomb(s + mb_len, instr[i]); + j = wcrtomb(s + mb_len, instr[i], &mbs); if (j == -1) { /* invalid char; what to do? */ s[mb_len++] = ZWC('?'); + memset(&mbs, 0, sizeof(mbs)); } else { mb_len += j; } @@ -780,6 +783,7 @@ showmsg(char const *msg) p = unmetafy(umsg, &ulen); memset(&mbs, 0, sizeof mbs); + mb_metacharinit(); while (ulen > 0) { char const *n; if (*p == '\n') { diff --git a/Src/prompt.c b/Src/prompt.c index facf777f0..21dff16e0 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -771,6 +771,7 @@ stradd(char *d) /* FALL THROUGH */ default: /* Take full wide character in one go */ + mb_metacharinit(); pc = wcs_nicechar(cc, NULL, NULL); break; } diff --git a/Src/utils.c b/Src/utils.c index a81c4ed04..21b722f6a 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -279,6 +279,7 @@ zerrmsg(const char *fmt, va_list ap) case 'c': num = va_arg(ap, int); #ifdef MULTIBYTE_SUPPORT + mb_metacharinit(); zputs(wcs_nicechar(num, NULL, NULL), stderr); #else zputs(nicechar(num), stderr); @@ -402,6 +403,20 @@ nicechar(int c) /**/ #ifdef MULTIBYTE_SUPPORT +static mbstate_t mb_shiftstate; + +/* + * Initialise multibyte state: called before a sequence of + * wcs_nicechar() or mb_metacharlenconv(). + */ + +/**/ +mod_export void +mb_metacharinit(void) +{ + memset(&mb_shiftstate, 0, sizeof(mb_shiftstate)); +} + /* * The number of bytes we need to allocate for a "nice" representation * of a multibyte character. @@ -430,6 +445,9 @@ nicechar(int c) * Either the initial ASCII part or the wide character part may be empty * (but not both). (Note the complication that the wide character * part may contain metafied characters.) + * + * The caller needs to call mb_metacharinit() before the first call, to + * set up the multibyte shift state for a range of characters. */ /**/ @@ -475,8 +493,11 @@ wcs_nicechar(wchar_t c, size_t *widthp, char **swidep) } } - if (ret == -1 || - (ret = wctomb(mbstr, c)) == -1) { + if (ret != -1) + ret = wcrtomb(mbstr, c, &mb_shiftstate); + + if (ret == -1) { + memset(&mb_shiftstate, 0, sizeof(mb_shiftstate)); /* * Can't or don't want to convert character: use UCS-2 or * UCS-4 code in print escape format. @@ -513,18 +534,6 @@ wcs_nicechar(wchar_t c, size_t *widthp, char **swidep) /**/ #endif /* MULTIBYTE_SUPPORT */ - -/* Output a string's visible representation. */ - -#if 0 /**/ -void -nicefputs(char *s, FILE *f) -{ - for (; *s; s++) - zputs(nicechar(*s), f); -} -#endif - /* get a symlink-free pathname for s relative to PWD */ /**/ @@ -699,7 +708,7 @@ get_username(void) #ifdef HAVE_GETPWUID struct passwd *pswd; uid_t current_uid; - + current_uid = getuid(); if (current_uid != cached_uid) { cached_uid = current_uid; @@ -900,12 +909,12 @@ dircmp(char *s, char *t) mod_export LinkList prepromptfns; /* the last time we checked mail */ - + /**/ time_t lastmailcheck; - + /* the last time we checked the people in the WATCH variable */ - + /**/ time_t lastwatch; @@ -2818,6 +2827,7 @@ mod_export int wcsitype(wchar_t c, int itype) { int len; + mbstate_t mbs; VARARR(char, outstr, MB_CUR_MAX); if (!isset(MULTIBYTE)) @@ -2830,7 +2840,8 @@ wcsitype(wchar_t c, int itype) * If it doesn't, use iswalnum on the original character. * If that fails, resort to the appropriate wide character array. */ - len = wctomb(outstr, c); + memset(&mbs, 0, sizeof(mbs)); + len = wcrtomb(outstr, c, &mbs); if (len == 0) { /* NULL is special */ @@ -3725,6 +3736,7 @@ mb_niceformat(const char *s, FILE *stream, char **outstrp, int heap) ptr = unmetafy(ums, ¨en); memset(&mbs, 0, sizeof mbs); + mb_metacharinit(); while (umlen > 0) { size_t cnt = eol ? MB_INVALID : mbrtowc(&c, ptr, umlen, &mbs); @@ -3853,20 +3865,6 @@ mb_width(const char *s) return width; } -static mbstate_t mb_shiftstate; - -/* - * Initialise multibyte state: called before a sequence of - * mb_metacharlenconv(). - */ - -/**/ -void -mb_metacharinit(void) -{ - memset(&mb_shiftstate, 0, sizeof(mb_shiftstate)); -} - /* * Length of metafied string s which contains the next multibyte * character; single (possibly metafied) character if string is not null -- cgit 1.4.1