changeset 18508:3cd689e9eb7f v8.1.2248

patch 8.1.2248: CTRL-W dot does not work when modifyOtherKeys is enabled Commit: https://github.com/vim/vim/commit/1e814bc017907209a66af82f8fb76c6d1fc324aa Author: Bram Moolenaar <Bram@vim.org> Date: Sun Nov 3 21:19:41 2019 +0100 patch 8.1.2248: CTRL-W dot does not work when modifyOtherKeys is enabled Problem: CTRL-W dot does not work in a terminal when modifyOtherKeys is enabled. Solution: Use the modifier when needed. Pass the modifier along with the key to avoid mistakes.
author Bram Moolenaar <Bram@vim.org>
date Sun, 03 Nov 2019 21:30:04 +0100
parents 5cab7eef0829
children 2fa136c5b011
files src/mouse.c src/proto/terminal.pro src/terminal.c src/version.c
diffstat 4 files changed, 68 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -2012,7 +2012,7 @@ nv_mousescroll(cmdarg_T *cap)
 	if (term_use_loop())
 	    // This window is a terminal window, send the mouse event there.
 	    // Set "typed" to FALSE to avoid an endless loop.
-	    send_keys_to_term(curbuf->b_term, cap->cmdchar, FALSE);
+	    send_keys_to_term(curbuf->b_term, cap->cmdchar, mod_mask, FALSE);
 	else
 # endif
 	if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
--- a/src/proto/terminal.pro
+++ b/src/proto/terminal.pro
@@ -13,7 +13,7 @@ int term_try_stop_job(buf_T *buf);
 int term_check_timers(int next_due_arg, proftime_T *now);
 int term_in_normal_mode(void);
 void term_enter_job_mode(void);
-int send_keys_to_term(term_T *term, int c, int typed);
+int send_keys_to_term(term_T *term, int c, int modmask, int typed);
 int terminal_is_active(void);
 cursorentry_T *term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg);
 int term_use_loop(void);
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -1226,11 +1226,12 @@ term_mouse_click(VTerm *vterm, int key)
 }
 
 /*
- * Convert typed key "c" into bytes to send to the job.
+ * Convert typed key "c" with modifiers "modmask" into bytes to send to the
+ * job.
  * Return the number of bytes in "buf".
  */
     static int
