0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 9.1.0321: Garbled output on serial terminals with XON/XOFF flow control

Problem:  When used terminal with XON/XOFF flow control, vim tries to
          still make CTRL-S mapping available, which results in severe
          screen corruption, especially on large redraws, and even
          spurious inputs (John Tsiombikas)
Solution: Disallow CTRL-S mapping if such terminal is recognized.
          Don't remove IXON from the bitmask inversion.
          (Anton Sharonov)

*** When started like this:

    TERM=vt420 vim

:set termcap

    shows "t_xon=y"

map <C-S> :echo "abc"<CR>

    does nothing (after <C-S> output freezes and subsequent <C-Q>
    unfreezes it)

*** When started like this:

    TERM=xterm vim

:set termcap

    shows "t_xon="

map <C-S> :echo "abc"<CR>

    works (after <C-S> one see "abc" string echo-ed)

fixes: #12674
closes: #14542

Signed-off-by: Anton Sharonov <anton.sharonov@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Anton Sharonov
2024-04-14 20:02:24 +02:00
committed by Christian Brabandt
parent 4052474a1b
commit 49528da8a6
10 changed files with 60 additions and 6 deletions

View File

@@ -3014,6 +3014,7 @@ static struct vimoption options[] =
p_term("t_8f", T_8F)
p_term("t_8b", T_8B)
p_term("t_8u", T_8U)
p_term("t_xo", T_XON)
// terminal key codes are not in here

View File

@@ -3766,7 +3766,8 @@ mch_settmode(tmode_T tmode)
{
// ~ICRNL enables typing ^V^M
// ~IXON disables CTRL-S stopping output, so that it can be mapped.
tnew.c_iflag &= ~(ICRNL | IXON);
tnew.c_iflag &= ~(ICRNL |
(T_XON == NULL || *T_XON == NUL ? IXON : 0));
tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
# if defined(IEXTEN)
| IEXTEN // IEXTEN enables typing ^V on SOLARIS

View File

@@ -1798,6 +1798,8 @@ get_term_entries(int *height, int *width)
T_DA = (char_u *)"y";
if ((T_UT == NULL || T_UT == empty_option) && tgetflag("ut") > 0)
T_UT = (char_u *)"y";
if ((T_XON == NULL || T_XON == empty_option) && tgetflag("xo") > 0)
T_XON = (char_u *)"y";
/*
* get key codes

View File

@@ -115,10 +115,11 @@ enum SpecialKey
KS_SRI, // restore icon text
KS_FD, // disable focus event tracking
KS_FE, // enable focus event tracking
KS_CF // set terminal alternate font
KS_CF, // set terminal alternate font
KS_XON // terminal uses xon/xoff handshaking
};
#define KS_LAST KS_CF
#define KS_LAST KS_XON
/*
* the terminal capabilities are stored in this array
@@ -224,6 +225,7 @@ extern char_u *(term_strings[]); // current terminal strings
#define T_SRI (TERM_STR(KS_SRI)) // restore icon text
#define T_FD (TERM_STR(KS_FD)) // disable focus event tracking
#define T_FE (TERM_STR(KS_FE)) // enable focus event tracking
#define T_XON (TERM_STR(KS_XON)) // terminal uses xon/xoff handshaking
typedef enum {
TMODE_COOK, // terminal mode for external cmds and Ex mode

View File

@@ -3792,4 +3792,22 @@ func Test_buffer_completion()
call assert_equal("\"b Xbuf_complete/Foobar.c Xbuf_complete/MyFoobar.c AFoobar.h", @:)
endfunc
" :set t_??
func Test_term_option()
set wildoptions&
let _cpo = &cpo
set cpo-=C
let expected='"set t_AB t_AF t_AU t_AL t_al t_bc t_BE t_BD t_cd t_ce t_Ce t_CF t_cl t_cm'
\ .. ' t_Co t_CS t_Cs t_cs t_CV t_da t_db t_DL t_dl t_ds t_Ds t_EC t_EI t_fs t_fd t_fe'
\ .. ' t_GP t_IE t_IS t_ke t_ks t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RF t_RB t_RC'
\ .. ' t_RI t_Ri t_RK t_RS t_RT t_RV t_Sb t_SC t_se t_Sf t_SH t_SI t_Si t_so t_SR t_sr'
\ .. ' t_ST t_Te t_te t_TE t_ti t_TI t_Ts t_ts t_u7 t_ue t_us t_Us t_ut t_vb t_ve t_vi'
\ .. ' t_VS t_vs t_WP t_WS t_XM t_xn t_xs t_ZH t_ZR t_8f t_8b t_8u t_xo t_#2 t_#4 t_%i'
\ .. ' t_*7 t_@7 t_F1 t_F2 t_k1 t_k2 t_k3 t_k4 t_k5 t_k6 t_k7 t_k8 t_k9 t_k; t_kB t_kD'
\ .. ' t_kI t_kN t_kP t_kb t_kd t_kh t_kl t_kr t_ku'
call feedkeys(":set t_\<C-A>\<C-B>\"\<CR>", 'tx')
call assert_equal(expected, @:)
let &cpo = _cpo
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@@ -931,5 +931,25 @@ func Test_terminal_term_start_error()
delfunc s:term_start_error
endfunc
func Test_terminal_vt420()
CheckRunVimInTerminal
" For Termcap
CheckUnix
let rows=15
call writefile([':set term=vt420'], 'Xterm420', 'D')
let buf = RunVimInTerminal('-S Xterm420', #{rows: rows})
call TermWait(buf, 100)
call term_sendkeys(buf, ":set t_xo?\<CR>")
call WaitForAssert({-> assert_match('t_xo=y', term_getline(buf, rows))})
call StopVimInTerminal(buf)
call writefile([''], 'Xterm420')
let buf = RunVimInTerminal('-S Xterm420', #{rows: rows})
call TermWait(buf, 100)
call term_sendkeys(buf, ":set t_xo?\<CR>")
call WaitForAssert({-> assert_match('t_xo=\s\+', term_getline(buf, rows))})
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

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