0
0
mirror of https://github.com/vim/vim.git synced 2025-09-28 04:24:06 -04:00

patch 9.0.0980: the keyboard state response may end up in a shell command

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.
This commit is contained in:
Bram Moolenaar
2022-12-01 12:03:47 +00:00
parent 4f501171f7
commit 733a69b29f
12 changed files with 110 additions and 28 deletions

View File

@@ -1001,10 +1001,15 @@ mapping, see |map-bar|.
WARNING: if you map <C-[> you may very well break any key codes that start WARNING: if you map <C-[> you may very well break any key codes that start
with Esc. Make sure it comes AFTER other mappings. with Esc. Make sure it comes AFTER other mappings.
Vim automatically detects if the modifyOtherKeys mode was enabled when it Starting with xterm version 377 Vim can detect the modifyOtherKeys state by
spots an escape sequence that must have been created by it. To see if Vim requesting it. For this the 't_RK' termcap entry is used. When the response
detected such an escape sequence use `:verbose map`, the first line will then is found then Vim will know whether modifyOtherKeys level 2 is enabled, and
show "Seen modifyOtherKeys: true" (possibly translated). 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 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 "<1b>[27;". This is the normal way xterm sends these key codes. However, if
@@ -1016,6 +1021,9 @@ after the CTRL-V key. This can be used to check whether modifyOtherKeys is
enabled: In Insert mode type CTRL-SHIFT-V CTRL-V, if you get one byte then 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. 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 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. Insert mode to avoid every key with a modifier causing Insert mode to end.

View File

@@ -90,6 +90,11 @@ Note: When 't_ti' is not empty, Vim assumes that it causes switching to the
alternate screen. This may slightly change what happens when executing a 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'. 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* *xterm-bracketed-paste*
When the 't_BE' option is set then 't_BE' will be sent to the 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 terminal when entering "raw" mode and 't_BD' when leaving "raw" mode. The
@@ -388,6 +393,8 @@ Added by Vim (there are no standard codes for these):
xterm and other terminal emulators) The xterm and other terminal emulators) The
response is stored in |v:termresponse| |xterm-8bit| response is stored in |v:termresponse| |xterm-8bit|
|'ttymouse'| |xterm-codes| |'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'* t_u7 request cursor position (for xterm) *t_u7* *'t_u7'*
see |'ambiwidth'| see |'ambiwidth'|
The response is stored in |v:termu7resp| The response is stored in |v:termu7resp|

View File

@@ -571,6 +571,8 @@ edit(
#ifdef USE_ON_FLY_SCROLL #ifdef USE_ON_FLY_SCROLL
dont_scroll = FALSE; // allow scrolling here dont_scroll = FALSE; // allow scrolling here
#endif #endif
// May request the keyboard protocol state now.
may_send_t_RK();
/* /*
* Get a character for Insert mode. Ignore K_IGNORE and K_NOP. * Get a character for Insert mode. Ignore K_IGNORE and K_NOP.
@@ -1479,7 +1481,8 @@ ins_redraw(int ready) // not busy with something
aco_save_T aco; aco_save_T aco;
varnumber_T tick = CHANGEDTICK(curbuf); varnumber_T tick = CHANGEDTICK(curbuf);
// save and restore curwin and curbuf, in case the autocmd changes them // Save and restore curwin and curbuf, in case the autocmd changes
// them.
aucmd_prepbuf(&aco, curbuf); aucmd_prepbuf(&aco, curbuf);
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
aucmd_restbuf(&aco); aucmd_restbuf(&aco);
@@ -1499,7 +1502,8 @@ ins_redraw(int ready) // not busy with something
aco_save_T aco; aco_save_T aco;
varnumber_T tick = CHANGEDTICK(curbuf); varnumber_T tick = CHANGEDTICK(curbuf);
// save and restore curwin and curbuf, in case the autocmd changes them // Save and restore curwin and curbuf, in case the autocmd changes
// them.
aucmd_prepbuf(&aco, curbuf); aucmd_prepbuf(&aco, curbuf);
apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf); apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf);
aucmd_restbuf(&aco); aucmd_restbuf(&aco);
@@ -3706,7 +3710,7 @@ ins_esc(
out_str(T_BE); out_str(T_BE);
// Re-enable modifyOtherKeys. // Re-enable modifyOtherKeys.
out_str(T_CTI); out_str_t_TI();
} }
#ifdef FEAT_CONCEAL #ifdef FEAT_CONCEAL
// Check if the cursor line needs redrawing after changing State. If // Check if the cursor line needs redrawing after changing State. If
@@ -4384,6 +4388,7 @@ bracketed_paste(paste_mode_T mode, int drop, garray_T *gap)
do do
c = vgetc(); c = vgetc();
while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR); while (c == K_IGNORE || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR);
if (c == NUL || got_int || (ex_normal_busy > 0 && c == Ctrl_C)) if (c == NUL || got_int || (ex_normal_busy > 0 && c == Ctrl_C))
// When CTRL-C was encountered the typeahead will be flushed and we // When CTRL-C was encountered the typeahead will be flushed and we
// won't get the end sequence. Except when using ":normal". // won't get the end sequence. Except when using ":normal".

View File

@@ -2908,6 +2908,9 @@ getexmodeline(
long sw; long sw;
char_u *s; char_u *s;
// May request the keyboard protocol state now.
may_send_t_RK();
if (ga_grow(&line_ga, 40) == FAIL) if (ga_grow(&line_ga, 40) == FAIL)
break; break;

View File

@@ -1162,6 +1162,15 @@ may_trigger_safestateagain(void)
} }
#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. * Main loop: Execute Normal mode commands until exiting Vim.
@@ -1477,10 +1486,11 @@ main_loop(
gui_mouse_correct(); gui_mouse_correct();
#endif #endif
/* // May request the keyboard protocol state now.
* Update w_curswant if w_set_curswant has been set. may_send_t_RK();
* Postponed until here to avoid computing w_virtcol too often.
*/ // Update w_curswant if w_set_curswant has been set.
// Postponed until here to avoid computing w_virtcol too often.
update_curswant(); update_curswant();
#ifdef FEAT_EVAL #ifdef FEAT_EVAL

View File

@@ -455,7 +455,7 @@ normal_cmd_get_more_chars(
// Re-enable bracketed paste mode and modifyOtherKeys // Re-enable bracketed paste mode and modifyOtherKeys
out_str(T_BE); out_str(T_BE);
out_str(T_CTI); out_str_t_TI();
} }
if (langmap_active) if (langmap_active)

