From: zeertzjq Date: Sun, 14 Jun 2026 15:39:26 +0000 (+0000) Subject: patch 9.2.0645: Composing chars no longer accepted in end-id abbr X-Git-Tag: v9.2.0645^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=23a84d28a8c4acfda1d01bde2b5366a496431d88;p=thirdparty%2Fvim.git patch 9.2.0645: Composing chars no longer accepted in end-id abbr Problem: Composing chars are no longer accepted in end-id abbreviation (after 9.2.0629). Solution: Unescape all chars using vim_unescape_csi() instead of using mb_unescape() on individual chars, so that mb_ptr2len() and MB_PTR_ADV() can still be used. closes: #20514 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- diff --git a/src/map.c b/src/map.c index 50d7ee4bcb..5970b3f5a5 100644 --- a/src/map.c +++ b/src/map.c @@ -660,26 +660,26 @@ do_map( // vi-compatible way. if (has_mbyte) { - int first, last; - int same = -1; - char_u *p_char; - - p = keys; - p_char = mb_unescape(&p); - if (p_char == NULL) - p_char = p++; - first = vim_iswordp(p_char); + int first, last; + int same = -1; + char_u keys_unescaped[MAXMAPLEN + 1]; + size_t keys_unescaped_len; + + mch_memmove(keys_unescaped, keys, (size_t)(len + 1)); + keys_unescaped_len = vim_unescape_csi(keys_unescaped); + p = keys_unescaped; + + first = vim_iswordp(p); last = first; + MB_PTR_ADV(p); n = 1; - while (p < keys + len) + while (p < keys_unescaped + keys_unescaped_len) { - ++n; // nr of (multi-byte) chars - p_char = mb_unescape(&p); - if (p_char == NULL) - p_char = p++; - last = vim_iswordp(p_char); // type of last char + ++n; // nr of (multi-byte) chars + last = vim_iswordp(p); // type of last char if (same == -1 && last != first) - same = n - 1; // count of same char type + same = n - 1; // count of same char type + MB_PTR_ADV(p); } if (last && n > 2 && same >= 0 && same < n - 1) { @@ -1687,8 +1687,7 @@ check_abbr( if (qe != NULL) { q = qe; - vim_unescape_csi(q); - qlen = (int)STRLEN(q); + qlen = (int)vim_unescape_csi(q); } } @@ -1908,8 +1907,9 @@ vim_strsave_escape_csi(char_u *p) /* * Remove escaping from CSI and K_SPECIAL characters. Reverse of * vim_strsave_escape_csi(). Works in-place. + * Returns the number of bytes in the unescaped string. */ - void + size_t vim_unescape_csi(char_u *p) { char_u *s = p, *d = p; @@ -1931,6 +1931,7 @@ vim_unescape_csi(char_u *p) *d++ = *s++; } *d = NUL; + return (size_t)(d - p); } /* diff --git a/src/proto/map.pro b/src/proto/map.pro index d696aabcd7..5f736f5047 100644 --- a/src/proto/map.pro +++ b/src/proto/map.pro @@ -12,7 +12,7 @@ int ExpandMappings(char_u *pat, regmatch_T *regmatch, int *numMatches, char_u ** int check_abbr(int c, char_u *ptr, int col, int mincol); char_u *eval_map_expr(mapblock_T *mp, int c); char_u *vim_strsave_escape_csi(char_u *p); -void vim_unescape_csi(char_u *p); +size_t vim_unescape_csi(char_u *p); int makemap(FILE *fd, buf_T *buf); int put_escstr(FILE *fd, char_u *strstart, int what); void check_map_keycodes(void); diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index 635193ebd3..d181bbf396 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -28,6 +28,18 @@ func Test_abbreviation() iunab abc; iunab ; + " abbreviation with composing chars (end-id) + inoreab ..ã a^~ + inoreab ..β̃ β^~ + inoreab ..π̃ π^~ + inoreab ..Λ̃ Λ^~ + call feedkeys("Go..ã ..β̃ ..π̃ ..Λ̃ \", "xt") + call assert_equal('a^~ β^~ π^~ Λ^~ ', getline('$')) + iunab ..ã + iunab ..β̃ + iunab ..π̃ + iunab ..Λ̃ + bwipe! endfunc diff --git a/src/version.c b/src/version.c index f00b31d09b..4a8bfe8213 100644 --- a/src/version.c +++ b/src/version.c @@ -759,6 +759,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 645, /**/ 644, /**/