To: vim_dev@googlegroups.com Subject: Patch 9.0.0980 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 9.0.0980 Problem: The keyboard state response may end up in a shell command. Solution: Only request the keyboard protocol state when the typeahead is empty, no more commands are following and not exiting. Add the t_RK termcap entry for this. Files: runtime/doc/term.txt, runtime/doc/map.txt, src/term.c, src/proto/term.pro, src/termdefs.h, src/edit.c, src/normal.c, src/os_unix.c, src/main.c, src/proto/main.pro, src/ex_getln.c *** ../vim-9.0.0979/runtime/doc/term.txt 2022-11-25 15:09:30.710402884 +0000 --- runtime/doc/term.txt 2022-12-01 11:09:35.145283059 +0000 *************** *** 90,95 **** --- 90,100 ---- alternate screen. This may slightly change what happens when executing a shell command or exiting Vim. To avoid this use 't_TI' and 't_TE'. + Vim will try to detect what keyboard protocol the terminal is using with the + 't_RK' termcap entry. This is sent after 't_TI', but only when there is no + work to do (no typeahead and no pending commands). That is to avoid the + response to end up in a shell command or arrive after Vim exits. + *xterm-bracketed-paste* When the 't_BE' option is set then 't_BE' will be sent to the terminal when entering "raw" mode and 't_BD' when leaving "raw" mode. The *************** *** 388,393 **** --- 393,400 ---- xterm and other terminal emulators) The response is stored in |v:termresponse| |xterm-8bit| |'ttymouse'| |xterm-codes| + t_RK request terminal keyboard protocol state; *t_RK* *'t_RK'* + sent after |t_TI| t_u7 request cursor position (for xterm) *t_u7* *'t_u7'* see |'ambiwidth'| The response is stored in |v:termu7resp| *** ../vim-9.0.0979/runtime/doc/map.txt 2022-11-24 13:27:32.385881078 +0000 --- runtime/doc/map.txt 2022-12-01 11:53:45.407249388 +0000 *************** *** 993,1002 **** WARNING: if you map you may very well break any key codes that start with Esc. Make sure it comes AFTER other mappings. ! Vim automatically detects if the modifyOtherKeys mode was enabled when it ! spots an escape sequence that must have been created by it. To see if Vim ! detected such an escape sequence use `:verbose map`, the first line will then ! show "Seen modifyOtherKeys: true" (possibly translated). This automatic detection depends on receiving an escape code starting with "<1b>[27;". This is the normal way xterm sends these key codes. However, if --- 1001,1015 ---- WARNING: if you map you may very well break any key codes that start with Esc. Make sure it comes AFTER other mappings. ! Starting with xterm version 377 Vim can detect the modifyOtherKeys state by ! requesting it. For this the 't_RK' termcap entry is used. When the response ! is found then Vim will know whether modifyOtherKeys level 2 is enabled, and ! handle mappings accordingly. ! ! Before version 377 Vim automatically detects if the modifyOtherKeys mode was ! enabled when it spots an escape sequence that must have been created by it. ! To see if Vim detected such an escape sequence use `:verbose map`, the first ! line will then show "Seen modifyOtherKeys: true" (possibly translated). This automatic detection depends on receiving an escape code starting with "<1b>[27;". This is the normal way xterm sends these key codes. However, if *************** *** 1008,1013 **** --- 1021,1029 ---- enabled: In Insert mode type CTRL-SHIFT-V CTRL-V, if you get one byte then modifyOtherKeys is off, if you get <1b>[27;5;118~ then it is on. + Note that xterm up to version 376 has a bug that makes Shift-Esc send a + regular Esc code, the Shift modifier is dropped. + When the 'esckeys' option is off, then modifyOtherKeys will be disabled in Insert mode to avoid every key with a modifier causing Insert mode to end. *** ../vim-9.0.0979/src/term.c 2022-11-30 18:11:52.694904295 +0000 --- src/term.c 2022-12-01 11:32:08.563300766 +0000 *************** *** 452,458 **** {(int)KS_TI, "\0337\033[?47h"}, {(int)KS_TE, "\033[?47l\0338"}, # endif ! {(int)KS_CTI, "\033[>4;2m\033[?4m"}, // see "builtin_mok2" {(int)KS_CTE, "\033[>4;m"}, {(int)KS_CIS, "\033]1;"}, {(int)KS_CIE, "\007"}, --- 452,459 ---- {(int)KS_TI, "\0337\033[?47h"}, {(int)KS_TE, "\033[?47l\0338"}, # endif ! {(int)KS_CTI, "\033[>4;2m"}, ! {(int)KS_CRK, "\033[?4m"}, // see "builtin_mok2" {(int)KS_CTE, "\033[>4;m"}, {(int)KS_CIS, "\033]1;"}, {(int)KS_CIE, "\007"}, *************** *** 593,602 **** * xterm. */ static tcap_entry_T builtin_mok2[] = { // XTQMODKEYS was added in xterm version 377: "CSI ? 4 m" which should // return "{lead} > 4 ; Pv m". Before version 377 we expect it to have no // effect. ! {(int)KS_CTI, "\033[>4;2m\033[?4m"}, {(int)KS_CTE, "\033[>4;m"}, {(int)KS_NAME, NULL} // end marker --- 594,608 ---- * xterm. */ static tcap_entry_T builtin_mok2[] = { + // t_TI enables modifyOtherKeys level 2 + {(int)KS_CTI, "\033[>4;2m"}, + // XTQMODKEYS was added in xterm version 377: "CSI ? 4 m" which should // return "{lead} > 4 ; Pv m". Before version 377 we expect it to have no // effect. ! {(int)KS_CRK, "\033[?4m"}, ! ! // t_TE disables modifyOtherKeys {(int)KS_CTE, "\033[>4;m"}, {(int)KS_NAME, NULL} // end marker *************** *** 606,616 **** * Additions for using the Kitty keyboard protocol. */ static tcap_entry_T builtin_kitty[] = { ! // t_TI enables the kitty keyboard protocol, requests the kitty keyboard ! // protocol state and requests the version response. ! {(int)KS_CTI, "\033[=1;1u\033[?u\033[>c"}, ! // t_TE also disabled modifyOtherKeys, because t_TI from xterm may already // have been used. {(int)KS_CTE, "\033[>4;m\033[=0;1u"}, --- 612,624 ---- * Additions for using the Kitty keyboard protocol. */ static tcap_entry_T builtin_kitty[] = { ! // t_TI enables the kitty keyboard protocol. ! {(int)KS_CTI, "\033[=1;1u"}, ! ! // t_RK requests the kitty keyboard protocol state ! {(int)KS_CRK, "\033[?u"}, ! // t_TE also disables modifyOtherKeys, because t_TI from xterm may already // have been used. {(int)KS_CTE, "\033[>4;m\033[=0;1u"}, *************** *** 1685,1691 **** {KS_CM, "cm"}, {KS_SR, "sr"}, {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"}, {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"}, ! {KS_CTI, "TI"}, {KS_CTE, "TE"}, {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"}, {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_CAU,"AU"}, {KS_LE, "le"}, --- 1693,1699 ---- {KS_CM, "cm"}, {KS_SR, "sr"}, {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"}, {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"}, ! {KS_CTI, "TI"}, {KS_CRK, "RK"}, {KS_CTE, "TE"}, {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"}, {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_CAU,"AU"}, {KS_LE, "le"}, *************** *** 3693,3698 **** --- 3701,3740 ---- kitty_protocol_state = KKPS_AFTER_T_KE; } + static int send_t_RK = FALSE; + + /* + * Output T_TI and setup for what follows. + */ + void + out_str_t_TI(void) + { + out_str(T_CTI); + + // Send t_RK when there is no more work to do. + send_t_RK = TRUE; + } + + /* + * If t_TI was recently sent and there is no typeahead or work to do, now send + * t_RK. This is postponed to avoid the response arriving in a shell command + * or after Vim exits. + */ + void + may_send_t_RK(void) + { + if (send_t_RK + && !work_pending() + && !ex_normal_busy + && !in_feedkeys + && !exiting) + { + send_t_RK = FALSE; + out_str(T_CRK); + out_flush(); + } + } + /* * Set the terminal to TMODE_RAW (for Normal mode) or TMODE_COOK (for external * commands and Ex mode). *************** *** 3751,3757 **** { out_str(T_BE); // enable bracketed paste mode (should // be before mch_settmode(). ! out_str(T_CTI); // possibly enables modifyOtherKeys } } out_flush(); --- 3793,3799 ---- { out_str(T_BE); // enable bracketed paste mode (should // be before mch_settmode(). ! out_str_t_TI(); // possibly enables modifyOtherKeys } } out_flush(); *************** *** 3775,3781 **** MAY_WANT_TO_LOG_THIS; out_str(T_TI); // start termcap mode ! out_str(T_CTI); // start "raw" mode out_str(T_KS); // start "keypad transmit" mode out_str(T_BE); // enable bracketed paste mode --- 3817,3823 ---- MAY_WANT_TO_LOG_THIS; out_str(T_TI); // start termcap mode ! out_str_t_TI(); // start "raw" mode out_str(T_KS); // start "keypad transmit" mode out_str(T_BE); // enable bracketed paste mode *** ../vim-9.0.0979/src/proto/term.pro 2022-11-23 20:19:17.129682462 +0000 --- src/proto/term.pro 2022-12-01 11:38:39.243456607 +0000 *************** *** 48,53 **** --- 48,55 ---- void shell_resized_check(void); void set_shellsize(int width, int height, int mustset); void out_str_t_TE(void); + void out_str_t_TI(void); + void may_send_t_RK(void); void settmode(tmode_T tmode); void starttermcap(void); void stoptermcap(void); *** ../vim-9.0.0979/src/termdefs.h 2022-06-29 18:39:05.011841452 +0100 --- src/termdefs.h 2022-12-01 11:23:24.078950857 +0000 *************** *** 69,74 **** --- 69,75 ---- KS_KE, // out of "keypad transmit" mode KS_TI, // put terminal in termcap mode KS_CTI, // put terminal in "raw" mode + KS_CRK, // request keyboard protocol state KS_TE, // end of termcap mode KS_CTE, // end of "raw" mode KS_BC, // backspace character (cursor left) *************** *** 177,182 **** --- 178,184 ---- #define T_KE (TERM_STR(KS_KE)) // out of "keypad transmit" mode #define T_TI (TERM_STR(KS_TI)) // put terminal in termcap mode #define T_CTI (TERM_STR(KS_CTI)) // put terminal in "raw" mode + #define T_CRK (TERM_STR(KS_CRK)) // request keyboard protocol status #define T_TE (TERM_STR(KS_TE)) // end of termcap mode #define T_CTE (TERM_STR(KS_CTE)) // end of "raw" mode #define T_BC (TERM_STR(KS_BC)) // backspace character *** ../vim-9.0.0979/src/edit.c 2022-11-23 20:19:17.129682462 +0000 --- src/edit.c 2022-12-01 11:36:12.163404016 +0000 *************** *** 571,576 **** --- 571,578 ---- #ifdef USE_ON_FLY_SCROLL dont_scroll = FALSE; // allow scrolling here #endif + // May request the keyboard protocol state now. + may_send_t_RK(); /* * Get a character for Insert mode. Ignore K_IGNORE and K_NOP. *************** *** 1479,1485 **** aco_save_T aco; varnumber_T tick = CHANGEDTICK(curbuf); ! // save and restore curwin and curbuf, in case the autocmd changes them aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); aucmd_restbuf(&aco); --- 1481,1488 ---- aco_save_T aco; varnumber_T tick = CHANGEDTICK(curbuf); ! // Save and restore curwin and curbuf, in case the autocmd changes ! // them. aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); aucmd_restbuf(&aco); *************** *** 1499,1505 **** aco_save_T aco; varnumber_T tick = CHANGEDTICK(curbuf); ! // save and restore curwin and curbuf, in case the autocmd changes them aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf); aucmd_restbuf(&aco); --- 1502,1509 ---- aco_save_T aco; varnumber_T tick = CHANGEDTICK(curbuf); ! // Save and restore curwin and curbuf, in case the autocmd changes ! // them. aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf); aucmd_restbuf(&aco); *************** *** 3706,3712 **** out_str(T_BE); // Re-enable modifyOtherKeys. ! out_str(T_CTI); } #ifdef FEAT_CONCEAL // Check if the cursor line needs redrawing after changing State. If --- 3710,3716 ---- out_str(T_BE); // Re-enable modifyOtherKeys. ! out_str_t_TI(); } #ifdef FEAT_CONCEAL // Check if the cursor line needs redrawing after changing State. If *************** *** 4384,4389 **** --- 4388,4394 ---- do c = vgetc(); while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR); + if (c == NUL || got_int || (ex_normal_busy > 0 && c == Ctrl_C)) // When CTRL-C was encountered the typeahead will be flushed and we // won't get the end sequence. Except when using ":normal". *** ../vim-9.0.0979/src/normal.c 2022-11-25 13:03:28.200437332 +0000 --- src/normal.c 2022-12-01 11:16:03.034352695 +0000 *************** *** 455,461 **** // Re-enable bracketed paste mode and modifyOtherKeys out_str(T_BE); ! out_str(T_CTI); } if (langmap_active) --- 455,461 ---- // Re-enable bracketed paste mode and modifyOtherKeys out_str(T_BE); ! out_str_t_TI(); } if (langmap_active) *** ../vim-9.0.0979/src/os_unix.c 2022-11-30 18:11:52.690904297 +0000 --- src/os_unix.c 2022-12-01 11:16:20.714386050 +0000 *************** *** 5379,5385 **** if (tmode == TMODE_RAW) // possibly enables modifyOtherKeys again ! out_str(T_CTI); } # endif --- 5379,5385 ---- if (tmode == TMODE_RAW) // possibly enables modifyOtherKeys again ! out_str_t_TI(); } # endif *** ../vim-9.0.0979/src/main.c 2022-11-30 18:11:52.690904297 +0000 --- src/main.c 2022-12-01 11:38:13.243447838 +0000 *************** *** 1133,1146 **** // of calling feedkeys(), we check if it's now safe again (all keys // were consumed). was_safe = is_safe_now(); ! #ifdef FEAT_EVAL if (was_safe) ch_log(NULL, "SafeState: undo reset"); ! #endif } if (was_safe) { ! #ifdef FEAT_EVAL // Only do this message when another message was given, otherwise we // get lots of them. if ((did_repeated_msg & REPEATED_MSG_SAFESTATE) == 0) --- 1133,1146 ---- // of calling feedkeys(), we check if it's now safe again (all keys // were consumed). was_safe = is_safe_now(); ! # ifdef FEAT_EVAL if (was_safe) ch_log(NULL, "SafeState: undo reset"); ! # endif } if (was_safe) { ! # ifdef FEAT_EVAL // Only do this message when another message was given, otherwise we // get lots of them. if ((did_repeated_msg & REPEATED_MSG_SAFESTATE) == 0) *************** *** 1151,1167 **** "SafeState: back to waiting, triggering SafeStateAgain"); did_repeated_msg = did | REPEATED_MSG_SAFESTATE; } ! #endif apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf); } ! #ifdef FEAT_EVAL else ch_log(NULL, "SafeState: back to waiting, not triggering SafeStateAgain"); ! #endif } #endif /* * Main loop: Execute Normal mode commands until exiting Vim. --- 1151,1176 ---- "SafeState: back to waiting, triggering SafeStateAgain"); did_repeated_msg = did | REPEATED_MSG_SAFESTATE; } ! # endif apply_autocmds(EVENT_SAFESTATEAGAIN, NULL, NULL, FALSE, curbuf); } ! # ifdef FEAT_EVAL else ch_log(NULL, "SafeState: back to waiting, not triggering SafeStateAgain"); ! # endif } #endif + /* + * Return TRUE if there is any typeahead, pending operator or command. + */ + int + work_pending(void) + { + return op_pending() || !is_safe_now(); + } + /* * Main loop: Execute Normal mode commands until exiting Vim. *************** *** 1477,1486 **** gui_mouse_correct(); #endif ! /* ! * Update w_curswant if w_set_curswant has been set. ! * Postponed until here to avoid computing w_virtcol too often. ! */ update_curswant(); #ifdef FEAT_EVAL --- 1486,1496 ---- gui_mouse_correct(); #endif ! // May request the keyboard protocol state now. ! may_send_t_RK(); ! ! // Update w_curswant if w_set_curswant has been set. ! // Postponed until here to avoid computing w_virtcol too often. update_curswant(); #ifdef FEAT_EVAL *** ../vim-9.0.0979/src/proto/main.pro 2022-09-24 13:10:00.739938625 +0100 --- src/proto/main.pro 2022-12-01 11:38:34.719455102 +0000 *************** *** 9,14 **** --- 9,15 ---- void state_no_longer_safe(char *reason); int get_was_safe_state(void); void may_trigger_safestateagain(void); + int work_pending(void); void main_loop(int cmdwin, int noexmode); void getout_preserve_modified(int exitval); void getout(int exitval); *** ../vim-9.0.0979/src/ex_getln.c 2022-11-17 11:34:33.333726348 +0000 --- src/ex_getln.c 2022-12-01 11:37:11.083425840 +0000 *************** *** 2908,2913 **** --- 2908,2916 ---- long sw; char_u *s; + // May request the keyboard protocol state now. + may_send_t_RK(); + if (ga_grow(&line_ga, 40) == FAIL) break; *** ../vim-9.0.0979/src/version.c 2022-12-01 11:02:19.288680405 +0000 --- src/version.c 2022-12-01 11:07:10.764647255 +0000 *************** *** 697,698 **** --- 697,700 ---- { /* Add new patch number below this line */ + /**/ + 980, /**/ -- hundred-and-one symptoms of being an internet addict: 191. You rate eating establishments not by the quality of the food, but by the availability of electrical outlets for your PowerBook. /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///