summaryrefslogtreecommitdiff
path: root/src/misc2.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-01-26 22:51:56 +0100
committerBram Moolenaar <Bram@vim.org>2017-01-26 22:51:56 +0100
commitcc5b22b3bfdc0e9e835cf7871166badda31447bd (patch)
tree11e117ab82deca899a492b823dd0b0cb1c0ed37b /src/misc2.c
parent65c836e6004647196ae0bc18e409a9e7b79207c0 (diff)
downloadvim-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.c68
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
/*