patch 8.0.0243: tolower() does not work if the byte count changes
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)
diff --git a/src/misc2.c b/src/misc2.c
index dd0e694..9c39d40 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1602,7 +1602,10 @@
{
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 @@
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
/*