-term_convert_key(term_T *term, int c, char *buf)
+term_convert_key(term_T *term, int c, int modmask, char *buf)
 {
     VTerm	    *vterm = term->tl_vterm;
     VTermKey	    key = VTERM_KEY_NONE;
@@ -1375,11 +1376,11 @@ term_convert_key(term_T *term, int c, ch
     }
 
     // add modifiers for the typed key
-    if (mod_mask & MOD_MASK_SHIFT)
+    if (modmask & MOD_MASK_SHIFT)
 	mod |= VTERM_MOD_SHIFT;
-    if (mod_mask & MOD_MASK_CTRL)
+    if (modmask & MOD_MASK_CTRL)
 	mod |= VTERM_MOD_CTRL;
-    if (mod_mask & (MOD_MASK_ALT | MOD_MASK_META))
+    if (modmask & (MOD_MASK_ALT | MOD_MASK_META))
 	mod |= VTERM_MOD_ALT;
 
     /*
@@ -1933,12 +1934,12 @@ term_vgetc()
 static int	mouse_was_outside = FALSE;
 
 /*
- * Send keys to terminal.
+ * Send key "c" with modifiers "modmask" to terminal.
  * Return FAIL when the key needs to be handled in Normal mode.
  * Return OK when the key was dropped or sent to the terminal.
  */
     int
-send_keys_to_term(term_T *term, int c, int typed)
+send_keys_to_term(term_T *term, int c, int modmask, int typed)
 {
     char	msg[KEY_BUF_LEN];
     size_t	len;
@@ -2005,10 +2006,10 @@ send_keys_to_term(term_T *term, int c, i
     if (typed)
 	mouse_was_outside = FALSE;
 
-    /* Convert the typed key to a sequence of bytes for the job. */
-    len = term_convert_key(term, c, msg);
+    // Convert the typed key to a sequence of bytes for the job.
+    len = term_convert_key(term, c, modmask, msg);
     if (len > 0)
-	/* TODO: if FAIL is returned, stop? */
+	// TODO: if FAIL is returned, stop?
 	channel_send(term->tl_job->jv_channel, get_tty_part(term),
 						(char_u *)msg, (int)len, NULL);
 
@@ -2259,6 +2260,34 @@ term_win_entered()
 }
 
 /*
+ * vgetc() may not include CTRL in the key when modify_other_keys is set.
+ * Return the Ctrl-key value in that case.
+ */
+    static int
+raw_c_to_ctrl(int c)
+{
+    if ((mod_mask & MOD_MASK_CTRL)
+	    && ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')))
+	return c & 0x1f;
+    return c;
+}
+
+/*
+ * When modify_other_keys is set then do the reverse of raw_c_to_ctrl().
+ * May set "mod_mask".
+ */
+    static int
+ctrl_to_raw_c(int c)
+{
+    if (c < 0x20 && vterm_is_modify_other_keys(curbuf->b_term->tl_vterm))
+    {
+	mod_mask |= MOD_MASK_CTRL;
+	return c + '@';
+    }
+    return c;
+}
+
+/*
  * Wait for input and send it to the job.
  * When "blocking" is TRUE wait for a character to be typed.  Otherwise return
  * when there is no more typahead.
@@ -2312,24 +2341,18 @@ terminal_loop(int blocking)
 	update_cursor(curbuf->b_term, FALSE);
 	restore_cursor = TRUE;
 
-	c = term_vgetc();
+	raw_c = term_vgetc();
 	if (!term_use_loop_check(TRUE) || in_terminal_loop != curbuf->b_term)
 	{
 	    /* Job finished while waiting for a character.  Push back the
 	     * received character. */
-	    if (c != K_IGNORE)
-		vungetc(c);
+	    if (raw_c != K_IGNORE)
+		vungetc(raw_c);
 	    break;
 	}
-	if (c == K_IGNORE)
+	if (raw_c == K_IGNORE)
 	    continue;
-
-	// vgetc may not include CTRL in the key when modify_other_keys is set.
-	raw_c = c;
-	if ((mod_mask & MOD_MASK_CTRL)
-		&& ((c >= '`' && c <= 0x7f)
-		    || (c >= '@' && c <= '_')))
-	    c &= 0x1f;
+	c = raw_c_to_ctrl(raw_c);
 
 #ifdef UNIX
 	/*
@@ -2362,12 +2385,16 @@ terminal_loop(int blocking)
 		)
 	{
 	    int	    prev_c = c;
+	    int	    prev_raw_c = raw_c;
+	    int	    prev_mod_mask = mod_mask;
 
 #ifdef FEAT_CMDL_INFO
 	    if (add_to_showcmd(c))
 		out_flush();
 #endif
-	    c = term_vgetc();
+	    raw_c = term_vgetc();
+	    c = raw_c_to_ctrl(raw_c);
+
 #ifdef FEAT_CMDL_INFO
 	    clear_showcmd();
 #endif
@@ -2385,8 +2412,10 @@ terminal_loop(int blocking)
 		    ret = FAIL;
 		    goto theend;
 		}
-		/* Send both keys to the terminal. */
-		send_keys_to_term(curbuf->b_term, prev_c, TRUE);
+		// Send both keys to the terminal, first one here, second one
+		// below.
+		send_keys_to_term(curbuf->b_term, prev_raw_c, prev_mod_mask,
+									 TRUE);
 	    }
 	    else if (c == Ctrl_C)
 	    {
@@ -2397,12 +2426,12 @@ terminal_loop(int blocking)
 	    {
 		/* "CTRL-W .": send CTRL-W to the job */
 		/* "'termwinkey' .": send 'termwinkey' to the job */
-		c = termwinkey == 0 ? Ctrl_W : termwinkey;
+		raw_c = ctrl_to_raw_c(termwinkey == 0 ? Ctrl_W : termwinkey);
 	    }
 	    else if (c == Ctrl_BSL)
 	    {
 		/* "CTRL-W CTRL-\": send CTRL-\ to the job */
-		c = Ctrl_BSL;
+		raw_c = ctrl_to_raw_c(Ctrl_BSL);
 	    }
 	    else if (c == 'N')
 	    {
@@ -2430,20 +2459,20 @@ terminal_loop(int blocking)
 	    }
 	}
 # ifdef MSWIN
-	if (!enc_utf8 && has_mbyte && c >= 0x80)
+	if (!enc_utf8 && has_mbyte && raw_c >= 0x80)
 	{
 	    WCHAR   wc;
 	    char_u  mb[3];
 
-	    mb[0] = (unsigned)c >> 8;
-	    mb[1] = c;
+	    mb[0] = (unsigned)raw_c >> 8;
+	    mb[1] = raw_c;
 	    if (MultiByteToWideChar(GetACP(), 0, (char*)mb, 2, &wc, 1) > 0)
-		c = wc;
+		raw_c = wc;
 	}
 # endif
-	if (send_keys_to_term(curbuf->b_term, raw_c, TRUE) != OK)
+	if (send_keys_to_term(curbuf->b_term, raw_c, mod_mask, TRUE) != OK)
 	{
-	    if (c == K_MOUSEMOVE)
+	    if (raw_c == K_MOUSEMOVE)
 		/* We are sure to come back here, don't reset the cursor color
 		 * and shape to avoid flickering. */
 		restore_cursor = FALSE;
@@ -5545,7 +5574,7 @@ f_term_sendkeys(typval_T *argvars, typva
 	    c = PTR2CHAR(msg);
 	    msg += MB_CPTR2LEN(msg);
 	}
-	send_keys_to_term(term, c, FALSE);
+	send_keys_to_term(term, c, 0, FALSE);
     }
 }
 
@@ -5811,7 +5840,8 @@ typedef int LPPROC_THREAD_ATTRIBUTE_LIST
 typedef int SIZE_T;
 typedef int PSIZE_T;
 typedef int PVOID;
-typedef int WINAPI;
+typedef int BOOL;
+# define WINAPI
 #endif
 
 HRESULT (WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON*);
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2248,
+/**/
     2247,
 /**/
     2246,