diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-05-02 22:53:45 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-05-02 22:53:45 +0100 |
commit | db08887f24d20be11d184ce321bc0890613e42bd (patch) | |
tree | 6e9feb7b98be9323db3220951107c1d2edd01d57 | |
parent | f4f579b46b27f5e1689912a3e84c6a2a96efd143 (diff) |
patch 8.2.4858: K_SPECIAL may be escaped twicev8.2.4858
Problem: K_SPECIAL may be escaped twice.
Solution: Avoid double escaping. (closes #10340)
-rw-r--r-- | src/highlight.c | 2 | ||||
-rw-r--r-- | src/misc2.c | 13 | ||||
-rw-r--r-- | src/proto/misc2.pro | 4 | ||||
-rw-r--r-- | src/term.c | 2 | ||||
-rw-r--r-- | src/testdir/test_eval_stuff.vim | 22 | ||||
-rw-r--r-- | src/testdir/test_feedkeys.vim | 11 | ||||
-rw-r--r-- | src/testdir/test_functions.vim | 4 | ||||
-rw-r--r-- | src/testdir/test_mapping.vim | 15 | ||||
-rw-r--r-- | src/typval.c | 9 | ||||
-rw-r--r-- | src/version.c | 2 |
10 files changed, 67 insertions, 17 deletions
diff --git a/src/highlight.c b/src/highlight.c index 6a2b0874df..1e6f9c7066 100644 --- a/src/highlight.c +++ b/src/highlight.c @@ -1356,7 +1356,7 @@ highlight_set_startstop_termcode(int idx, char_u *key, char_u *arg, int init) // Copy characters from arg[] to buf[], translating <> codes. for (p = arg, off = 0; off < 100 - 6 && *p; ) { - len = trans_special(&p, buf + off, FSK_SIMPLIFY, NULL); + len = trans_special(&p, buf + off, FSK_SIMPLIFY, FALSE, NULL); if (len > 0) // recognized special char off += len; else // copy as normal char diff --git a/src/misc2.c b/src/misc2.c index 6641a27c73..8e46a733c7 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -1265,6 +1265,7 @@ trans_special( char_u **srcp, char_u *dst, int flags, // FSK_ values + int escape_ks, // escape K_SPECIAL bytes in the character int *did_simplify) // FSK_SIMPLIFY and found <C-H> or <A-x> { int modifiers = 0; @@ -1274,18 +1275,18 @@ trans_special( if (key == 0) return 0; - return special_to_buf(key, modifiers, flags & FSK_KEYCODE, dst); + return special_to_buf(key, modifiers, escape_ks, dst); } /* * Put the character sequence for "key" with "modifiers" into "dst" and return * the resulting length. - * When "keycode" is TRUE prefer key code, e.g. K_DEL instead of DEL. + * When "escape_ks" is TRUE escape K_SPECIAL bytes in the character. * The sequence is not NUL terminated. * This is how characters in a string are encoded. */ int -special_to_buf(int key, int modifiers, int keycode, char_u *dst) +special_to_buf(int key, int modifiers, int escape_ks, char_u *dst) { int dlen = 0; @@ -1303,10 +1304,10 @@ special_to_buf(int key, int modifiers, int keycode, char_u *dst) dst[dlen++] = KEY2TERMCAP0(key); dst[dlen++] = KEY2TERMCAP1(key); } - else if (has_mbyte && !keycode) - dlen += (*mb_char2bytes)(key, dst + dlen); - else if (keycode) + else if (escape_ks) dlen = (int)(add_char2buf(key, dst + dlen) - dst); + else if (has_mbyte) + dlen += (*mb_char2bytes)(key, dst + dlen); else dst[dlen++] = key; diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index e34202127a..fe0a4fbb53 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -24,8 +24,8 @@ int vim_isspace(int x); int simplify_key(int key, int *modifiers); int handle_x_keys(int key); char_u *get_special_key_name(int c, int modifiers); -int trans_special(char_u **srcp, char_u *dst, int flags, int *did_simplify); -int special_to_buf(int key, int modifiers, int keycode, char_u *dst); +int trans_special(char_u **srcp, char_u *dst, int flags, int escape_ks, int *did_simplify); +int special_to_buf(int key, int modifiers, int escape_ks, char_u *dst); int find_special_key(char_u **srcp, int *modp, int flags, int *did_simplify); int may_adjust_key_for_ctrl(int modifiers, int key); int may_remove_shift_modifier(int modifiers, int key); diff --git a/src/term.c b/src/term.c index 4044d751a0..bf5943d53b 100644 --- a/src/term.c +++ b/src/term.c @@ -6104,7 +6104,7 @@ replace_termcodes( #endif slen = trans_special(&src, result + dlen, FSK_KEYCODE | ((flags & REPTERM_NO_SIMPLIFY) ? 0 : FSK_SIMPLIFY), - did_simplify); + TRUE, did_simplify); if (slen) { dlen += slen; diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim index 6043ed9a13..3c168f2f59 100644 --- a/src/testdir/test_eval_stuff.vim +++ b/src/testdir/test_eval_stuff.vim @@ -595,4 +595,26 @@ func Test_deep_recursion() call assert_fails("exe 'if ' .. repeat('(', 1002)", 'E1169: Expression too recursive: ((') endfunc +" K_SPECIAL in the modified character used be escaped, which causes +" double-escaping with feedkeys() or as the return value of an <expr> mapping, +" and doesn't match what getchar() returns, +func Test_modified_char_no_escape_special() + nnoremap <M-…> <Cmd>let g:got_m_ellipsis += 1<CR> + call feedkeys("\<M-…>", 't') + call assert_equal("\<M-…>", getchar()) + let g:got_m_ellipsis = 0 + call feedkeys("\<M-…>", 'xt') + call assert_equal(1, g:got_m_ellipsis) + func Func() + return "\<M-…>" + endfunc + nmap <expr> <F2> Func() + call feedkeys("\<F2>", 'xt') + call assert_equal(2, g:got_m_ellipsis) + delfunc Func + nunmap <F2> + unlet g:got_m_ellipsis + nunmap <M-…> +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_feedkeys.vim b/src/testdir/test_feedkeys.vim index f343b0174c..fb64711863 100644 --- a/src/testdir/test_feedkeys.vim +++ b/src/testdir/test_feedkeys.vim @@ -23,4 +23,15 @@ func Test_feedkeys_with_abbreviation() iunabbrev trigger endfunc +func Test_feedkeys_escape_special() + nnoremap … <Cmd>let g:got_ellipsis += 1<CR> + call feedkeys('…', 't') + call assert_equal('…', getcharstr()) + let g:got_ellipsis = 0 + call feedkeys('…', 'xt') + call assert_equal(1, g:got_ellipsis) + unlet g:got_ellipsis + nunmap … +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index dbed757ff3..a1b9b3d262 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -2721,8 +2721,8 @@ func Test_nr2char() call assert_equal('a', nr2char(97, 1)) call assert_equal('a', nr2char(97, 0)) - call assert_equal("\x80\xfc\b\xf4\x80\xfeX\x80\xfeX\x80\xfeX", eval('"\<M-' .. nr2char(0x100000) .. '>"')) - call assert_equal("\x80\xfc\b\xfd\x80\xfeX\x80\xfeX\x80\xfeX\x80\xfeX\x80\xfeX", eval('"\<M-' .. nr2char(0x40000000) .. '>"')) + call assert_equal("\x80\xfc\b" .. nr2char(0x100000), eval('"\<M-' .. nr2char(0x100000) .. '>"')) + call assert_equal("\x80\xfc\b" .. nr2char(0x40000000), eval('"\<M-' .. nr2char(0x40000000) .. '>"')) endfunc " Test for screenattr(), screenchar() and screenchars() functions diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index b413f4fc34..7f768cf80f 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -1643,4 +1643,19 @@ func Test_unmap_simplifiable() unmap <C-I> endfunc +func Test_expr_map_escape_special() + nnoremap … <Cmd>let g:got_ellipsis += 1<CR> + func Func() + return '…' + endfunc + nmap <expr> <F2> Func() + let g:got_ellipsis = 0 + call feedkeys("\<F2>", 'xt') + call assert_equal(1, g:got_ellipsis) + delfunc Func + nunmap <F2> + unlet g:got_ellipsis + nunmap … +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/typval.c b/src/typval.c index 50b1d620a6..4f6e41dfdd 100644 --- a/src/typval.c +++ b/src/typval.c @@ -2069,11 +2069,10 @@ eval_string(char_u **arg, typval_T *rettv, int evaluate) { ++p; // A "\<x>" form occupies at least 4 characters, and produces up - // to 21 characters (3 * 6 for the char and 3 for a modifier): - // reserve space for 18 extra. - // Each byte in the char could be encoded as K_SPECIAL K_EXTRA x. + // to 9 characters (6 for the char and 3 for a modifier): + // reserve space for 5 extra. if (*p == '<') - extra += 18; + extra += 5; } } @@ -2168,7 +2167,7 @@ eval_string(char_u **arg, typval_T *rettv, int evaluate) if (p[1] != '*') flags |= FSK_SIMPLIFY; - extra = trans_special(&p, end, flags, NULL); + extra = trans_special(&p, end, flags, FALSE, NULL); if (extra != 0) { end += extra; diff --git a/src/version.c b/src/version.c index c62081853d..511e3d3460 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4858, +/**/ 4857, /**/ 4856, |