# HG changeset patch # User Christian Brabandt # Date 1713118503 -7200 # Node ID 286bee19bc96adc49f8a540709aed6d65130a1c2 # Parent c95bcbccb165b8f972cf32b67edad45ed290df60 patch 9.1.0321: Garbled output on serial terminals with XON/XOFF flow control Commit: https://github.com/vim/vim/commit/49528da8a60f8fd38ca491d6ccec47dfccf5f23c Author: Anton Sharonov Date: Sun Apr 14 20:02:24 2024 +0200 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 :echo "abc" does nothing (after output freezes and subsequent unfreezes it) *** When started like this: TERM=xterm vim :set termcap shows "t_xon=" map :echo "abc" works (after one see "abc" string echo-ed) fixes: #12674 closes: #14542 Signed-off-by: Anton Sharonov Signed-off-by: Christian Brabandt diff --git a/runtime/doc/tags b/runtime/doc/tags --- a/runtime/doc/tags +++ b/runtime/doc/tags @@ -1157,6 +1157,7 @@ 't_vi' term.txt /*'t_vi'* 't_vs' term.txt /*'t_vs'* 't_xn' term.txt /*'t_xn'* +'t_xo' term.txt /*'t_xo'* 't_xs' term.txt /*'t_xs'* 'ta' options.txt /*'ta'* 'tabline' options.txt /*'tabline'* @@ -10403,6 +10404,7 @@ t_ve term.txt /*t_ve* t_vi term.txt /*t_vi* t_vs term.txt /*t_vs* t_xn term.txt /*t_xn* +t_xo term.txt /*t_xo* t_xs term.txt /*t_xs* tab intro.txt /*tab* tab-page tabpage.txt /*tab-page* diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt --- a/runtime/doc/term.txt +++ b/runtime/doc/term.txt @@ -1,4 +1,4 @@ -*term.txt* For Vim version 9.1. Last change: 2024 Feb 28 +*term.txt* For Vim version 9.1. Last change: 2024 Apr 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -382,7 +382,7 @@ The options are listed below. The assoc the last two characters of the option name. Only one termcap code is required: Cursor motion, 't_cm'. -The options 't_da', 't_db', 't_ms', 't_xs', 't_xn' represent flags in the +The options 't_da', 't_db', 't_ms', 't_xs', 't_xn', 't_xo' represent flags in the termcap. When the termcap flag is present, the option will be set to "y". But any non-empty string means that the flag is set. An empty string means that the flag is not set. 't_CS' works like this too, but it isn't a termcap @@ -441,6 +441,11 @@ OUTPUT CODES *terminal-output-codes *t_xn* *'t_xn'* t_xn if non-empty, writing a character at the last screen cell does not cause scrolling + *t_xo* *'t_xo'* + t_xo if non-empty, terminal uses xon/xoff handshaking, mapping + CTRL-S will not be possible then, since it is used for flow + control (used by vt420 terminal). Setting this flag has only + an effect when starting Vim. t_ZH italics mode *t_ZH* *'t_ZH'* t_ZR italics end *t_ZR* *'t_ZR'* diff --git a/runtime/doc/version9.txt b/runtime/doc/version9.txt --- a/runtime/doc/version9.txt +++ b/runtime/doc/version9.txt @@ -1,4 +1,4 @@ -*version9.txt* For Vim version 9.1. Last change: 2024 Apr 08 +*version9.txt* For Vim version 9.1. Last change: 2024 Apr 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -41591,6 +41591,7 @@ Commands: ~ Options: ~ 'winfixbuf' Keep buffer focused in a window +'t_xo' Terminal uses XON/XOFF handshaking (e.g. vt420). ============================================================================== INCOMPATIBLE CHANGES *incompatible-9.2* diff --git a/src/optiondefs.h b/src/optiondefs.h --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -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 diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -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 diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -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 diff --git a/src/termdefs.h b/src/termdefs.h --- a/src/termdefs.h +++ b/src/termdefs.h @@ -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[]); // c #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 diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -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_\\\"\", 'tx') + call assert_equal(expected, @:) + let &cpo = _cpo +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_terminal3.vim b/src/testdir/test_terminal3.vim --- a/src/testdir/test_terminal3.vim +++ b/src/testdir/test_terminal3.vim @@ -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?\") + 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?\") + call WaitForAssert({-> assert_match('t_xo=\s\+', term_getline(buf, rows))}) + call StopVimInTerminal(buf) +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 321, +/**/ 320, /**/ 319,