To: vim_dev@googlegroups.com Subject: Patch 8.1.2248 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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. Files: src/terminal.c, src/proto/terminal.pro, src/mouse.c *** ../vim-8.1.2247/src/terminal.c 2019-10-26 16:21:34.511468348 +0200 --- src/terminal.c 2019-11-03 20:58:13.371134721 +0100 *************** *** 1226,1236 **** } /* ! * Convert typed key "c" 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) { VTerm *vterm = term->tl_vterm; VTermKey key = VTERM_KEY_NONE; --- 1226,1237 ---- } /* ! * 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, int modmask, char *buf) { VTerm *vterm = term->tl_vterm; VTermKey key = VTERM_KEY_NONE; *************** *** 1375,1385 **** } // add modifiers for the typed key ! if (mod_mask & MOD_MASK_SHIFT) mod |= VTERM_MOD_SHIFT; ! if (mod_mask & MOD_MASK_CTRL) mod |= VTERM_MOD_CTRL; ! if (mod_mask & (MOD_MASK_ALT | MOD_MASK_META)) mod |= VTERM_MOD_ALT; /* --- 1376,1386 ---- } // add modifiers for the typed key ! if (modmask & MOD_MASK_SHIFT) mod |= VTERM_MOD_SHIFT; ! if (modmask & MOD_MASK_CTRL) mod |= VTERM_MOD_CTRL; ! if (modmask & (MOD_MASK_ALT | MOD_MASK_META)) mod |= VTERM_MOD_ALT; /* *************** *** 1933,1944 **** static int mouse_was_outside = FALSE; /* ! * Send keys 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) { char msg[KEY_BUF_LEN]; size_t len; --- 1934,1945 ---- static int mouse_was_outside = FALSE; /* ! * 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 modmask, int typed) { char msg[KEY_BUF_LEN]; size_t len; *************** *** 2005,2014 **** 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); if (len > 0) ! /* TODO: if FAIL is returned, stop? */ channel_send(term->tl_job->jv_channel, get_tty_part(term), (char_u *)msg, (int)len, NULL); --- 2006,2015 ---- if (typed) mouse_was_outside = FALSE; ! // 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? channel_send(term->tl_job->jv_channel, get_tty_part(term), (char_u *)msg, (int)len, NULL); *************** *** 2259,2264 **** --- 2260,2293 ---- } /* + * 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,2335 **** update_cursor(curbuf->b_term, FALSE); restore_cursor = TRUE; ! 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); break; } ! if (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; #ifdef UNIX /* --- 2341,2358 ---- update_cursor(curbuf->b_term, FALSE); restore_cursor = TRUE; ! 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 (raw_c != K_IGNORE) ! vungetc(raw_c); break; } ! if (raw_c == K_IGNORE) continue; ! c = raw_c_to_ctrl(raw_c); #ifdef UNIX /* *************** *** 2362,2373 **** ) { int prev_c = c; #ifdef FEAT_CMDL_INFO if (add_to_showcmd(c)) out_flush(); #endif ! c = term_vgetc(); #ifdef FEAT_CMDL_INFO clear_showcmd(); #endif --- 2385,2400 ---- ) { 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 ! raw_c = term_vgetc(); ! c = raw_c_to_ctrl(raw_c); ! #ifdef FEAT_CMDL_INFO clear_showcmd(); #endif *************** *** 2385,2392 **** ret = FAIL; goto theend; } ! /* Send both keys to the terminal. */ ! send_keys_to_term(curbuf->b_term, prev_c, TRUE); } else if (c == Ctrl_C) { --- 2412,2421 ---- ret = FAIL; goto theend; } ! // 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,2408 **** { /* "CTRL-W .": send CTRL-W to the job */ /* "'termwinkey' .": send 'termwinkey' to the job */ ! c = termwinkey == 0 ? Ctrl_W : termwinkey; } else if (c == Ctrl_BSL) { /* "CTRL-W CTRL-\": send CTRL-\ to the job */ ! c = Ctrl_BSL; } else if (c == 'N') { --- 2426,2437 ---- { /* "CTRL-W .": send CTRL-W to the job */ /* "'termwinkey' .": send 'termwinkey' to the job */ ! raw_c = ctrl_to_raw_c(termwinkey == 0 ? Ctrl_W : termwinkey); } else if (c == Ctrl_BSL) { /* "CTRL-W CTRL-\": send CTRL-\ to the job */ ! raw_c = ctrl_to_raw_c(Ctrl_BSL); } else if (c == 'N') { *************** *** 2430,2449 **** } } # ifdef MSWIN ! if (!enc_utf8 && has_mbyte && c >= 0x80) { WCHAR wc; char_u mb[3]; ! mb[0] = (unsigned)c >> 8; ! mb[1] = c; if (MultiByteToWideChar(GetACP(), 0, (char*)mb, 2, &wc, 1) > 0) ! c = wc; } # endif ! if (send_keys_to_term(curbuf->b_term, raw_c, TRUE) != OK) { ! if (c == K_MOUSEMOVE) /* We are sure to come back here, don't reset the cursor color * and shape to avoid flickering. */ restore_cursor = FALSE; --- 2459,2478 ---- } } # ifdef MSWIN ! if (!enc_utf8 && has_mbyte && raw_c >= 0x80) { WCHAR wc; char_u mb[3]; ! mb[0] = (unsigned)raw_c >> 8; ! mb[1] = raw_c; if (MultiByteToWideChar(GetACP(), 0, (char*)mb, 2, &wc, 1) > 0) ! raw_c = wc; } # endif ! if (send_keys_to_term(curbuf->b_term, raw_c, mod_mask, TRUE) != OK) { ! 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,5551 **** c = PTR2CHAR(msg); msg += MB_CPTR2LEN(msg); } ! send_keys_to_term(term, c, FALSE); } } --- 5574,5580 ---- c = PTR2CHAR(msg); msg += MB_CPTR2LEN(msg); } ! send_keys_to_term(term, c, 0, FALSE); } } *************** *** 5811,5817 **** typedef int SIZE_T; typedef int PSIZE_T; typedef int PVOID; ! typedef int WINAPI; #endif HRESULT (WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON*); --- 5840,5847 ---- typedef int SIZE_T; typedef int PSIZE_T; typedef int PVOID; ! typedef int BOOL; ! # define WINAPI #endif HRESULT (WINAPI *pCreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON*); *** ../vim-8.1.2247/src/proto/terminal.pro 2019-09-26 23:08:10.501926883 +0200 --- src/proto/terminal.pro 2019-11-03 20:58:15.111125061 +0100 *************** *** 13,19 **** 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 terminal_is_active(void); cursorentry_T *term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg); int term_use_loop(void); --- 13,19 ---- 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 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); *** ../vim-8.1.2247/src/mouse.c 2019-10-17 22:58:59.066497012 +0200 --- src/mouse.c 2019-11-03 19:56:50.723673238 +0100 *************** *** 2012,2018 **** 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); else # endif if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) --- 2012,2018 ---- 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, mod_mask, FALSE); else # endif if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)) *** ../vim-8.1.2247/src/version.c 2019-11-03 18:38:44.492598820 +0100 --- src/version.c 2019-11-03 21:17:41.969127362 +0100 *************** *** 743,744 **** --- 743,746 ---- { /* Add new patch number below this line */ + /**/ + 2248, /**/ -- How To Keep A Healthy Level Of Insanity: 13. Go to a poetry recital and ask why the poems don't rhyme. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///