changeset 31776:1e21d10ceb58 v9.0.1220

patch 9.0.1220: termcap/terminfo entries do not indicate possible modifiers Commit: https://github.com/vim/vim/commit/4aecaa168e90cf28da7a6facea6b11ae250a8a18 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jan 18 17:20:25 2023 +0000 patch 9.0.1220: termcap/terminfo entries do not indicate possible modifiers Problem: Termcap/terminfo entries do not indicate where modifiers might appear. Solution: Add ";*" for function keys where modifiers are likely to be used.
author Bram Moolenaar <Bram@vim.org>
date Wed, 18 Jan 2023 18:30:02 +0100
parents 9305dcf37660
children 84bb462086cf
files src/term.c src/version.c
diffstat 2 files changed, 73 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/src/term.c
+++ b/src/term.c
@@ -65,6 +65,7 @@ static void del_termcode_idx(int idx);
 static int find_term_bykeys(char_u *src);
 static int term_is_builtin(char_u *name);
 static int term_7to8bit(char_u *p);
+static void accept_modifiers_for_function_keys(void);
 
     // Change this to "if 1" to debug what happens with termresponse.
 #  if 0
@@ -2097,6 +2098,11 @@ set_termname(char_u *term)
 		&& term_strings_not_set(KS_8U))
 	    apply_builtin_tcap(term, builtin_rgb, TRUE);
 #endif
+
+	if (kpc != KEYPROTOCOL_NONE)
+	    // Some function keys may accept modifiers even though the
+	    // terminfo/termcap entry does not indicate this.
+	    accept_modifiers_for_function_keys();
     }
 
 /*
@@ -2212,6 +2218,9 @@ set_termname(char_u *term)
 
 #ifdef FEAT_MOUSE_XTERM
     // Focus reporting is supported by xterm compatible terminals and tmux.
+    // We hard-code the received escape sequences here.  There are the terminfo
+    // entries kxIN and kxOUT, but they are rarely used and do hot have a
+    // two-letter termcap name.
     if (use_xterm_like_mouse(term))
     {
 	char_u name[3];
@@ -4471,6 +4480,25 @@ clear_termcodes(void)
 #define ATC_FROM_TERM 55
 
 /*
+ * For xterm we recognize special codes like "ESC[42;*X" and "ESC O*X" that
+ * accept modifiers.
+ * Set "termcodes[idx].modlen".
+ */
+    static void
+adjust_modlen(int idx)
+{
+    termcodes[idx].modlen = 0;
+    int j = termcode_star(termcodes[idx].code, termcodes[idx].len);
+    if (j <= 0)
+	return;
+
+    termcodes[idx].modlen = termcodes[idx].len - 1 - j;
+    // For "CSI[@;X" the "@" is not included in "modlen".
+    if (termcodes[idx].code[termcodes[idx].modlen - 1] == '@')
+	--termcodes[idx].modlen;
+}
+
+/*
  * Add a new entry for "name[2]" to the list of terminal codes.
  * Note that "name" may not have a terminating NUL.
  * The list is kept alphabetical for ":set termcap"
@@ -4618,19 +4646,51 @@ add_termcode(char_u *name, char_u *strin
     termcodes[i].name[1] = name[1];
     termcodes[i].code = s;
     termcodes[i].len = len;
-
-    // For xterm we recognize special codes like "ESC[42;*X" and "ESC O*X" that
-    // accept modifiers.
-    termcodes[i].modlen = 0;
-    j = termcode_star(s, len);
-    if (j > 0)
+    adjust_modlen(i);
+
+    ++tc_len;
+}
+
+/*
+ * Some function keys may include modifiers, but the terminfo/termcap entries
+ * do not indicate that.  Insert ";*" where we expect modifiers might appear.
+ */
+    static void
+accept_modifiers_for_function_keys(void)
+{
+    regmatch_T regmatch;
+    CLEAR_FIELD(regmatch);
+    regmatch.rm_ic = TRUE;
+    regmatch.regprog = vim_regcomp((char_u *)"^\033[\\d\\+\\~$", RE_MAGIC);
+
+    for (int i = 0; i < tc_len; ++i)
     {
-	termcodes[i].modlen = len - 1 - j;
-	// For "CSI[@;X" the "@" is not included in "modlen".
-	if (termcodes[i].code[termcodes[i].modlen - 1] == '@')
-	    --termcodes[i].modlen;
+	if (regmatch.regprog == NULL)
+	    return;
+
+	// skip PasteStart and PasteEnd
+	if (termcodes[i].name[0] == 'P'
+		&& (termcodes[i].name[1] == 'S' || termcodes[i].name[1] == 'E'))
+	    continue;
+
+	char_u *s = termcodes[i].code;
+	if (s != NULL && vim_regexec(&regmatch, s, (colnr_T)0))
+	{
+	    size_t len = STRLEN(s);
+	    char_u *ns = alloc(len + 3);
+	    if (ns != NULL)
+	    {
+		mch_memmove(ns, s, len - 1);
+		mch_memmove(ns + len - 1, ";*~", 4);
+		vim_free(s);
+		termcodes[i].code = ns;
+		termcodes[i].len += 2;
+		adjust_modlen(i);
+	    }
+	}
     }
-    ++tc_len;
+
+    vim_regfree(regmatch.regprog);
 }
 
 /*
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1220,
+/**/
     1219,
 /**/
     1218,