Skip to content

Commit 45ba2e1

Browse files
authored
fix(tui): add fixups for hterm family neovim#19078
Problem ------- In neovim#19040, I reported two things that started happening somewhen in the last three months when using neovim in hterm (the Chrome Secure Shell terminal): 1. Under certain circumstances, the window title (set by nvim [i0]) would appear over the line I was typing, corrupting the screen. 2. If I changed my $TERM from xterm-256color to the new hterm-256color (available since ncurses >=20210320), the window title corruption was gone, but pane scrolling was broken. Both problems are due to changes in the termcap files, their source of truth being the ncurses project. See "Timeline of ncurses changes" below for details. Cause: title corruption ----------------------- The title corruption when using hterm + TERM=xterm-256color can be explained by event neovim#4 (ncurses 2022-03-12) in the ncurses timeline: The xterm-256color termcap file gained status line termcodes in ncurses 2022-03-12. These termcodes are used by Neovim to set the title when. hterm does not have a status line. Due to ncurses versions earlier than 2022-03-12 missing the xterm status line capability, Neovim manually fixed up [t0] the terminfo file if $TERM was xterm-256color. So if before Neovim manually added fsl/tsl capabilties, and after they were in the termcap file, why did hterm suddenly start getting corruption? The answer is that the termcodes for these capabilties are different when Neovim fixes them up, versus the one in the new termcap database: fsl=\E[0$} // from xterm-256color tsl=\E[2$~\E[1$}\E[%i%p1%d` // from xterm-256color fsl=\x07 // patched by Neovim tsl=\x1b]0; // patched by Neovim hterm ignores the latter, but corrupts the screen with the former. Solution: Make hterm users set hterm-256color, which lacks the new fsl/tsl codes. Also, to reduce superfluous work, stop patching in this capability when hterm is detected (even if hterm would ignore the patched version). Cause: pane corruption ---------------------- The pane corruption when using hterm + TERM=hterm-256color, but NOT when using hterm + TERM=xterm-256color can be explained by: - Neovim uses DECSLRM when available [p1] for performant scrolling. - Both the hterm-256color and xterm-256color termcap databases advertise support for DECSLRM (ncurses timeline #1, neovim#2 and neovim#3). - hterm does not support DESCLRM [p2] (note: it does support DESCTBM for top/bottom scrolling, but it's broken [p3] and not used by Neovim) - xterm-alikes that are not real xterm generally don't support DECSLRM either, so Neovim patches it out [p4]. When using hterm-256color, hterm is no longer considered an xterm-alike by Neovim. As a result, DECSLRM is not cleared. hterm does not support it, so corruption ensues. This is a problem with the hterm-256color termcap file, but we're stuck with it so the best we can do is patch over it. Timeline of ncurses changes --------------------------- 1. 2019-05-19: Part of the DECSLRM capability (smglr AKA set_lr_margin) added to vt420+lrmm, which xterm-256color inherits [n1] 2. 2021-03-20: hterm-256color added, inheriting xterm-256colors. [n2] 3. 2021-09-25: The *parm versions of smglr (AKA set_lr_margin) were added to vt420+lrmm [n3]. Namely: 1. smglp AKA set_left_margin_parm, and 2. smgrp AKA set_right_margin_parm 4. 2022-03-12: (new) codes for fsl, bsl and tsl added to xterm (add dec+sl to xterm-new, per patch neovim#371 -TD) [n4] Fixes neovim#19040. [i0]: https://github.com/neovim/neovim/blob/3a4fa22badc5595afc0a994ead965ff32ccf6c76/src/nvim/tui/tui.c#L1377 [t0]: https://github.com/neovim/neovim/blob/3a4fa22badc5595afc0a994ead965ff32ccf6c76/src/nvim/tui/tui.c#L1728,L1729 [p1]: https://github.com/neovim/neovim/blob/3a4fa22badc5595afc0a994ead965ff32ccf6c76/src/nvim/tui/tui.c#L1196 [p2]: https://bugs.chromium.org/p/chromium/issues/detail?id=1175065&q=component%3APlatform%3EApps%3EDefault%3EHterm [p3]: https://bugs.chromium.org/p/chromium/issues/detail?id=1298796&q=component%3APlatform%3EApps%3EDefault%3EHterm [p4]: https://github.com/neovim/neovim/blob/3a4fa22badc5595afc0a994ead965ff32ccf6c76/src/nvim/tui/tui.c#L1740-L1752 [n1]: mirror/ncurses@8f6d94b#diff-01544c577762d3308a1d232aa7afc79acf64b9a5057f88a004df82fda89549b7R2742 [n2]: mirror/ncurses@c265010#diff-01544c577762d3308a1d232aa7afc79acf64b9a5057f88a004df82fda89549b7R5907 [n3]: mirror/ncurses@f6b436c#diff-01544c577762d3308a1d232aa7afc79acf64b9a5057f88a004df82fda89549b7R2842 [n4]: mirror/ncurses@8bf8c83#diff-01544c577762d3308a1d232aa7afc79acf64b9a5057f88a004df82fda89549b7R4828 Signed-off-by: Nicolas Hillegeer <[email protected]>
1 parent b999de2 commit 45ba2e1

File tree

1 file changed

