# HG changeset patch # User Bram Moolenaar # Date 1572813004 -3600 # Node ID 3cd689e9eb7fd7d5a692e3416c86df04b25a783f # Parent 5cab7eef0829b7f33c43acaf3028831c2d491eea 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 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. diff --git a/src/mouse.c b/src/mouse.c --- 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 --- 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 --- 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*); diff --git a/src/version.c b/src/version.c --- 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,