summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-11-03 21:19:41 +0100
committerBram Moolenaar <Bram@vim.org>2019-11-03 21:19:41 +0100
commit1e814bc017907209a66af82f8fb76c6d1fc324aa (patch)
tree05f1e944d8ae05ca878842a5ed49b551852bcbd8
parente890b9f5dd3ae76e301b2df7f3151366acaba5dc (diff)
downloadvim-git-1e814bc017907209a66af82f8fb76c6d1fc324aa.tar.gz
patch 8.1.2248: CTRL-W dot does not work when modifyOtherKeys is enabledv8.1.2248
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.
-rw-r--r--src/mouse.c2
-rw-r--r--src/proto/terminal.pro2
-rw-r--r--src/terminal.c98
-rw-r--r--src/version.c2
4 files changed, 68 insertions, 36 deletions
diff --git a/src/mouse.c b/src/mouse.c
index b71ef37a4..366cbaf54 100644
--- 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))
diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro
index 52bb1b8d4..5206addd4 100644
--- 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);
diff --git a/src/terminal.c b/src/terminal.c
index 13e32eb5d..10343fe20 100644
--- 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, char *buf)
}
// 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, int typed)
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, typval_T *rettv)
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*);
diff --git a/src/version.c b/src/version.c
index 62897987c..a577dab70 100644
--- 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,