To: vim_dev@googlegroups.com Subject: Patch 8.2.0916 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0916 Problem: Mapping with partly modifyOtherKeys code does not work. Solution: If there is no mapping with a separate modifier include the modifier in the key and then try mapping again. (closes #6200) Files: src/getchar.c, src/proto/getchar.pro, src/edit.c, src/term.c, src/proto/term.pro, src/testdir/test_termcodes.vim *** ../vim-8.2.0915/src/getchar.c 2020-06-04 22:22:07.865401775 +0200 --- src/getchar.c 2020-06-06 22:31:30.588935340 +0200 *************** *** 1582,1596 **** } /* ! * Convert "c" plus "mod_mask" to merge the effect of modifyOtherKeys into the * character. */ int ! merge_modifyOtherKeys(int c_arg) { int c = c_arg; ! if (mod_mask & MOD_MASK_CTRL) { if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) c &= 0x1f; --- 1582,1596 ---- } /* ! * Convert "c" plus "modifiers" to merge the effect of modifyOtherKeys into the * character. */ int ! merge_modifyOtherKeys(int c_arg, int *modifiers) { int c = c_arg; ! if (*modifiers & MOD_MASK_CTRL) { if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) c &= 0x1f; *************** *** 1612,1624 **** c = DEL; #endif if (c != c_arg) ! mod_mask &= ~MOD_MASK_CTRL; } ! if ((mod_mask & (MOD_MASK_META | MOD_MASK_ALT)) && c >= 0 && c <= 127) { c += 0x80; ! mod_mask &= ~(MOD_MASK_META|MOD_MASK_ALT); } return c; } --- 1612,1624 ---- c = DEL; #endif if (c != c_arg) ! *modifiers &= ~MOD_MASK_CTRL; } ! if ((*modifiers & (MOD_MASK_META | MOD_MASK_ALT)) && c >= 0 && c <= 127) { c += 0x80; ! *modifiers &= ~(MOD_MASK_META|MOD_MASK_ALT); } return c; } *************** *** 1866,1872 **** // cases they are put back in the typeahead buffer. vgetc_mod_mask = mod_mask; vgetc_char = c; ! c = merge_modifyOtherKeys(c); } break; --- 1866,1872 ---- // cases they are put back in the typeahead buffer. vgetc_mod_mask = mod_mask; vgetc_char = c; ! c = merge_modifyOtherKeys(c, &mod_mask); } break; *************** *** 2255,2260 **** --- 2255,2298 ---- } /* + * Check if typebuf.tb_buf[] contains a modifer plus key that can be changed + * into just a key, apply that. + * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off + * + "max_offset"]. + * Return the length of the replaced bytes, zero if nothing changed. + */ + static int + check_simplify_modifier(int max_offset) + { + int offset; + char_u *tp; + + for (offset = 0; offset < max_offset; ++offset) + { + if (offset + 3 >= typebuf.tb_len) + break; + tp = typebuf.tb_buf + typebuf.tb_off + offset; + if (tp[0] == K_SPECIAL && tp[1] == KS_MODIFIER) + { + int modifier = tp[2]; + int new_c = merge_modifyOtherKeys(tp[3], &modifier); + + if (new_c != tp[3] && modifier == 0) + { + char_u new_string[MB_MAXBYTES]; + int len = mb_char2bytes(new_c, new_string); + + if (put_string_in_typebuf(offset, 4, new_string, len, + NULL, 0, 0) == FAIL) + return -1; + return len; + } + } + } + return 0; + } + + /* * Handle mappings in the typeahead buffer. * - When something was mapped, return map_result_retry for recursive mappings. * - When nothing mapped and typeahead has a character: return map_result_get. *************** *** 2519,2524 **** --- 2557,2567 ---- if (keylen == 0 && save_keylen == KEYLEN_PART_KEY) keylen = KEYLEN_PART_KEY; + // If no termcode matched, try to include the modifier into the + // key. This for when modifyOtherKeys is working. + if (keylen == 0) + keylen = check_simplify_modifier(max_mlen + 1); + // When getting a partial match, but the last characters were not // typed, don't wait for a typed character to complete the // termcode. This helps a lot when a ":normal" command ends in an *** ../vim-8.2.0915/src/proto/getchar.pro 2020-05-29 22:41:36.925691046 +0200 --- src/proto/getchar.pro 2020-06-06 20:16:04.903041860 +0200 *************** *** 37,43 **** void close_all_scripts(void); int using_script(void); void before_blocking(void); ! int merge_modifyOtherKeys(int c_arg); int vgetc(void); int safe_vgetc(void); int plain_vgetc(void); --- 37,43 ---- void close_all_scripts(void); int using_script(void); void before_blocking(void); ! int merge_modifyOtherKeys(int c_arg, int *modifiers); int vgetc(void); int safe_vgetc(void); int plain_vgetc(void); *** ../vim-8.2.0915/src/edit.c 2020-05-01 14:26:17.128949276 +0200 --- src/edit.c 2020-06-06 20:16:10.499025162 +0200 *************** *** 1609,1615 **** #endif mod_mask = decode_modifiers(arg[!form]); ! c = merge_modifyOtherKeys(arg[form]); } } --- 1609,1615 ---- #endif mod_mask = decode_modifiers(arg[!form]); ! c = merge_modifyOtherKeys(arg[form], &mod_mask); } } *** ../vim-8.2.0915/src/term.c 2020-06-05 19:36:53.468217572 +0200 --- src/term.c 2020-06-06 20:16:36.790946717 +0200 *************** *** 4251,4257 **** * Remove "slen" bytes. * Returns FAIL for error. */ ! static int put_string_in_typebuf( int offset, int slen, --- 4251,4257 ---- * Remove "slen" bytes. * Returns FAIL for error. */ ! int put_string_in_typebuf( int offset, int slen, *************** *** 4342,4348 **** /* * Check if typebuf.tb_buf[] contains a terminal key code. * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off ! * + max_offset]. * Return 0 for no match, -1 for partial match, > 0 for full match. * Return KEYLEN_REMOVED when a key code was deleted. * With a match, the match is removed, the replacement code is inserted in --- 4342,4348 ---- /* * Check if typebuf.tb_buf[] contains a terminal key code. * Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off ! * + "max_offset"]. * Return 0 for no match, -1 for partial match, > 0 for full match. * Return KEYLEN_REMOVED when a key code was deleted. * With a match, the match is removed, the replacement code is inserted in *** ../vim-8.2.0915/src/proto/term.pro 2020-05-31 16:41:04.646603340 +0200 --- src/proto/term.pro 2020-06-06 20:16:50.946904556 +0200 *************** *** 68,73 **** --- 68,74 ---- void del_termcode(char_u *name); void set_mouse_topline(win_T *wp); int is_mouse_topline(win_T *wp); + int put_string_in_typebuf(int offset, int slen, char_u *string, int new_slen, char_u *buf, int bufsize, int *buflen); int decode_modifiers(int n); int check_termcode(int max_offset, char_u *buf, int bufsize, int *buflen); void term_get_fg_color(char_u *r, char_u *g, char_u *b); *** ../vim-8.2.0915/src/testdir/test_termcodes.vim 2020-05-07 18:43:40.867365982 +0200 --- src/testdir/test_termcodes.vim 2020-06-06 22:25:15.366004122 +0200 *************** *** 1222,1227 **** --- 1222,1244 ---- endif endfunc + func Test_modifyOtherKeys_mapped() + set timeoutlen=10 + imap ' + imap c-a + call setline(1, '') + + " single quote is turned into single byte CTRL-W + " CTRL-A is added with a separate modifier, and needs to be simplified before + " the mapping can match. + call feedkeys("a'" .. GetEscCodeCSI27('A', 5) .. "\", 'Lx!') + call assert_equal('c-a', getline(1)) + + iunmap ' + iunmap + set timeoutlen& + endfunc + func RunTest_mapping_works_with_shift(func) new set timeoutlen=10 *** ../vim-8.2.0915/src/version.c 2020-06-06 18:37:47.864138502 +0200 --- src/version.c 2020-06-06 22:29:40.713246954 +0200 *************** *** 756,757 **** --- 756,759 ---- { /* Add new patch number below this line */ + /**/ + 916, /**/ -- FIRST HEAD: All right! All right! We'll kill him first and then have tea and biscuits. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///