View File

@@ -5379,7 +5379,7 @@ finished:
if (tmode == TMODE_RAW) if (tmode == TMODE_RAW)
// possibly enables modifyOtherKeys again // possibly enables modifyOtherKeys again
out_str(T_CTI); out_str_t_TI();
} }
# endif # endif

View File

@@ -9,6 +9,7 @@ void may_trigger_safestate(int safe);
void state_no_longer_safe(char *reason); void state_no_longer_safe(char *reason);
int get_was_safe_state(void); int get_was_safe_state(void);
void may_trigger_safestateagain(void); void may_trigger_safestateagain(void);
int work_pending(void);
void main_loop(int cmdwin, int noexmode); void main_loop(int cmdwin, int noexmode);
void getout_preserve_modified(int exitval); void getout_preserve_modified(int exitval);
void getout(int exitval); void getout(int exitval);

View File

@@ -48,6 +48,8 @@ void shell_resized(void);
void shell_resized_check(void); void shell_resized_check(void);
void set_shellsize(int width, int height, int mustset); void set_shellsize(int width, int height, int mustset);
void out_str_t_TE(void); void out_str_t_TE(void);
void out_str_t_TI(void);
void may_send_t_RK(void);
void settmode(tmode_T tmode); void settmode(tmode_T tmode);
void starttermcap(void); void starttermcap(void);
void stoptermcap(void); void stoptermcap(void);

View File

