# HG changeset patch # User Bram Moolenaar # Date 1607022005 -3600 # Node ID 5fbac68bda237c404c6a72a123936787aa9c3547 # Parent fc0d222fcf3693a9a9fdaf6f94fc7cbfd24d7ab8 patch 8.2.2084: CTRL-V U doesn't work to enter a Unicode character Commit: https://github.com/vim/vim/commit/0684e36a7ee0743f2889698fb8e0e14f7acae423 Author: Bram Moolenaar Date: Thu Dec 3 19:54:42 2020 +0100 patch 8.2.2084: CTRL-V U doesn't work to enter a Unicode character Problem: CTRL-V U doesn't work to enter a Unicode character when modifyOtherKeys is effective. (Ken Takata) Solution: Add a flag to get_literal() for the shift key. (closes #7413) diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -1534,7 +1534,6 @@ ins_ctrl_v(void) { int c; int did_putchar = FALSE; - int prev_mod_mask = mod_mask; // may need to redraw when no more chars available now ins_redraw(FALSE); @@ -1550,7 +1549,9 @@ ins_ctrl_v(void) add_to_showcmd_c(Ctrl_V); #endif - c = get_literal(); + // Do not change any modifyOtherKeys ESC sequence to a normal key for + // CTRL-SHIFT-V. + c = get_literal(mod_mask & MOD_MASK_SHIFT); if (did_putchar) // when the line fits in 'columns' the '^' is at the start of the next // line and will not removed by the redraw @@ -1559,11 +1560,6 @@ ins_ctrl_v(void) clear_showcmd(); #endif - if ((c == ESC || c == CSI) && !(prev_mod_mask & MOD_MASK_SHIFT)) - // Using CTRL-V: Change any modifyOtherKeys ESC sequence to a normal - // key. Don't do this for CTRL-SHIFT-V. - c = decodeModifyOtherKeys(c); - insert_special(c, FALSE, TRUE); #ifdef FEAT_RIGHTLEFT revins_chars++; @@ -1845,9 +1841,11 @@ del_char_after_col(int limit_col UNUSED) * A one, two or three digit decimal number is interpreted as its byte value. * If one or two digits are entered, the next character is given to vungetc(). * For Unicode a character > 255 may be returned. + * If "noReduceKeys" is TRUE do not change any modifyOtherKeys ESC sequence + * into a normal key, return ESC. */ int -get_literal(void) +get_literal(int noReduceKeys) { int cc; int nc; @@ -1878,6 +1876,9 @@ get_literal(void) for (;;) { nc = plain_vgetc(); + if ((nc == ESC || nc == CSI) && !noReduceKeys) + nc = decodeModifyOtherKeys(nc); + #ifdef FEAT_CMDL_INFO if (!(State & CMDLINE) && MB_BYTE2LEN_CHECK(nc) == 1) add_to_showcmd(nc); @@ -3812,8 +3813,7 @@ ins_ctrl_o(void) { if (State & VREPLACE_FLAG) restart_edit = 'V'; - else - if (State & REPLACE_FLAG) + else if (State & REPLACE_FLAG) restart_edit = 'R'; else restart_edit = 'I'; diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -2206,13 +2206,14 @@ getcmdline_int( case Ctrl_V: case Ctrl_Q: { - int prev_mod_mask = mod_mask; - ignore_drag_release = TRUE; putcmdline('^', TRUE); - no_reduce_keys = TRUE; // don't merge modifyOtherKeys - c = get_literal(); // get next (two) character(s) - no_reduce_keys = FALSE; + + // Get next (two) character(s). Do not change any + // modifyOtherKeys ESC sequence to a normal key for + // CTRL-SHIFT-V. + c = get_literal(mod_mask & MOD_MASK_SHIFT); + do_abbr = FALSE; // don't do abbreviation now extra_char = NUL; // may need to remove ^ when composing char was typed @@ -2223,13 +2224,6 @@ getcmdline_int( msg_putchar(' '); cursorcmd(); } - - if ((c == ESC || c == CSI) - && !(prev_mod_mask & MOD_MASK_SHIFT)) - // Using CTRL-V: Change any modifyOtherKeys ESC - // sequence to a normal key. Don't do this for - // CTRL-SHIFT-V. - c = decodeModifyOtherKeys(c); } break; diff --git a/src/getchar.c b/src/getchar.c --- a/src/getchar.c +++ b/src/getchar.c @@ -2580,11 +2580,10 @@ handle_mapping( typebuf.tb_off] == RM_YES)) && !*timedout) { - keylen = check_termcode(max_mlen + 1, - NULL, 0, NULL); - - // If no termcode matched but 'pastetoggle' matched partially it's - // like an incomplete key sequence. + keylen = check_termcode(max_mlen + 1, NULL, 0, NULL); + + // If no termcode matched but 'pastetoggle' matched partially + // it's like an incomplete key sequence. if (keylen == 0 && save_keylen == KEYLEN_PART_KEY) keylen = KEYLEN_PART_KEY; @@ -3680,7 +3679,7 @@ getcmdkeycmd( // CTRL-V is followed by octal, hex or other characters, reverses // what AppendToRedobuffLit() does. no_reduce_keys = TRUE; // don't merge modifyOtherKeys - c1 = get_literal(); + c1 = get_literal(TRUE); no_reduce_keys = FALSE; } diff --git a/src/normal.c b/src/normal.c --- a/src/normal.c +++ b/src/normal.c @@ -4927,7 +4927,7 @@ nv_replace(cmdarg_T *cap) if (cap->nchar == Ctrl_V) { had_ctrl_v = Ctrl_V; - cap->nchar = get_literal(); + cap->nchar = get_literal(FALSE); // Don't redo a multibyte character with CTRL-V. if (cap->nchar > DEL) had_ctrl_v = NUL; @@ -5208,7 +5208,7 @@ nv_vreplace(cmdarg_T *cap) else { if (cap->extra_char == Ctrl_V) // get another character - cap->extra_char = get_literal(); + cap->extra_char = get_literal(FALSE); stuffcharReadbuff(cap->extra_char); stuffcharReadbuff(ESC); if (virtual_active()) diff --git a/src/proto/edit.pro b/src/proto/edit.pro --- a/src/proto/edit.pro +++ b/src/proto/edit.pro @@ -10,7 +10,7 @@ void display_dollar(colnr_T col); void undisplay_dollar(void); void truncate_spaces(char_u *line); void backspace_until_column(int col); -int get_literal(void); +int get_literal(int noReduceKeys); void insertchar(int c, int flags, int second_indent); void start_arrow(pos_T *end_insert_pos); int stop_arrow(void); diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -1966,6 +1966,16 @@ func RunTest_modifyOtherKeys(func) bwipe aaa bwipe bbb + " Ctrl-V X 33 is 3 + call setline(1, '') + call feedkeys("a\" .. a:func('X', 2) .. "33\", 'Lx!') + call assert_equal("3", getline(1)) + + " Ctrl-V U 12345 is Unicode 12345 + call setline(1, '') + call feedkeys("a\" .. a:func('U', 2) .. "12345\", 'Lx!') + call assert_equal("\U12345", getline(1)) + bwipe! set timeoutlen& endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2084, +/**/ 2083, /**/ 2082,