summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-10-13 16:43:39 +0200
committerBram Moolenaar <Bram@vim.org>2019-10-13 16:43:39 +0200
commit459fd785e4a8d044147a3f83a5fca8748528aa84 (patch)
tree52c679e08a445bac0f650bff4d8118d6eb190d7b
parent171a921b51101c1261040d28a8147c8829b675d3 (diff)
patch 8.1.2145: cannot map <C-H> when modifyOtherKeys is enabledv8.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.
-rw-r--r--src/eval.c3
-rw-r--r--src/getchar.c5
-rw-r--r--src/globals.h4
-rw-r--r--src/gui_mac.c6
-rw-r--r--src/gui_w32.c2
-rw-r--r--src/highlight.c3
-rw-r--r--src/if_ole.cpp2
-rw-r--r--src/main.c2
-rw-r--r--src/map.c616
-rw-r--r--src/menu.c3
-rw-r--r--src/misc2.c57
-rw-r--r--src/option.c2
-rw-r--r--src/proto/misc2.pro6
-rw-r--r--src/proto/term.pro2
-rw-r--r--src/structs.h2
-rw-r--r--src/term.c45
-rw-r--r--src/terminal.c10
-rw-r--r--src/testdir/test_termcodes.vim92
-rw-r--r--src/usercmd.c2
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h6
21 files changed, 535 insertions, 337 deletions
diff --git a/src/eval.c b/src/eval.c
index 0fe8fd34aa..ace1e013f5 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3526,7 +3526,8 @@ get_string_tv(char_u **arg, typval_T *rettv, int evaluate)
break;
/* Special key, e.g.: "\<C-W>" */
- case '<': extra = trans_special(&p, name, TRUE, TRUE);
+ case '<': extra = trans_special(&p, name, TRUE, TRUE,
+ TRUE, NULL);
if (extra != 0)
{
name += extra;
diff --git a/src/getchar.c b/src/getchar.c
index 0e4e3c3157..475bfca8e1 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -52,7 +52,7 @@ static int typeahead_char = 0; /* typeahead char that's not flushed */
*/
static int block_redo = FALSE;
-static int KeyNoremap = 0; /* remapping flags */
+static int KeyNoremap = 0; // remapping flags
/*
* Variables used by vgetorpeek() and flush_buffers().
@@ -1771,7 +1771,7 @@ vgetc(void)
if (!no_reduce_keys)
{
// A modifier was not used for a mapping, apply it to ASCII
- // keys.
+ // keys. Shift would already have been applied.
if ((mod_mask & MOD_MASK_CTRL)
&& ((c >= '`' && c <= 0x7f)
|| (c >= '@' && c <= '_')))
@@ -2240,6 +2240,7 @@ handle_mapping(
// 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
diff --git a/src/globals.h b/src/globals.h
index d790c82e78..014fca2ad4 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1002,6 +1002,10 @@ EXTERN int ex_no_reprint INIT(= FALSE); // no need to print after z or p
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
diff --git a/src/gui_mac.c b/src/gui_mac.c
index b43ed8506f..185cdee28e 100644
--- a/src/gui_mac.c
+++ b/src/gui_mac.c
@@ -2177,7 +2177,8 @@ gui_mac_unicode_key_event(
key_char = simplify_key(key_char, (int *)&vimModifiers);
/* Interpret META, include SHIFT, etc. */
- key_char = extract_modifiers(key_char, (int *)&vimModifiers);
+ key_char = extract_modifiers(key_char, (int *)&vimModifiers,
+ TRUE, NULL);
if (key_char == CSI)
key_char = K_CSI;
@@ -4772,7 +4773,8 @@ gui_mch_add_menu_item(vimmenu_T *menu, int idx)
char_u *p_actext;
p_actext = menu->actext;
- key = find_special_key(&p_actext, &modifiers, FALSE, FALSE, FALSE);
+ 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
diff --git a/src/gui_w32.c b/src/gui_w32.c
index 61b09e1395..ae47873e4e 100644
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -850,7 +850,7 @@ _OnSysChar(
modifiers &= ~MOD_MASK_SHIFT;
/* Interpret the ALT key as making the key META, include SHIFT, etc. */
- ch = extract_modifiers(ch, &modifiers);
+ ch = extract_modifiers(ch, &modifiers, TRUE, NULL);
if (ch == CSI)
ch = K_CSI;
diff --git a/src/highlight.c b/src/highlight.c
index 0fdd93a267..1333362dbd 100644
--- a/src/highlight.c
+++ b/src/highlight.c
@@ -1417,7 +1417,8 @@ do_highlight(
*/
for (p = arg, off = 0; off < 100 - 6 && *p; )
{
- len = trans_special(&p, buf + off, FALSE, FALSE);
+ len = trans_special(&p, buf + off, FALSE, FALSE,
+ TRUE, NULL);
if (len > 0) // recognized special char
off += len;
else // copy as normal char
diff --git a/src/if_ole.cpp b/src/if_ole.cpp
index cb643e5461..34ce232660 100644
--- a/src/if_ole.cpp
+++ b/src/if_ole.cpp
@@ -330,7 +330,7 @@ CVim::SendKeys(BSTR keys)
}
/* Translate key codes like <Esc> */
- str = replace_termcodes((char_u *)buffer, &ptr, FALSE, TRUE, FALSE);
+ 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.
diff --git a/src/main.c b/src/main.c
index 33ac89c097..5545cc48a6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4339,7 +4339,7 @@ server_to_input_buf(char_u *str)
* <lt> sequence is recognised - needed for a real backslash.
*/
p_cpo = (char_u *)"Bk";
- str = replace_termcodes((char_u *)str, &ptr, FALSE, TRUE, FALSE);
+ str = replace_termcodes((char_u *)str, &ptr, REPTERM_DO_LT, NULL);
p_cpo = cpo_save;
if (*ptr != NUL) /* trailing CTRL-V results in nothing */
diff --git a/src/map.c b/src/map.c
index df8cbedb1f..00f4608b07 100644
--- a/src/map.c
+++ b/src/map.c
@@ -256,18 +256,15 @@ do_map(
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;
+ 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;
- int hash;
- int new_hash;
mapblock_T **abbr_table;
mapblock_T **map_table;
int unique = FALSE;
@@ -277,6 +274,7 @@ do_map(
#ifdef FEAT_EVAL
int expr = FALSE;
#endif
+ int did_simplify = FALSE;
int noremap;
char_u *orig_rhs;
@@ -375,6 +373,7 @@ do_map(
rhs = p;
hasarg = (*rhs != NUL);
haskey = (*keys != NUL);
+ do_print = !haskey || (maptype != 1 && !hasarg);
// check for :unmap without argument
if (maptype == 1 && !haskey)
@@ -389,373 +388,427 @@ do_map(
// 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)
- keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special);
+ {
+ 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, FALSE, TRUE, special);
+ rhs = replace_termcodes(rhs, &arg_buf,
+ REPTERM_DO_LT | (special ? REPTERM_SPECIAL : 0), NULL);
}
- // check arguments and translate function keys
- if (haskey)
+ /*
+ * The following is done twice if we have two versions of keys:
+ * "alt_keys_buf" is not NULL.
+ */
+ for (keyround = 1; keyround <= 2; ++keyround)
{
- len = (int)STRLEN(keys);
- if (len > MAXMAPLEN) // maximum length of MAXMAPLEN chars
+ int did_it = FALSE;
+ int did_local = FALSE;
+ int round;
+ int hash;
+ int new_hash;
+
+ if (keyround == 2)
{
- retval = 1;
- goto theend;
+ 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;
- if (abbrev && maptype != 1)
+ // check arguments and translate function keys
+ if (haskey)
{
- // 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)
+ len = (int)STRLEN(keys);
+ if (len > MAXMAPLEN) // maximum length of MAXMAPLEN chars
{
- 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;
+ }
+
+ 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)
{
- retval = 1;
- goto theend;
+ 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
+ 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;
- }
+ // 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
+ 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();
+ 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)
+ // Check if a new local mapping wasn't already defined globally.
+ if (map_table == curbuf->b_maphash && haskey && hasarg && maptype != 1)
{
- 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)
+ // need to loop over all global hash lists
+ for (hash = 0; hash < 256 && !got_int; ++hash)
{
- // 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)
{
- 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;
+ 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)
+ // When listing global mappings, also list buffer-local ones here.
+ if (map_table != curbuf->b_maphash && !hasarg && maptype != 1)
{
- 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)
+ // need to loop over all global hash lists
+ for (hash = 0; hash < 256 && !got_int; ++hash)
{
- // check entries with the same mode
- if ((mp->m_mode & mode) != 0)
+ if (abbrev)
{
- if (!haskey) // show all entries
- {
- showmap(mp, TRUE);
- did_local = TRUE;
- }
- else
+ 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)
{
- n = mp->m_keylen;
- if (STRNCMP(mp->m_keys, keys,
- (size_t)(n < len ? n : len)) == 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)
+ // 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)
{
- if (abbrev)
+ // need to loop over all hash lists
+ for (hash = 0; hash < 256 && !got_int; ++hash)
{
- 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
+ if (abbrev)
{
- mpp = &(mp->m_next);
- continue;
- }
- if (!haskey) // show all entries
- {
- showmap(mp, map_table != maphash);
- did_it = TRUE;
+ if (hash > 0) // there is only one abbreviation list
+ break;
+ mpp = abbr_table;
}
- else // do we have a match?
+ else
+ mpp = &(map_table[hash]);
+ for (mp = *mpp; mp != NULL && !got_int; mp = *mpp)
{
- if (round) // second round: Try unmap "rhs" string
+
+ if (!(mp->m_mode & mode)) // skip entries with wrong mode
{
- n = (int)STRLEN(mp->m_str);
- p = mp->m_str;
+ mpp = &(mp->m_next);
+ continue;
}
- else
+ if (!haskey) // show all entries
{
- n = mp->m_keylen;
- p = mp->m_keys;
+ showmap(mp, map_table != maphash);
+ did_it = TRUE;
}
- if (STRNCMP(p, keys, (size_t)(n < len ? n : len)) == 0)
+ else // do we have a match?
{
- if (maptype == 1) // delete entry
+ if (round) // second round: Try unmap "rhs" string
{
- // 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
+ 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;
}
- // 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 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
- 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)
+ // new rhs for existing entry
+ mp->m_mode &= ~mode; // remove mode bits
+ if (mp->m_mode == 0 && !did_it) // reuse entry
{
- 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;
+ 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;
+ mp->m_expr = expr;
+ mp->m_script_ctx = current_sctx;
+ mp->m_script_ctx.sc_lnum += sourcing_lnum;
#endif
- did_it = TRUE;
+ did_it = TRUE;
+ }
+ }
+ if (mp->m_mode == 0) // entry can be deleted
+ {
+ map_free(mpp);
+ continue; // continue with *mpp
}
- }
- 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;
+ // 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
+ continue; // continue with *mpp
+ }
}
}
+ mpp = &(mp->m_next);
}
- mpp = &(mp->m_next);
}
}
- }
- if (maptype == 1) // delete entry
- {
- if (!did_it)
- retval = 2; // no match
- else if (*keys == Ctrl_C)
+ if (maptype == 1)
{
- // 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;
+ // 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;
}
- goto theend;
- }
- if (!haskey || !hasarg) // print entries
- {
- if (!did_it && !did_local)
+ if (!haskey || !hasarg)
{
- if (abbrev)
- msg(_("No abbreviation found"));
- else
- msg(_("No mapping found"));
+ // print entries
+ if (!did_it && !did_local)
+ {
+ if (abbrev)
+ msg(_("No abbreviation found"));
+ else
+ msg(_("No mapping found"));
+ }
+ goto theend; // listing finished
}
- goto theend; // listing finished
- }
- if (did_it) // have added the new entry already
- goto theend;
+ 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;
- }
+ // 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;
- }
+ // 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_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;
+ 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;
+ // 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,7 +987,7 @@ map_to_exists(char_u *str, char_u *modechars, int abbr)
char_u *buf;
int retval;
- rhs = replace_termcodes(str, &buf, FALSE, TRUE, FALSE);
+ rhs = replace_termcodes(str, &buf, REPTERM_DO_LT, NULL);
retval = map_to_exists_mode(rhs, mode_str2flags(modechars), abbr);
vim_free(buf);
@@ -2036,7 +2089,8 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
mode = get_map_mode(&which, 0);
- keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
+ 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);
diff --git a/src/menu.c b/src/menu.c
index 4096a0571c..e55cab6758 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -372,7 +372,8 @@ ex_menu(
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);
+ 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;
diff --git a/src/misc2.c b/src/misc2.c
index 3261437db2..67fa8b5eed 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -2696,12 +2696,15 @@ trans_special(
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 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);
+ key = find_special_key(srcp, &modifiers, keycode, FALSE, in_string,
+ simplify, did_simplify);
if (key == 0)
return 0;
@@ -2753,9 +2756,11 @@ special_to_buf(int key, int modifiers, int keycode, char_u *dst)
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 keycode, // prefer key code, e.g. K_DEL instead of DEL
+ int keep_x_key, // don't tr