+17
-6
lines changed

1 file changed

+17
-6
lines changed

src/nvim/tui/tui.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,6 +1642,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col
16421642
bool xterm = terminfo_is_term_family(term, "xterm")
16431643
// Treat Terminal.app as generic xterm-like, for now.
16441644
|| nsterm;
1645+
bool hterm = terminfo_is_term_family(term, "hterm");
16451646
bool kitty = terminfo_is_term_family(term, "xterm-kitty");
16461647
bool linuxvt = terminfo_is_term_family(term, "linux");
16471648
bool bsdvt = terminfo_is_bsd_console(term);
@@ -1705,7 +1706,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col
17051706
unibi_set_bool(ut, unibi_back_color_erase, false);
17061707
}
17071708

1708-
if (xterm) {
1709+
if (xterm || hterm) {
17091710
// Termit, LXTerminal, GTKTerm2, GNOME Terminal, MATE Terminal, roxterm,
17101711
// and EvilVTE falsely claim to be xterm and do not support important xterm
17111712
// control sequences that we use. In an ideal world, these would have
@@ -1714,9 +1715,13 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col
17141715
// treatable as xterm.
17151716

17161717
// 2017-04 terminfo.src lacks these. Xterm-likes have them.
1717-
unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]0;");
1718-
unibi_set_if_empty(ut, unibi_from_status_line, "\x07");
1719-
unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr");
1718+
if (!hterm) {
1719+
// hterm doesn't have a status line.
1720+
unibi_set_if_empty(ut, unibi_to_status_line, "\x1b]0;");
1721+
unibi_set_if_empty(ut, unibi_from_status_line, "\x07");
1722+
// TODO(aktau): patch this in when DECSTBM is fixed (https://crbug.com/1298796)
1723+
unibi_set_if_empty(ut, unibi_set_tb_margin, "\x1b[%i%p1%d;%p2%dr");
1724+
}
17201725
unibi_set_if_empty(ut, unibi_enter_italics_mode, "\x1b[3m");
17211726
unibi_set_if_empty(ut, unibi_exit_italics_mode, "\x1b[23m");
17221727

@@ -1727,6 +1732,9 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col
17271732
unibi_set_if_empty(ut, unibi_set_right_margin_parm, "\x1b[%i;%p2%ds");
17281733
} else {
17291734
// Fix things advertised via TERM=xterm, for non-xterm.
1735+
//
1736+
// TODO(aktau): stop patching this out for hterm when it gains support
1737+
// (https://crbug.com/1175065).
17301738
if (unibi_get_str(ut, unibi_set_lr_margin)) {
17311739
ILOG("Disabling smglr with TERM=xterm for non-xterm.");
17321740
unibi_set_str(ut, unibi_set_lr_margin, NULL);
@@ -1875,6 +1883,8 @@ static void patch_terminfo_bugs(TUIData *data, const char *term, const char *col
18751883
&& ((xterm && !vte_version) // anything claiming xterm compat
18761884
// per MinTTY 0.4.3-1 release notes from 2009
18771885
|| putty
1886+
// per https://chromium.googlesource.com/apps/libapps/+/a5fb83c190aa9d74f4a9bca233dac6be2664e9e9/hterm/doc/ControlSequences.md
1887+
|| hterm
18781888
// per https://bugzilla.gnome.org/show_bug.cgi?id=720821
18791889
|| (vte_version >= 3900)
18801890
|| (konsolev >= 180770) // #9364
@@ -1959,6 +1969,7 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
19591969
bool xterm = terminfo_is_term_family(term, "xterm")
19601970
// Treat Terminal.app as generic xterm-like, for now.
19611971
|| nsterm;
1972+
bool hterm = terminfo_is_term_family(term, "hterm");
19621973
bool bsdvt = terminfo_is_bsd_console(term);
19631974
bool dtterm = terminfo_is_term_family(term, "dtterm");
19641975
bool rxvt = terminfo_is_term_family(term, "rxvt");
@@ -1988,7 +1999,7 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
19881999
"ext.resize_screen",
19892000
"\x1b[8;%p1%d;%p2%dt");
19902001
}
1991-
if (putty || xterm || rxvt) {
2002+
if (putty || xterm || hterm || rxvt) {
19922003
data->unibi_ext.reset_scroll_region = (int)unibi_add_ext_str(ut,
19932004
"ext.reset_scroll_region",
19942005
"\x1b[r");
@@ -2045,7 +2056,7 @@ static void augment_terminfo(TUIData *data, const char *term, long vte_version,
20452056
// would use a tmux control sequence and an extra if(screen) test.
20462057
data->unibi_ext.set_cursor_color =
20472058
(int)unibi_add_ext_str(ut, NULL, TMUX_WRAP(tmux, "\033]Pl%p1%06x\033\\"));
2048-
} else if ((xterm || rxvt || tmux || alacritty)
2059+
} else if ((xterm || hterm || rxvt || tmux || alacritty)
20492060
&& (vte_version == 0 || vte_version >= 3900)) {
20502061
// Supported in urxvt, newer VTE.
20512062
data->unibi_ext.set_cursor_color = (int)unibi_add_ext_str(ut, "ext.set_cursor_color",

0 commit comments

Comments
 (0)