diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-01-26 22:51:56 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-01-26 22:51:56 +0100 |
commit | cc5b22b3bfdc0e9e835cf7871166badda31447bd (patch) | |
tree | 11e117ab82deca899a492b823dd0b0cb1c0ed37b /src/misc2.c | |
parent | 65c836e6004647196ae0bc18e409a9e7b79207c0 (diff) | |
download | vim-git-cc5b22b3bfdc0e9e835cf7871166badda31447bd.tar.gz |
patch 8.0.0243: tolower() does not work if the byte count changesv8.0.0243
Problem: When making a character lower case with tolower() changes the byte
cound, it is not made lower case.
Solution: Add strlow_save(). (Dominique Pelle, closes #1406)
Diffstat (limited to 'src/misc2.c')
-rw-r--r-- | src/misc2.c | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/src/misc2.c b/src/misc2.c index dd0e69464..9c39d4039 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -1602,7 +1602,10 @@ strup_save(char_u *orig) { s = alloc((unsigned)STRLEN(res) + 1 + newl - l); if (s == NULL) - break; + { + vim_free(res); + return NULL; + } mch_memmove(s, res, p - res); STRCPY(s + (p - res) + newl, p + l); p = s + (p - res); @@ -1625,6 +1628,69 @@ strup_save(char_u *orig) return res; } + +/* + * Make string "s" all lower-case and return it in allocated memory. + * Handles multi-byte characters as well as possible. + * Returns NULL when out of memory. + */ + char_u * +strlow_save(char_u *orig) +{ + char_u *p; + char_u *res; + + res = p = vim_strsave(orig); + + if (res != NULL) + while (*p != NUL) + { +# ifdef FEAT_MBYTE + int l; + + if (enc_utf8) + { + int c, lc; + int newl; + char_u *s; + + c = utf_ptr2char(p); + lc = utf_tolower(c); + + /* Reallocate string when byte count changes. This is rare, + * thus it's OK to do another malloc()/free(). */ + l = utf_ptr2len(p); + newl = utf_char2len(lc); + if (newl != l) + { + s = alloc((unsigned)STRLEN(res) + 1 + newl - l); + if (s == NULL) + { + vim_free(res); + return NULL; + } + mch_memmove(s, res, p - res); + STRCPY(s + (p - res) + newl, p + l); + p = s + (p - res); + vim_free(res); + res = s; + } + + utf_char2bytes(lc, p); + p += newl; + } + else if (has_mbyte && (l = (*mb_ptr2len)(p)) > 1) + p += l; /* skip multi-byte character */ + else +# endif + { + *p = TOLOWER_LOC(*p); /* note that tolower() can be a macro */ + p++; + } + } + + return res; +} #endif /* |