@@ -452,7 +452,8 @@ static tcap_entry_T builtin_xterm[] = {
{(int)KS_TI, "\0337\033[?47h"}, {(int)KS_TI, "\0337\033[?47h"},
{(int)KS_TE, "\033[?47l\0338"}, {(int)KS_TE, "\033[?47l\0338"},
# endif # endif
{(int)KS_CTI, "\033[>4;2m\033[?4m"}, // see "builtin_mok2" {(int)KS_CTI, "\033[>4;2m"},
{(int)KS_CRK, "\033[?4m"}, // see "builtin_mok2"
{(int)KS_CTE, "\033[>4;m"}, {(int)KS_CTE, "\033[>4;m"},
{(int)KS_CIS, "\033]1;"}, {(int)KS_CIS, "\033]1;"},
{(int)KS_CIE, "\007"}, {(int)KS_CIE, "\007"},
@@ -593,10 +594,15 @@ static tcap_entry_T builtin_xterm[] = {
* xterm. * xterm.
*/ */
static tcap_entry_T builtin_mok2[] = { 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 // 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 // return "{lead} > 4 ; Pv m". Before version 377 we expect it to have no
// effect. // effect.
{(int)KS_CTI, "\033[>4;2m\033[?4m"}, {(int)KS_CRK, "\033[?4m"},
// t_TE disables modifyOtherKeys
{(int)KS_CTE, "\033[>4;m"}, {(int)KS_CTE, "\033[>4;m"},
{(int)KS_NAME, NULL} // end marker {(int)KS_NAME, NULL} // end marker
@@ -606,11 +612,13 @@ static tcap_entry_T builtin_mok2[] = {
* Additions for using the Kitty keyboard protocol. * Additions for using the Kitty keyboard protocol.
*/ */
static tcap_entry_T builtin_kitty[] = { static tcap_entry_T builtin_kitty[] = {
// t_TI enables the kitty keyboard protocol, requests the kitty keyboard // t_TI enables the kitty keyboard protocol.
// protocol state and requests the version response. {(int)KS_CTI, "\033[=1;1u"},
{(int)KS_CTI, "\033[=1;1u\033[?u\033[>c"},
// t_TE also disabled modifyOtherKeys, because t_TI from xterm may already // 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. // have been used.
{(int)KS_CTE, "\033[>4;m\033[=0;1u"}, {(int)KS_CTE, "\033[>4;m\033[=0;1u"},
@@ -1685,7 +1693,7 @@ get_term_entries(int *height, int *width)
{KS_CM, "cm"}, {KS_SR, "sr"}, {KS_CM, "cm"}, {KS_SR, "sr"},
{KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"}, {KS_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
{KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"}, {KS_KE, "ke"}, {KS_TI, "ti"}, {KS_TE, "te"},
{KS_CTI, "TI"}, {KS_CTE, "TE"}, {KS_CTI, "TI"}, {KS_CRK, "RK"}, {KS_CTE, "TE"},
{KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"}, {KS_BC, "bc"}, {KS_CSB,"Sb"}, {KS_CSF,"Sf"},
{KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_CAU,"AU"}, {KS_CAB,"AB"}, {KS_CAF,"AF"}, {KS_CAU,"AU"},
{KS_LE, "le"}, {KS_LE, "le"},
@@ -3693,6 +3701,40 @@ out_str_t_TE(void)
kitty_protocol_state = KKPS_AFTER_T_KE; 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 * Set the terminal to TMODE_RAW (for Normal mode) or TMODE_COOK (for external
* commands and Ex mode). * commands and Ex mode).
@@ -3751,7 +3793,7 @@ settmode(tmode_T tmode)
{ {
out_str(T_BE); // enable bracketed paste mode (should out_str(T_BE); // enable bracketed paste mode (should
// be before mch_settmode(). // be before mch_settmode().
out_str(T_CTI); // possibly enables modifyOtherKeys out_str_t_TI(); // possibly enables modifyOtherKeys
} }
} }
out_flush(); out_flush();
@@ -3775,7 +3817,7 @@ starttermcap(void)
MAY_WANT_TO_LOG_THIS; MAY_WANT_TO_LOG_THIS;
out_str(T_TI); // start termcap mode out_str(T_TI); // start termcap mode
out_str(T_CTI); // start "raw" mode out_str_t_TI(); // start "raw" mode
out_str(T_KS); // start "keypad transmit" mode out_str(T_KS); // start "keypad transmit" mode
out_str(T_BE); // enable bracketed paste mode out_str(T_BE); // enable bracketed paste mode

View File

@@ -69,6 +69,7 @@ enum SpecialKey
KS_KE, // out of "keypad transmit" mode KS_KE, // out of "keypad transmit" mode
KS_TI, // put terminal in termcap mode KS_TI, // put terminal in termcap mode
KS_CTI, // put terminal in "raw" mode KS_CTI, // put terminal in "raw" mode
KS_CRK, // request keyboard protocol state
KS_TE, // end of termcap mode KS_TE, // end of termcap mode
KS_CTE, // end of "raw" mode KS_CTE, // end of "raw" mode
KS_BC, // backspace character (cursor left) KS_BC, // backspace character (cursor left)
@@ -177,6 +178,7 @@ extern char_u *(term_strings[]); // current terminal strings
#define T_KE (TERM_STR(KS_KE)) // out of "keypad transmit" mode #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_TI (TERM_STR(KS_TI)) // put terminal in termcap mode
#define T_CTI (TERM_STR(KS_CTI)) // put terminal in "raw" 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_TE (TERM_STR(KS_TE)) // end of termcap mode
#define T_CTE (TERM_STR(KS_CTE)) // end of "raw" mode #define T_CTE (TERM_STR(KS_CTE)) // end of "raw" mode
#define T_BC (TERM_STR(KS_BC)) // backspace character #define T_BC (TERM_STR(KS_BC)) // backspace character

View File

@@ -695,6 +695,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
980,
/**/ /**/
979, 979,
/**/ /**/