1
0
forked from aniani/vim

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
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).
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
@@ -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
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.

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
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,6 +393,8 @@ Added by Vim (there are no standard codes for these):
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|

View File

@@ -571,6 +571,8 @@ edit(
#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,7 +1481,8 @@ ins_redraw(int ready) // not busy with something
aco_save_T aco;
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);
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
aucmd_restbuf(&aco);
@@ -1499,7 +1502,8 @@ ins_redraw(int ready) // not busy with something
aco_save_T aco;
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);
apply_autocmds(EVENT_TEXTCHANGEDP, NULL, NULL, FALSE, curbuf);
aucmd_restbuf(&aco);
@@ -3706,7 +3710,7 @@ ins_esc(
out_str(T_BE);
// Re-enable modifyOtherKeys.
out_str(T_CTI);
out_str_t_TI();
}
#ifdef FEAT_CONCEAL
// 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
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".

View File

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

View File

@@ -1162,6 +1162,15 @@ may_trigger_safestateagain(void)
}
#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,10 +1486,11 @@ main_loop(
gui_mouse_correct();
#endif
/*
* Update w_curswant if w_set_curswant has been set.
* Postponed until here to avoid computing w_virtcol too often.
*/
// 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

View File

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

View File

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

View File

@@ -9,6 +9,7 @@ void may_trigger_safestate(int safe);
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);

View File

@@ -48,6 +48,8 @@ void shell_resized(void);
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);

View File

@@ -452,7 +452,8 @@ static tcap_entry_T builtin_xterm[] = {
{(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_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,10 +594,15 @@ static tcap_entry_T builtin_xterm[] = {
* 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_CTI, "\033[>4;2m\033[?4m"},
{(int)KS_CRK, "\033[?4m"},
// t_TE disables modifyOtherKeys
{(int)KS_CTE, "\033[>4;m"},
{(int)KS_NAME, NULL} // end marker
@@ -606,11 +612,13 @@ static tcap_entry_T builtin_mok2[] = {
* 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_TI enables the kitty keyboard protocol.
{(int)KS_CTI, "\033[=1;1u"},
// 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.
{(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_CRI,"RI"}, {KS_VB, "vb"}, {KS_KS, "ks"},
{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_CAB,"AB"}, {KS_CAF,"AF"}, {KS_CAU,"AU"},
{KS_LE, "le"},
@@ -3693,6 +3701,40 @@ out_str_t_TE(void)
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,7 +3793,7 @@ settmode(tmode_T tmode)
{
out_str(T_BE); // enable bracketed paste mode (should
// be before mch_settmode().
out_str(T_CTI); // possibly enables modifyOtherKeys
out_str_t_TI(); // possibly enables modifyOtherKeys
}
}
out_flush();
@@ -3775,7 +3817,7 @@ starttermcap(void)
MAY_WANT_TO_LOG_THIS;
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_BE); // enable bracketed paste mode

View File

@@ -69,6 +69,7 @@ enum SpecialKey
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,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_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

View File

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