Patch 8.1.2145
Problem: Cannot map <C-H> when modifyOtherKeys is enabled.
Solution: Add the <C-H> mapping twice, both with modifier and as 0x08. Use
only the first one when modifyOtherKeys has been detected.
Files: src/term.c, src/eval.c, src/getchar.c, src/globals.h,
src/gui_mac.c, src/gui_w32.c, src/highlight.c, src/if_ole.cpp,
src/main.c, src/map.c, src/menu.c, src/misc2.c, src/option.c,
src/proto/misc2.pro, src/proto/term.pro,
src/testdir/test_termcodes.vim, src/structs.h, src/terminal.c,
src/usercmd.c, src/vim.h
*** ../vim-8.1.2144/src/term.c 2019-10-12 21:08:37.002660427 +0200
--- src/term.c 2019-10-13 16:32:33.182348952 +0200
***************
*** 4845,4850 ****
--- 4845,4851 ----
else if ((arg[0] == 27 && argc == 3 && trail == '~')
|| (argc == 2 && trail == 'u'))
{
+ seenModifyOtherKeys = TRUE;
if (trail == 'u')
key = arg[0];
else
***************
*** 4853,4865 ****
modifiers = decode_modifiers(arg[1]);
// Some keys already have Shift included, pass them as
! // normal keys.
if (modifiers == MOD_MASK_SHIFT
&& ((key >= '@' && key <= 'Z')
|| key == '^' || key == '_'
|| (key >= '{' && key <= '~')))
modifiers = 0;
// insert modifiers with KS_MODIFIER
new_slen = modifiers2keycode(modifiers, &key, string);
slen = csi_len;
--- 4854,4873 ----
modifiers = decode_modifiers(arg[1]);
// Some keys already have Shift included, pass them as
! // normal keys. Not when Ctrl is also used, because <C-H>
! // and <C-S-H> are different.
if (modifiers == MOD_MASK_SHIFT
&& ((key >= '@' && key <= 'Z')
|| key == '^' || key == '_'
|| (key >= '{' && key <= '~')))
modifiers = 0;
+ // When used with Ctrl we always make a letter upper case,
+ // so that mapping <C-H> and <C-h> are the same. Typing
+ // <C-S-H> also uses "H" but modifier is different.
+ if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key))
+ key = TOUPPER_ASC(key);
+
// insert modifiers with KS_MODIFIER
new_slen = modifiers2keycode(modifiers, &key, string);
slen = csi_len;
***************
*** 5340,5357 ****
* pointer to it is returned. If something fails *bufp is set to NULL and from
* is returned.
*
! * CTRL-V characters are removed. When "from_part" is TRUE, a trailing CTRL-V
! * is included, otherwise it is removed (for ":map xx ^V", maps xx to
! * nothing). When 'cpoptions' does not contain 'B', a backslash can be used
! * instead of a CTRL-V.
*/
char_u *
replace_termcodes(
char_u *from,
char_u **bufp,
! int from_part,
! int do_lt, /* also translate <lt> */
! int special) /* always accept <key> notation */
{
int i;
int slen;
--- 5348,5373 ----
* pointer to it is returned. If something fails *bufp is set to NULL and from
* is returned.
*
! * CTRL-V characters are removed. When "flags" has REPTERM_FROM_PART, a
! * trailing CTRL-V is included, otherwise it is removed (for ":map xx ^V",
maps
! * xx to nothing). When 'cpoptions' does not contain 'B', a backslash can be
! * used instead of a CTRL-V.
! *
! * Flags:
! * REPTERM_FROM_PART see above
! * REPTERM_DO_LT also translate <lt>
! * REPTERM_SPECIAL always accept <key> notation
! * REPTERM_NO_SIMPLIFY do not simplify <C-H> to 0x08 and set 8th bit
for <A-x>
! *
! * "did_simplify" is set when some <C-H> or <A-x> code was simplified, unless
! * it is NULL.
*/
char_u *
replace_termcodes(
char_u *from,
char_u **bufp,
! int flags,
! int *did_simplify)
{
int i;
int slen;
***************
*** 5364,5370 ****
char_u *result; /* buffer for resulting string */
do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
! do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL) || special;
do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
/*
--- 5380,5387 ----
char_u *result; /* buffer for resulting string */
do_backslash = (vim_strchr(p_cpo, CPO_BSLASH) == NULL);
! do_special = (vim_strchr(p_cpo, CPO_SPECI) == NULL)
! || (flags & REPTERM_SPECIAL);
do_key_code = (vim_strchr(p_cpo, CPO_KEYCODE) == NULL);
/*
***************
*** 5383,5389 ****
/*
* Check for #n at start only: function key n
*/
! if (from_part && src[0] == '#' && VIM_ISDIGIT(src[1])) /* function key */
{
result[dlen++] = K_SPECIAL;
result[dlen++] = 'k';
--- 5400,5406 ----
/*
* Check for #n at start only: function key n
*/
! if ((flags & REPTERM_FROM_PART) && src[0] == '#' && VIM_ISDIGIT(src[1]))
{
result[dlen++] = K_SPECIAL;
result[dlen++] = 'k';
***************
*** 5403,5409 ****
* If 'cpoptions' does not contain '<', check for special key codes,
* like "<C-S-LeftMouse>"
*/
! if (do_special && (do_lt || STRNCMP(src, "<lt>", 4) != 0))
{
#ifdef FEAT_EVAL
/*
--- 5420,5427 ----
* If 'cpoptions' does not contain '<', check for special key codes,
* like "<C-S-LeftMouse>"
*/
! if (do_special && ((flags & REPTERM_DO_LT)
! || STRNCMP(src, "<lt>", 4) != 0))
{
#ifdef FEAT_EVAL
/*
***************
*** 5429,5435 ****
}
#endif
! slen = trans_special(&src, result + dlen, TRUE, FALSE);
if (slen)
{
dlen += slen;
--- 5447,5454 ----
}
#endif
! slen = trans_special(&src, result + dlen, TRUE, FALSE,
! (flags & REPTERM_NO_SIMPLIFY) == 0, did_simplify);
if (slen)
{
dlen += slen;
***************
*** 5509,5515 ****
++src; /* skip CTRL-V or backslash */
if (*src == NUL)
{
! if (from_part)
result[dlen++] = key;
break;
}
--- 5528,5534 ----
++src; /* skip CTRL-V or backslash */
if (*src == NUL)
{
! if (flags & REPTERM_FROM_PART)
result[dlen++] = key;
break;
}
*** ../vim-8.1.2144/src/eval.c 2019-10-06 22:00:08.293244132 +0200
--- src/eval.c 2019-10-12 22:54:09.036941168 +0200
***************
*** 3526,3532 ****
break;
/* Special key, e.g.: "\<C-W>" */
! case '<': extra = trans_special(&p, name, TRUE, TRUE);
if (extra != 0)
{
name += extra;
--- 3526,3533 ----
break;
/* Special key, e.g.: "\<C-W>" */
! case '<': extra = trans_special(&p, name, TRUE, TRUE,
! TRUE, NULL);
if (extra != 0)
{
name += extra;
*** ../vim-8.1.2144/src/getchar.c 2019-10-10 21:49:24.974264458 +0200
--- src/getchar.c 2019-10-13 16:30:20.398643743 +0200
***************
*** 52,58 ****
*/
static int block_redo = FALSE;
! static int KeyNoremap = 0; /* remapping flags */
/*
* Variables used by vgetorpeek() and flush_buffers().
--- 52,58 ----
*/
static int block_redo = FALSE;
! static int KeyNoremap = 0; // remapping flags
/*
* Variables used by vgetorpeek() and flush_buffers().
***************
*** 1771,1777 ****
if (!no_reduce_keys)
{
// A modifier was not used for a mapping, apply it to ASCII
! // keys.
if ((mod_mask & MOD_MASK_CTRL)
&& ((c >= '`' && c <= 0x7f)
|| (c >= '@' && c <= '_')))
--- 1771,1777 ----
if (!no_reduce_keys)
{
// A modifier was not used for a mapping, apply it to ASCII
! // keys. Shift would already have been applied.
if ((mod_mask & MOD_MASK_CTRL)
&& ((c >= '`' && c <= 0x7f)
|| (c >= '@' && c <= '_')))
***************
*** 2240,2245 ****
--- 2240,2246 ----
// Skip ":lmap" mappings if keys were mapped.
if (mp->m_keys[0] == tb_c1
&& (mp->m_mode & local_State)
+ && !(mp->m_simplified && seenModifyOtherKeys)
&& ((mp->m_mode & LANGMAP) == 0 || typebuf.tb_maplen == 0))
{
#ifdef FEAT_LANGMAP
*** ../vim-8.1.2144/src/globals.h 2019-10-10 21:13:59.962360351 +0200
--- src/globals.h 2019-10-12 21:30:03.017623342 +0200
***************
*** 1002,1007 ****
--- 1002,1011 ----
EXTERN int reg_recording INIT(= 0); // register for recording or zero
EXTERN int reg_executing INIT(= 0); // register being executed or zero
+ // Set when a modifyOtherKeys sequence was seen, then simplified mappings will
+ // no longer be used.
+ EXTERN int seenModifyOtherKeys INIT(= FALSE);
+
EXTERN int no_mapping INIT(= FALSE); // currently no mapping allowed
EXTERN int no_zero_mapping INIT(= 0); // mapping zero not allowed
EXTERN int allow_keys INIT(= FALSE); // allow key codes when no_mapping
*** ../vim-8.1.2144/src/gui_mac.c 2019-06-14 21:36:51.014437500 +0200
--- src/gui_mac.c 2019-10-12 22:52:04.457341368 +0200
***************
*** 2177,2183 ****
key_char = simplify_key(key_char, (int *)&vimModifiers);
/* Interpret META, include SHIFT, etc. */
! key_char = extract_modifiers(key_char, (int *)&vimModifiers);
if (key_char == CSI)
key_char = K_CSI;
--- 2177,2184 ----
key_char = simplify_key(key_char, (int *)&vimModifiers);
/* Interpret META, include SHIFT, etc. */
! key_char = extract_modifiers(key_char, (int *)&vimModifiers,
! TRUE, NULL);
if (key_char == CSI)
key_char = K_CSI;
***************
*** 4772,4778 ****
char_u *p_actext;
p_actext = menu->actext;
! key = find_special_key(&p_actext, &modifiers, FALSE, FALSE, FALSE);
if (*p_actext != 0)
key = 0; /* error: trailing text */
/* find_special_key() returns a keycode with as many of the
--- 4773,4780 ----
char_u *p_actext;
p_actext = menu->actext;
! key = find_special_key(&p_actext, &modifiers, FALSE, FALSE, FALSE,
! TRUE, NULL);
if (*p_actext != 0)
key = 0; /* error: trailing text */
/* find_special_key() returns a keycode with as many of the
*** ../vim-8.1.2144/src/gui_w32.c 2019-09-21 23:09:00.975830710 +0200
--- src/gui_w32.c 2019-10-12 22:50:19.669659794 +0200
***************
*** 850,856 ****
modifiers &= ~MOD_MASK_SHIFT;
/* Interpret the ALT key as making the key META, include SHIFT, etc. */
! ch = extract_modifiers(ch, &modifiers);
if (ch == CSI)
ch = K_CSI;
--- 850,856 ----
modifiers &= ~MOD_MASK_SHIFT;
/* Interpret the ALT key as making the key META, include SHIFT, etc. */
! ch = extract_modifiers(ch, &modifiers, TRUE, NULL);
if (ch == CSI)
ch = K_CSI;
*** ../vim-8.1.2144/src/highlight.c 2019-10-06 22:00:08.297244105 +0200
--- src/highlight.c 2019-10-12 22:54:29.120874876 +0200
***************
*** 1417,1423 ****
*/
for (p = arg, off = 0; off < 100 - 6 && *p; )
{
! len = trans_special(&p, buf + off, FALSE, FALSE);
if (len > 0) // recognized special char
off += len;
else // copy as normal char
--- 1417,1424 ----
*/
for (p = arg, off = 0; off < 100 - 6 && *p; )
{
! len = trans_special(&p, buf + off, FALSE, FALSE,
! TRUE, NULL);
if (len > 0) // recognized special char
off += len;
else // copy as normal char
*** ../vim-8.1.2144/src/if_ole.cpp 2019-05-25 20:21:24.677951017 +0200
--- src/if_ole.cpp 2019-10-12 21:53:01.919597212 +0200
***************
*** 330,336 ****
}
/* Translate key codes like <Esc> */
! str = replace_termcodes((char_u *)buffer, &ptr, FALSE, TRUE, FALSE);
/* If ptr was set, then a new buffer was allocated,
* so we can free the old one.
--- 330,336 ----
}
/* Translate key codes like <Esc> */
! str = replace_termcodes((char_u *)buffer, &ptr, REPTERM_DO_LT, NULL);
/* If ptr was set, then a new buffer was allocated,
* so we can free the old one.
*** ../vim-8.1.2144/src/main.c 2019-09-25 21:43:07.275251603 +0200
--- src/main.c 2019-10-12 21:46:49.873275123 +0200
***************
*** 4339,4345 ****
* <lt> sequence is recognised - needed for a real backslash.
*/
p_cpo = (char_u *)"Bk";
! str = replace_termcodes((char_u *)str, &ptr, FALSE, TRUE, FALSE);
p_cpo = cpo_save;
if (*ptr != NUL) /* trailing CTRL-V results in nothing */
--- 4339,4345 ----
* <lt> sequence is recognised - needed for a real backslash.
*/
p_cpo = (char_u *)"Bk";
! str = replace_termcodes((char_u *)str, &ptr, REPTERM_DO_LT, NULL);
p_cpo = cpo_save;
if (*ptr != NUL) /* trailing CTRL-V results in nothing */
*** ../vim-8.1.2144/src/map.c 2019-09-03 22:08:13.673035035 +0200
--- src/map.c 2019-10-13 15:33:19.963928416 +0200
***************
*** 256,273 ****
char_u *p;
int n;
int len = 0; // init for GCC
- char_u *newstr;
int hasarg;
int haskey;
! int did_it = FALSE;
! int did_local = FALSE;
! int round;
char_u *keys_buf = NULL;
char_u *arg_buf = NULL;
int retval = 0;
int do_backslash;
- int hash;
- int new_hash;
mapblock_T **abbr_table;
mapblock_T **map_table;
int unique = FALSE;
--- 256,270 ----
char_u *p;
int n;
int len = 0; // init for GCC
int hasarg;
int haskey;
! int do_print;
! int keyround;
char_u *keys_buf = NULL;
+ char_u *alt_keys_buf = NULL;
char_u *arg_buf = NULL;
int retval = 0;
int do_backslash;
mapblock_T **abbr_table;
mapblock_T **map_table;
int unique = FALSE;
***************
*** 277,282 ****
--- 274,280 ----
#ifdef FEAT_EVAL
int expr = FALSE;
#endif
+ int did_simplify = FALSE;
int noremap;
char_u *orig_rhs;
***************
*** 375,380 ****
--- 373,379 ----
rhs = p;
hasarg = (*rhs != NUL);
haskey = (*keys != NUL);
+ do_print = !haskey || (maptype != 1 && !hasarg);
// check for :unmap without argument
if (maptype == 1 && !haskey)
***************
*** 389,761 ****
// replace_termcodes() may move the result to allocated memory, which
// needs to be freed later (*keys_buf and *arg_buf).
// replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
if (haskey)
! keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special);
orig_rhs = rhs;
if (hasarg)
{
if (STRICMP(rhs, "<nop>") == 0) // "<Nop>" means nothing
rhs = (char_u *)"";
else
! rhs = replace_termcodes(rhs, &arg_buf, FALSE, TRUE, special);
}
! // check arguments and translate function keys
! if (haskey)
{
! len = (int)STRLEN(keys);
! if (len > MAXMAPLEN) // maximum length of MAXMAPLEN chars
{
! retval = 1;
! goto theend;
}
! if (abbrev && maptype != 1)
{
! // If an abbreviation ends in a keyword character, the
! // rest must be all keyword-char or all non-keyword-char.
! // Otherwise we won't be able to find the start of it in a
! // vi-compatible way.
! if (has_mbyte)
{
! int first, last;
! int same = -1;
! first = vim_iswordp(keys);
! last = first;
! p = keys + (*mb_ptr2len)(keys);
! n = 1;
! while (p < keys + len)
! {
! ++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
! p += (*mb_ptr2len)(p);
! }
! if (last && n > 2 && same >= 0 && same < n - 1)
{
! retval = 1;
! goto theend;
}
! }
! else if (vim_iswordc(keys[len - 1])) // ends in keyword char
for (n = 0; n < len - 2; ++n)
if (vim_iswordc(keys[n]) != vim_iswordc(keys[len - 2]))
{
retval = 1;
goto theend;
}
! // An abbreviation cannot contain white space.
! for (n = 0; n < len; ++n)
! if (VIM_ISWHITE(keys[n]))
! {
! retval = 1;
! goto theend;
! }
}
- }
! if (haskey && hasarg && abbrev) // if we will add an abbreviation
! no_abbr = FALSE; // reset flag that indicates there are
// no abbreviations
! if (!haskey || (maptype != 1 && !hasarg))
! msg_start();
! // Check if a new local mapping wasn't already defined globally.
! if (map_table == curbuf->b_maphash && haskey && hasarg && maptype != 1)
! {
! // need to loop over all global hash lists
! for (hash = 0; hash < 256 && !got_int; ++hash)
{
! if (abbrev)
! {
! if (hash != 0) // there is only one abbreviation list
! break;
! mp = first_abbr;
! }
! else
! mp = maphash[hash];
! for ( ; mp != NULL && !got_int; mp = mp->m_next)
{
! // check entries with the same mode
! if ((mp->m_mode & mode) != 0
! && mp->m_keylen == len
! && unique
! && STRNCMP(mp->m_keys, keys, (size_t)len) == 0)
{
! if (abbrev)
! semsg(_("E224: global abbreviation already exists for
%s"),
! mp->m_keys);
! else
! semsg(_("E225: global mapping already exists for %s"),
! mp->m_keys);
! retval = 5;
! goto theend;
}
}
}
- }
! // When listing global mappings, also list buffer-local ones here.
! if (map_table != curbuf->b_maphash && !hasarg && maptype != 1)
! {
! // need to loop over all global hash lists
! for (hash = 0; hash < 256 && !got_int; ++hash)
{
! if (abbrev)
! {
! if (hash != 0) // there is only one abbreviation list
! break;
! mp = curbuf->b_first_abbr;
! }
! else
! mp = curbuf->b_maphash[hash];
! for ( ; mp != NULL && !got_int; mp = mp->m_next)
{
! // check entries with the same mode
! if ((mp->m_mode & mode) != 0)
{
! if (!haskey) // show all entries
! {
! showmap(mp, TRUE);
! did_local = TRUE;
! }
! else
{
! n = mp->m_keylen;
! if (STRNCMP(mp->m_keys, keys,
! (size_t)(n < len ? n : len)) == 0)
{
showmap(mp, TRUE);
did_local = TRUE;
}
}
}
}
}
- }
! // Find an entry in the maphash[] list that matches.
! // For :unmap we may loop two times: once to try to unmap an entry with a
! // matching 'from' part, a second time, if the first fails, to unmap an
! // entry with a matching 'to' part. This was done to allow ":ab foo bar"
! // to be unmapped by typing ":unab foo", where "foo" will be replaced by
! // "bar" because of the abbreviation.
! for (round = 0; (round == 0 || maptype == 1) && round <= 1
! && !did_it && !got_int; ++round)
! {
! // need to loop over all hash lists
! for (hash = 0; hash < 256 && !got_int; ++hash)
{
! if (abbrev)
! {
! if (hash > 0) // there is only one abbreviation list
! break;
! mpp = abbr_table;
! }
! else
! mpp = &(map_table[hash]);
! for (mp = *mpp; mp != NULL && !got_int; mp = *mpp)
{
!
! if (!(mp->m_mode & mode)) // skip entries with wrong mode
! {
! mpp = &(mp->m_next);
! continue;
! }
! if (!haskey) // show all entries
{
! showmap(mp, map_table != maphash);
! did_it = TRUE;
}
! else // do we have a match?
{
! if (round) // second round: Try unmap "rhs" string
{
! n = (int)STRLEN(mp->m_str);
! p = mp->m_str;
}
! else
{
! n = mp->m_keylen;
! p = mp->m_keys;
}
! if (STRNCMP(p, keys, (size_t)(n < len ? n : len)) == 0)
{
! if (maptype == 1) // delete entry
{
! // Only accept a full match. For abbreviations we
! // ignore trailing space when matching with the
! // "lhs", since an abbreviation can't have
! // trailing space.
! if (n != len && (!abbrev || round || n > len
|| *skipwhite(keys + n) != NUL))
{
mpp = &(mp->m_next);
continue;
}
! // We reset the indicated mode bits. If nothing is
! // left the entry is deleted below.
! mp->m_mode &= ~mode;
! did_it = TRUE; // remember we did something
! }
! else if (!hasarg) // show matching entry
! {
! showmap(mp, map_table != maphash);
! did_it = TRUE;
! }
! else if (n != len) // new entry is ambiguous
! {
! mpp = &(mp->m_next);
! continue;
! }
! else if (unique)
! {
! if (abbrev)
! semsg(_("E226: abbreviation already exists for
%s"),
! p);
else
- semsg(_("E227: mapping already exists for %s"),
p);
- retval = 5;
- goto theend;
- }
- else // new rhs for existing entry
- {
- mp->m_mode &= ~mode; // remove mode bits
- if (mp->m_mode == 0 && !did_it) // reuse entry
{
! newstr = vim_strsave(rhs);
! if (newstr == NULL)
{
! retval = 4; // no mem
! goto theend;
! }
! vim_free(mp->m_str);
! mp->m_str = newstr;
! vim_free(mp->m_orig_str);
! mp->m_orig_str = vim_strsave(orig_rhs);
! mp->m_noremap = noremap;
! mp->m_nowait = nowait;
! mp->m_silent = silent;
! mp->m_mode = mode;
#ifdef FEAT_EVAL
! mp->m_expr = expr;
! mp->m_script_ctx = current_sctx;
! mp->m_script_ctx.sc_lnum += sourcing_lnum;
#endif
! did_it = TRUE;
}
- }
- if (mp->m_mode == 0) // entry can be deleted
- {
- map_free(mpp);
- continue; // continue with *mpp
- }
! // May need to put this entry into another hash list.
! new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
! if (!abbrev && new_hash != hash)
! {
! *mpp = mp->m_next;
! mp->m_next = map_table[new_hash];
! map_table[new_hash] = mp;
! continue; // continue with *mpp
}
}
}
- mpp = &(mp->m_next);
}
}
- }
! if (maptype == 1) // delete entry
! {
! if (!did_it)
! retval = 2; // no match
! else if (*keys == Ctrl_C)
{
! // If CTRL-C has been unmapped, reuse it for Interrupting.
! if (map_table == curbuf->b_maphash)
! curbuf->b_mapped_ctrl_c &= ~mode;
! else
! mapped_ctrl_c &= ~mode;
}
- goto theend;
- }
! if (!haskey || !hasarg) // print entries
! {
! if (!did_it && !did_local)
{
! if (abbrev)
! msg(_("No abbreviation found"));
! else
! msg(_("No mapping found"));
}
- goto theend; // listing finished
- }
! if (did_it) // have added the new entry already
! goto theend;
! // Get here when adding a new entry to the maphash[] list or abbrlist.
! mp = ALLOC_ONE(mapblock_T);
! if (mp == NULL)
! {
! retval = 4; // no mem
! goto theend;
! }
! // If CTRL-C has been mapped, don't always use it for Interrupting.
! if (*keys == Ctrl_C)
! {
! if (map_table == curbuf->b_maphash)
! curbuf->b_mapped_ctrl_c |= mode;
! else
! mapped_ctrl_c |= mode;
! }
! mp->m_keys = vim_strsave(keys);
! mp->m_str = vim_strsave(rhs);
! mp->m_orig_str = vim_strsave(orig_rhs);
! if (mp->m_keys == NULL || mp->m_str == NULL)
! {
! vim_free(mp->m_keys);
! vim_free(mp->m_str);
! vim_free(mp->m_orig_str);
! vim_free(mp);
! retval = 4; // no mem
! goto theend;
! }
! mp->m_keylen = (int)STRLEN(mp->m_keys);
! mp->m_noremap = noremap;
! mp->m_nowait = nowait;
! mp->m_silent = silent;
! mp->m_mode = mode;
#ifdef FEAT_EVAL
! mp->m_expr = expr;
! mp->m_script_ctx = current_sctx;
! mp->m_script_ctx.sc_lnum += sourcing_lnum;
#endif
! // add the new entry in front of the abbrlist or maphash[] list
! if (abbrev)
! {
! mp->m_next = *abbr_table;
! *abbr_table = mp;
! }
! else
! {
! n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
! mp->m_next = map_table[n];
! map_table[n] = mp;
}
theend:
vim_free(keys_buf);
vim_free(arg_buf);
return retval;
}
--- 388,814 ----
// replace_termcodes() may move the result to allocated memory, which
// needs to be freed later (*keys_buf and *arg_buf).
// replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
+ // If something like <C-H> is simplified to 0x08 then mark it as
simplified
+ // and also add a n entry with a modifier, which will work when
+ // modifyOtherKeys is working.
if (haskey)
! {
! char_u *new_keys;
! int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
!
! if (special)
! flags |= REPTERM_SPECIAL;
! new_keys = replace_termcodes(keys, &keys_buf, flags, &did_simplify);
! if (did_simplify)
! (void)replace_termcodes(keys, &alt_keys_buf,
! flags | REPTERM_NO_SIMPLIFY, NULL);
! keys = new_keys;
! }
orig_rhs = rhs;
if (hasarg)
{
if (STRICMP(rhs, "<nop>") == 0) // "<Nop>" means nothing
rhs = (char_u *)"";
else
! rhs = replace_termcodes(rhs, &arg_buf,
! REPTERM_DO_LT | (special ? REPTERM_SPECIAL : 0), NULL);
}
! /*
! * The following is done twice if we have two versions of keys:
! * "alt_keys_buf" is not NULL.
! */
! for (keyround = 1; keyround <= 2; ++keyround)
{
! int did_it = FALSE;
! int did_local = FALSE;
! int round;
! int hash;
! int new_hash;
!
! if (keyround == 2)
{
! if (alt_keys_buf == NULL)
! break;
! keys = alt_keys_buf;
}
+ else if (alt_keys_buf != NULL && do_print)
+ // when printing always use the not-simplified map
+ keys = alt_keys_buf;
! // check arguments and translate function keys
! if (haskey)
{
! len = (int)STRLEN(keys);
! if (len > MAXMAPLEN) // maximum length of MAXMAPLEN chars
{
! retval = 1;
! goto theend;
! }
! if (abbrev && maptype != 1)
! {
! // If an abbreviation ends in a keyword character, the
! // rest must be all keyword-char or all non-keyword-char.
! // Otherwise we won't be able to find the start of it in a
! // vi-compatible way.
! if (has_mbyte)
{
! int first, last;
! int same = -1;
!
! first = vim_iswordp(keys);
! last = first;
! p = keys + (*mb_ptr2len)(keys);
! n = 1;
! while (p < keys + len)
! {
! ++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
! p += (*mb_ptr2len)(p);
! }
! if (last && n > 2 && same >= 0 && same < n - 1)
! {
! retval = 1;
! goto theend;
! }
}
! else if (vim_iswordc(keys[len - 1]))
! // ends in keyword char
for (n = 0; n < len - 2; ++n)
if (vim_iswordc(keys[n]) != vim_iswordc(keys[len - 2]))
{
retval = 1;
goto theend;
}
! // An abbreviation cannot contain white space.
! for (n = 0; n < len; ++n)
! if (VIM_ISWHITE(keys[n]))
! {
! retval = 1;
! goto theend;
! }
! }
}
! if (haskey && hasarg && abbrev) // if we will add an abbreviation
! no_abbr = FALSE; // reset flag that indicates there are
// no abbreviations
! if (do_print)
! msg_start();
! // Check if a new local mapping wasn't already defined globally.
! if (map_table == curbuf->b_maphash && haskey && hasarg && maptype != 1)
{
! // need to loop over all global hash lists
! for (hash = 0; hash < 256 && !got_int; ++hash)
{
! if (abbrev)
{
! if (hash != 0) // there is only one abbreviation list
! break;
! mp = first_abbr;
! }
! else
! mp = maphash[hash];
! for ( ; mp != NULL && !got_int; mp = mp->m_next)
! {
! // check entries with the same mode
! if ((mp->m_mode & mode) != 0
! && mp->m_keylen == len
! && unique
! && STRNCMP(mp->m_keys, keys, (size_t)len) == 0)
! {
! if (abbrev)
! semsg(_(
! "E224: global abbreviation already exists for %s"),
! mp->m_keys);
! else
! semsg(_(
! "E225: global mapping already exists for %s"),
! mp->m_keys);
! retval = 5;
! goto theend;
! }
}
}
}
! // When listing global mappings, also list buffer-local ones here.
! if (map_table != curbuf->b_maphash && !hasarg && maptype != 1)
{
! // need to loop over all global hash lists
! for (hash = 0; hash < 256 && !got_int; ++hash)
{
! if (abbrev)
{
! if (hash != 0) // there is only one abbreviation list
! break;
! mp = curbuf->b_first_abbr;
! }
! else
! mp = curbuf->b_maphash[hash];
! for ( ; mp != NULL && !got_int; mp = mp->m_next)
! {
! // check entries with the same mode
! if ((mp->m_mode & mode) != 0)
{
! if (!haskey) // show all entries
{
showmap(mp, TRUE);
did_local = TRUE;
}
+ else
+ {
+ n = mp->m_keylen;
+ if (STRNCMP(mp->m_keys, keys,
+ (size_t)(n < len ? n : len)) == 0)
+ {
+ showmap(mp, TRUE);
+ did_local = TRUE;
+ }
+ }
}
}
}
}
! // Find an entry in the maphash[] list that matches.
! // For :unmap we may loop two times: once to try to unmap an entry with
! // a matching 'from' part, a second time, if the first fails, to unmap
! // an entry with a matching 'to' part. This was done to allow ":ab foo
! // bar" to be unmapped by typing ":unab foo", where "foo" will be
! // replaced by "bar" because of the abbreviation.
! for (round = 0; (round == 0 || maptype == 1) && round <= 1
! && !did_it && !got_int; ++round)
{
! // need to loop over all hash lists
! for (hash = 0; hash < 256 && !got_int; ++hash)
{
! if (abbrev)
{
! if (hash > 0) // there is only one abbreviation list
! break;
! mpp = abbr_table;
}
! else
! mpp = &(map_table[hash]);
! for (mp = *mpp; mp != NULL && !got_int; mp = *mpp)
{
!
! if (!(mp->m_mode & mode)) // skip entries with wrong mode
{
! mpp = &(mp->m_next);
! continue;
}
! if (!haskey) // show all entries
{
! showmap(mp, map_table != maphash);
! did_it = TRUE;
}
! else // do we have a match?
{
! if (round) // second round: Try unmap "rhs" string
{
! n = (int)STRLEN(mp->m_str);
! p = mp->m_str;
! }
! else
! {
! n = mp->m_keylen;
! p = mp->m_keys;
! }
! if (STRNCMP(p, keys, (size_t)(n < len ? n : len)) == 0)
! {
! if (maptype == 1)
! {
! // Delete entry.
! // Only accept a full match. For abbreviations
! // we ignore trailing space when matching with
! // the "lhs", since an abbreviation can't have
! // trailing space.
! if (n != len && (!abbrev || round || n > len
|| *skipwhite(keys + n) != NUL))
+ {
+ mpp = &(mp->m_next);
+ continue;
+ }
+ // We reset the indicated mode bits. If nothing
+ // is left the entry is deleted below.
+ mp->m_mode &= ~mode;
+ did_it = TRUE; // remember we did something
+ }
+ else if (!hasarg) // show matching entry
+ {
+ showmap(mp, map_table != maphash);
+ did_it = TRUE;
+ }
+ else if (n != len) // new entry is ambiguous
{
mpp = &(mp->m_next);
continue;
}
! else if (unique)
! {
! if (abbrev)
! semsg(_(
! "E226: abbreviation already exists for %s"),
! p);
! else
! semsg(_(
! "E227: mapping already exists for %s"),
! p);
! retval = 5;
! goto theend;
! }
else
{
! // new rhs for existing entry
! mp->m_mode &= ~mode; // remove mode bits
! if (mp->m_mode == 0 && !did_it) // reuse entry
{
! char_u *newstr = vim_strsave(rhs);
!
! if (newstr == NULL)
! {
! retval = 4; // no mem
! goto theend;
! }
! vim_free(mp->m_str);
! mp->m_str = newstr;
! vim_free(mp->m_orig_str);
! mp->m_orig_str = vim_strsave(orig_rhs);
! mp->m_noremap = noremap;
! mp->m_nowait = nowait;
! mp->m_silent = silent;
! mp->m_mode = mode;
! mp->m_simplified =
! did_simplify && keyround == 1;
#ifdef FEAT_EVAL
! mp->m_expr = expr;
! mp->m_script_ctx = current_sctx;
! mp->m_script_ctx.sc_lnum += sourcing_lnum;
#endif
! did_it = TRUE;
! }
! }
! if (mp->m_mode == 0) // entry can be deleted
! {
! map_free(mpp);
! continue; // continue with *mpp
}
! // May need to put this entry into another hash
! // list.
! new_hash = MAP_HASH(mp->m_mode, mp->m_keys[0]);
! if (!abbrev && new_hash != hash)
! {
! *mpp = mp->m_next;
! mp->m_next = map_table[new_hash];
! map_table[new_hash] = mp;
! continue; // continue with *mpp
! }
}
}
+ mpp = &(mp->m_next);
}
}
}
! if (maptype == 1)
{
! // delete entry
! if (!did_it)
! retval = 2; // no match
! else if (*keys == Ctrl_C)
! {
! // If CTRL-C has been unmapped, reuse it for Interrupting.
! if (map_table == curbuf->b_maphash)
! curbuf->b_mapped_ctrl_c &= ~mode;
! else
! mapped_ctrl_c &= ~mode;
! }
! continue;
}
! if (!haskey || !hasarg)
{
! // print entries
! if (!did_it && !did_local)
! {
! if (abbrev)
! msg(_("No abbreviation found"));
! else
! msg(_("No mapping found"));
! }
! goto theend; // listing finished
}
! if (did_it)
! continue; // have added the new entry already
! // Get here when adding a new entry to the maphash[] list or abbrlist.
! mp = ALLOC_ONE(mapblock_T);
! if (mp == NULL)
! {
! retval = 4; // no mem
! goto theend;
! }
! // If CTRL-C has been mapped, don't always use it for Interrupting.
! if (*keys == Ctrl_C)
! {
! if (map_table == curbuf->b_maphash)
! curbuf->b_mapped_ctrl_c |= mode;
! else
! mapped_ctrl_c |= mode;
! }
! mp->m_keys = vim_strsave(keys);
! mp->m_str = vim_strsave(rhs);
! mp->m_orig_str = vim_strsave(orig_rhs);
! if (mp->m_keys == NULL || mp->m_str == NULL)
! {
! vim_free(mp->m_keys);
! vim_free(mp->m_str);
! vim_free(mp->m_orig_str);
! vim_free(mp);
! retval = 4; // no mem
! goto theend;
! }
! mp->m_keylen = (int)STRLEN(mp->m_keys);
! mp->m_noremap = noremap;
! mp->m_nowait = nowait;
! mp->m_silent = silent;
! mp->m_mode = mode;
! mp->m_simplified = did_simplify && keyround == 1;
#ifdef FEAT_EVAL
! mp->m_expr = expr;
! mp->m_script_ctx = current_sctx;
! mp->m_script_ctx.sc_lnum += sourcing_lnum;
#endif
! // add the new entry in front of the abbrlist or maphash[] list
! if (abbrev)
! {
! mp->m_next = *abbr_table;
! *abbr_table = mp;
! }
! else
! {
! n = MAP_HASH(mp->m_mode, mp->m_keys[0]);
! mp->m_next = map_table[n];
! map_table[n] = mp;
! }
}
theend:
vim_free(keys_buf);
+ vim_free(alt_keys_buf);
vim_free(arg_buf);
return retval;
}
***************
*** 934,940 ****
char_u *buf;
int retval;
! rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE);
retval = map_to_exists_mode(rhs, mode_str2flags(modechars), abbr);
vim_free(buf);
--- 987,993 ----
char_u *buf;
int retval;
! rhs = replace_termcodes(str, &buf, REPTERM_DO_LT, NULL);
retval = map_to_exists_mode(rhs, mode_str2flags(modechars), abbr);
vim_free(buf);
***************
*** 2036,2042 ****
mode = get_map_mode(&which, 0);
! keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
vim_free(keys_buf);
--- 2089,2096 ----
mode = get_map_mode(&which, 0);
! keys = replace_termcodes(keys, &keys_buf,
! REPTERM_FROM_PART | REPTERM_DO_LT, NULL);
rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
vim_free(keys_buf);
*** ../vim-8.1.2144/src/menu.c 2019-08-20 20:13:40.326821952 +0200
--- src/menu.c 2019-10-12 21:51:21.328038913 +0200
***************
*** 372,378 ****
else if (modes & MENU_TIP_MODE)
map_buf = NULL; /* Menu tips are plain text. */
else
! map_to = replace_termcodes(map_to, &map_buf, FALSE, TRUE, special);
menuarg.modes = modes;
#ifdef FEAT_TOOLBAR
menuarg.iconfile = icon;
--- 372,379 ----
else if (modes & MENU_TIP_MODE)
map_buf = NULL; /* Menu tips are plain text. */
else
! map_to = replace_termcodes(map_to, &map_buf,
! REPTERM_DO_LT | (special ? REPTERM_SPECIAL : 0), NULL);
menuarg.modes = modes;
#ifdef FEAT_TOOLBAR
menuarg.iconfile = icon;
*** ../vim-8.1.2144/src/misc2.c 2019-10-12 16:12:50.968492825 +0200
--- src/misc2.c 2019-10-13 15:57:54.153813986 +0200
***************
*** 2696,2707 ****
char_u **srcp,
char_u *dst,
int keycode, // prefer key code, e.g. K_DEL instead of
DEL
! int in_string) // TRUE when inside a double quoted string
{
int modifiers = 0;
int key;
! key = find_special_key(srcp, &modifiers, keycode, FALSE, in_string);
if (key == 0)
return 0;
--- 2696,2710 ----
char_u **srcp,
char_u *dst,
int keycode, // prefer key code, e.g. K_DEL instead of
DEL
! int in_string, // TRUE when inside a double quoted string
! int simplify, // simplify <C-H> and <A-x>
! int *did_simplify) // found <C-H> or <A-x>
{
int modifiers = 0;
int key;
! key = find_special_key(srcp, &modifiers, keycode, FALSE, in_string,
! simplify, did_simplify);
if (key == 0)
return 0;
***************
*** 2753,2761 ****
find_special_key(
char_u **srcp,
int *modp,
! int keycode, /* prefer key code, e.g. K_DEL instead of
DEL */
! int keep_x_key, /* don't translate xHome to Home key */
! int in_string) /* TRUE in string, double quote is escaped
*/
{
char_u *last_dash;
char_u *end_of_name;
--- 2756,2766 ----
find_special_key(
char_u **srcp,
int *modp,
! int keycode, // prefer key code, e.g. K_DEL instead
of DEL
! int keep_x_key, // don't translate xHome to Home key
! int in_string, // TRUE in string, double quote is
escaped
! int simplify, // simplify <C-H> and <A-x>
! int *did_simplify) // found <C-H> or <A-x>
{
char_u *last_dash;
char_u *end_of_name;
***************
*** 2835,2841 ****
&& VIM_ISDIGIT(last_dash[6]))
{
/* <Char-123> or <Char-033> or <Char-0x33> */
! vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0,
TRUE);
if (l == 0)
{
emsg(_(e_invarg));
--- 2840,2847 ----
&& VIM_ISDIGIT(last_dash[6]))
{
/* <Char-123> or <Char-033> or <Char-0x33> */
! vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL,
! &n, 0, TRUE);
if (l == 0)
{
emsg(_(e_invarg));
***************
*** 2885,2895 ****
key = DEL;
}
! /*
! * Normal Key with modifier: Try to make a single byte code.
! */
if (!IS_SPECIAL(key))
! key = extract_modifiers(key, &modifiers);
*modp = modifiers;
*srcp = end_of_name;
--- 2891,2900 ----
key = DEL;
}
! // Normal Key with modifier: Try to make a single byte code.
if (!IS_SPECIAL(key))
! key = extract_modifiers(key, &modifiers,
! simplify, did_simplify);
*modp = modifiers;
*srcp = end_of_name;
***************
*** 2903,2928 ****
/*
* Try to include modifiers in the key.
* Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
*/
int
! extract_modifiers(int key, int *modp)
{
int modifiers = *modp;
#ifdef MACOS_X
! /* Command-key really special, no fancynest */
if (!(modifiers & MOD_MASK_CMD))
#endif
if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
{
key = TOUPPER_ASC(key);
! modifiers &= ~MOD_MASK_SHIFT;
}
! if ((modifiers & MOD_MASK_CTRL)
#ifdef EBCDIC
! /* * TODO: EBCDIC Better use:
! * && (Ctrl_chr(key) || key == '?')
! * ??? */
&& strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key)
!= NULL
#else
--- 2908,2944 ----
/*
* Try to include modifiers in the key.
* Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
+ * When "simplify" is FALSE don't do Ctrl and Alt.
+ * When "simplify" is TRUE and Ctrl or Alt is removed from modifiers set
+ * "did_simplify" when it's not NULL.
*/
int
! extract_modifiers(int key, int *modp, int simplify, int *did_simplify)
{
int modifiers = *modp;
#ifdef MACOS_X
! // Command-key really special, no fancynest
if (!(modifiers & MOD_MASK_CMD))
#endif
if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
{
key = TOUPPER_ASC(key);
! // With <C-S-a> and <A-S-a> we keep the shift modifier.
! // With <S-a> and <S-A> we don't keep the shift modifier.
! if (simplify || modifiers == MOD_MASK_SHIFT)
! modifiers &= ~MOD_MASK_SHIFT;
}
!
! // <C-H> and <C-h> mean the same thing, always use "H"
! if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key))
! key = TOUPPER_ASC(key);
!
! if (simplify && (modifiers & MOD_MASK_CTRL)
#ifdef EBCDIC
! // TODO: EBCDIC Better use:
! // && (Ctrl_chr(key) || key == '?')
! // ???
&& strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key)
!= NULL
#else
***************
*** 2935,2950 ****
/* <C-@> is <Nul> */
if (key == 0)
key = K_ZERO;
}
#ifdef MACOS_X
/* Command-key really special, no fancynest */
if (!(modifiers & MOD_MASK_CMD))
#endif
! if ((modifiers & MOD_MASK_ALT) && key < 0x80
&& !enc_dbcs) // avoid creating a lead byte
{
key |= 0x80;
modifiers &= ~MOD_MASK_ALT; /* remove the META modifier */
}
*modp = modifiers;
--- 2951,2971 ----
/* <C-@> is <Nul> */
if (key == 0)
key = K_ZERO;
+ if (did_simplify != NULL)
+ *did_simplify = TRUE;
}
+
#ifdef MACOS_X
/* Command-key really special, no fancynest */
if (!(modifiers & MOD_MASK_CMD))
#endif
! if (simplify && (modifiers & MOD_MASK_ALT) && key < 0x80
&& !enc_dbcs) // avoid creating a lead byte
{
key |= 0x80;
modifiers &= ~MOD_MASK_ALT; /* remove the META modifier */
+ if (did_simplify != NULL)
+ *did_simplify = TRUE;
}
*modp = modifiers;
*** ../vim-8.1.2144/src/option.c 2019-10-05 21:35:12.228950931 +0200
--- src/option.c 2019-10-12 22:53:38.777040254 +0200
***************
*** 4495,4501 ****
{
--arg; /* put arg at the '<' */
modifiers = 0;
! key = find_special_key(&arg, &modifiers, TRUE, TRUE, FALSE);
if (modifiers) /* can't handle modifiers here */
key = 0;
}
--- 4495,4501 ----
{
--arg; /* put arg at the '<' */
modifiers = 0;
! key = find_special_key(&arg, &modifiers, TRUE, TRUE, FALSE, TRUE, NULL);
if (modifiers) /* can't handle modifiers here */
key = 0;
}
*** ../vim-8.1.2144/src/proto/misc2.pro 2019-09-21 20:46:14.728275744 +0200
--- src/proto/misc2.pro 2019-10-12 22:55:37.116647113 +0200
***************
*** 67,76 ****
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 keycode, int in_string);
int special_to_buf(int key, int modifiers, int keycode, char_u *dst);
! int find_special_key(char_u **srcp, int *modp, int keycode, int keep_x_key,
int in_string);
! int extract_modifiers(int key, int *modp);
int find_special_key_in_table(int c);
int get_special_key_code(char_u *name);
char_u *get_key_name(int i);
--- 67,76 ----
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 keycode, int in_string, int
simplify, int *did_simplify);
int special_to_buf(int key, int modifiers, int keycode, char_u *dst);
! int find_special_key(char_u **srcp, int *modp, int keycode, int keep_x_key,
int in_string, int simplify, int *did_simplify);
! int extract_modifiers(int key, int *modp, int simplify, int *did_simplify);
int find_special_key_in_table(int c);
int get_special_key_code(char_u *name);
char_u *get_key_name(int i);
*** ../vim-8.1.2144/src/proto/term.pro 2019-09-23 21:16:51.387544361 +0200
--- src/proto/term.pro 2019-10-12 21:47:56.652964165 +0200
***************
*** 67,73 ****
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);
void term_get_bg_color(char_u *r, char_u *g, char_u *b);
! char_u *replace_termcodes(char_u *from, char_u **bufp, int from_part, int
do_lt, int special);
void show_termcodes(void);
int show_one_termcode(char_u *name, char_u *code, int printit);
char_u *translate_mapping(char_u *str);
--- 67,73 ----
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);
void term_get_bg_color(char_u *r, char_u *g, char_u *b);
! char_u *replace_termcodes(char_u *from, char_u **bufp, int flags, int
*did_simplify);
void show_termcodes(void);
int show_one_termcode(char_u *name, char_u *code, int printit);
char_u *translate_mapping(char_u *str);
*** ../vim-8.1.2144/src/testdir/test_termcodes.vim 2019-10-12
18:22:46.957511288 +0200
--- src/testdir/test_termcodes.vim 2019-10-13 16:37:26.833546697 +0200
***************
*** 862,868 ****
" The mode doesn't need to be enabled, the codes are always detected.
func RunTest_modifyOtherKeys(func)
new
! set timeoutlen=20
" Shift-X is send as 'X' with the shift modifier
call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!')
--- 862,868 ----
" The mode doesn't need to be enabled, the codes are always detected.
func RunTest_modifyOtherKeys(func)
new
! set timeoutlen=10
" Shift-X is send as 'X' with the shift modifier
call feedkeys('a' .. a:func('X', 2) .. "\<Esc>", 'Lx!')
***************
*** 902,912 ****
set timeoutlen&
endfunc
! func Test_modifyOtherKeys_CSI27()
call RunTest_modifyOtherKeys(function('GetEscCodeCSI27'))
- endfunc
-
- func Test_modifyOtherKeys_CSIu()
call RunTest_modifyOtherKeys(function('GetEscCodeCSIu'))
endfunc
--- 902,909 ----
set timeoutlen&
endfunc
! func Test_modifyOtherKeys_basic()
call RunTest_modifyOtherKeys(function('GetEscCodeCSI27'))
call RunTest_modifyOtherKeys(function('GetEscCodeCSIu'))
endfunc
***************
*** 928,934 ****
func RunTest_mapping_works_with_shift(func)
new
! set timeoutlen=20
call RunTest_mapping_shift('@', a:func)
call RunTest_mapping_shift('A', a:func)
--- 925,931 ----
func RunTest_mapping_works_with_shift(func)
new
! set timeoutlen=10
call RunTest_mapping_shift('@', a:func)
call RunTest_mapping_shift('A', a:func)
***************
*** 944,950 ****
set timeoutlen&
endfunc
! func Test_mapping_works_with_shift()
call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27'))
call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu'))
endfunc
--- 941,1028 ----
set timeoutlen&
endfunc
! func Test_mapping_works_with_shift_plain()
call RunTest_mapping_works_with_shift(function('GetEscCodeCSI27'))
call RunTest_mapping_works_with_shift(function('GetEscCodeCSIu'))
endfunc
+
+ func RunTest_mapping_mods(map, key, func, code)
+ call setline(1, '')
+ exe 'inoremap ' .. a:map .. ' xyz'
+ call feedkeys('a' .. a:func(a:key, a:code) .. "\<Esc>", 'Lx!')
+ call assert_equal("xyz", getline(1))
+ exe 'iunmap ' .. a:map
+ endfunc
+
+ func RunTest_mapping_works_with_mods(func, mods, code)
+ new
+ set timeoutlen=10
+
+ if a:mods !~ 'S'
+ " Shift by itself has no effect
+ call RunTest_mapping_mods('<' .. a:mods .. '-@>', '@', a:func, a:code)
+ endif
+ call RunTest_mapping_mods('<' .. a:mods .. '-A>', 'A', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-Z>', 'Z', a:func, a:code)
+ if a:mods !~ 'S'
+ " with Shift code is always upper case
+ call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'a', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'z', a:func, a:code)
+ endif
+ if a:mods != 'A'
+ " with Alt code is not in upper case
+ call RunTest_mapping_mods('<' .. a:mods .. '-a>', 'A', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-z>', 'Z', a:func, a:code)
+ endif
+ call RunTest_mapping_mods('<' .. a:mods .. '-á>', 'á', a:func, a:code)
+ if a:mods !~ 'S'
+ " Shift by itself has no effect
+ call RunTest_mapping_mods('<' .. a:mods .. '-^>', '^', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-_>', '_', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-{>', '{', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-\|>', '|', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-}>', '}', a:func, a:code)
+ call RunTest_mapping_mods('<' .. a:mods .. '-~>', '~', a:func, a:code)
+ endif
+
+ bwipe!
+ set timeoutlen&
+ endfunc
+
+ func Test_mapping_works_with_shift()
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S', 2)
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S', 2)
+ endfunc
+
+ func Test_mapping_works_with_ctrl()
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5)
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5)
+ endfunc
+
+ func Test_mapping_works_with_shift_ctrl()
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6)
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6)
+ endfunc
+
+ " Below we also test the "u" code with Alt, This works, but libvterm would not
+ " send the Alt key like this but by prefixing an Esc.
+
+ func Test_mapping_works_with_alt()
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'A', 3)
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'A', 3)
+ endfunc
+
+ func Test_mapping_works_with_shift_alt()
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'S-A', 4)
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'S-A', 4)
+ endfunc
+
+ func Test_mapping_works_with_ctrl_alt()
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-A', 7)
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-A', 7)
+ endfunc
+
+ func Test_mapping_works_with_shift_ctrl_alt()
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S-A',
8)
+ call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S-A', 8)
+ endfunc
*** ../vim-8.1.2144/src/structs.h 2019-10-09 22:01:20.599438001 +0200
--- src/structs.h 2019-10-13 12:42:34.776055302 +0200
***************
*** 1172,1177 ****
--- 1172,1179 ----
char_u *m_orig_str; // rhs as entered by the user
int m_keylen; // strlen(m_keys)
int m_mode; // valid mode
+ int m_simplified; // m_keys was simplified, do not use
this map
+ // if seenModifyOtherKeys is TRUE
int m_noremap; // if non-zero no re-mapping for m_str
char m_silent; // <silent> used, don't echo commands
char m_nowait; // <nowait> used
*** ../vim-8.1.2144/src/terminal.c 2019-10-10 21:13:59.962360351 +0200
--- src/terminal.c 2019-10-13 13:46:43.253595570 +0200
***************
*** 772,778 ****
p = skiptowhite(cmd);
*p = NUL;
! keys = replace_termcodes(ep + 1, &buf, TRUE, TRUE, TRUE);
opt.jo_set2 |= JO2_EOF_CHARS;
opt.jo_eof_chars = vim_strsave(keys);
vim_free(buf);
--- 772,779 ----
p = skiptowhite(cmd);
*p = NUL;
! keys = replace_termcodes(ep + 1, &buf,
! REPTERM_FROM_PART | REPTERM_DO_LT | REPTERM_SPECIAL, NULL);
opt.jo_set2 |= JO2_EOF_CHARS;
opt.jo_eof_chars = vim_strsave(keys);
vim_free(buf);
***************
*** 1372,1378 ****
}
// add modifiers for the typed key
! mod |= mod_mask;
/*
* Convert special keys to vterm keys:
--- 1373,1384 ----
}
// add modifiers for the typed key
! if (mod_mask & MOD_MASK_SHIFT)
! mod |= VTERM_MOD_SHIFT;
! if (mod_mask & MOD_MASK_CTRL)
! mod |= VTERM_MOD_CTRL;
! if (mod_mask & (MOD_MASK_ALT | MOD_MASK_META))
! mod |= VTERM_MOD_ALT;
/*
* Convert special keys to vterm keys:
*** ../vim-8.1.2144/src/usercmd.c 2019-08-18 22:25:54.669447972 +0200
--- src/usercmd.c 2019-10-12 21:52:36.699707297 +0200
***************
*** 868,874 ****
char_u *rep_buf = NULL;
garray_T *gap;
! replace_termcodes(rep, &rep_buf, FALSE, FALSE, FALSE);
if (rep_buf == NULL)
{
// Can't replace termcodes - try using the string as is
--- 868,874 ----
char_u *rep_buf = NULL;
garray_T *gap;
! replace_termcodes(rep, &rep_buf, 0, NULL);
if (rep_buf == NULL)
{
// Can't replace termcodes - try using the string as is
*** ../vim-8.1.2144/src/vim.h 2019-09-21 20:46:14.728275744 +0200
--- src/vim.h 2019-10-12 21:47:07.149194164 +0200
***************
*** 2633,2636 ****
--- 2633,2642 ----
#define CLIP_ZINDEX 32000
+ // Flags for replace_termcodes()
+ #define REPTERM_FROM_PART 1
+ #define REPTERM_DO_LT 2
+ #define REPTERM_SPECIAL 4
+ #define REPTERM_NO_SIMPLIFY 8
+
#endif // VIM__H
*** ../vim-8.1.2144/src/version.c 2019-10-12 21:08:37.006660412 +0200
--- src/version.c 2019-10-13 16:40:35.672957071 +0200
***************
*** 755,756 ****
--- 755,758 ----
{ /* Add new patch number below this line */
+ /**/
+ 2145,
/**/
--
Kisses may last for as much as, but no more than, five minutes.
[real standing law in Iowa, United States of America]
/// Bram Moolenaar -- [email protected] -- 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 ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/201910131444.x9DEiC6V027985%40masaka.moolenaar.net.