Add xterm-256color fallback

And use it if $TERM is xterm-256color and could not be found, *without* warning.

These barely change, especially in the parts we use.
This commit is contained in:
Fabian Boehm 2024-01-28 10:16:32 +01:00
parent 8c86336109
commit 75f7cda6ab
2 changed files with 97 additions and 2 deletions

View file

@ -41,6 +41,7 @@ pub fn term() -> Option<Arc<Term>> {
///
/// An extant `Term` instance means the curses `TERMINAL *cur_term` pointer is non-null. Any
/// functionality that is normally performed using `cur_term` should be done via `Term` instead.
#[derive(Default)]
pub struct Term {
// String capabilities. Any Some value is confirmed non-empty.
pub enter_bold_mode: Option<CString>,
@ -394,6 +395,79 @@ where
}
}
pub fn setup_fallback_term() -> Arc<Term> {
let mut global_term = TERM.lock().expect("Mutex poisoned!");
// These values extracted from xterm-256color from ncurses 6.4
let term = Term {
enter_bold_mode: Some(CString::new("\x1b[1m").unwrap()),
enter_italics_mode: Some(CString::new("\x1b[3m").unwrap()),
exit_italics_mode: Some(CString::new("\x1b[23m").unwrap()),
enter_dim_mode: Some(CString::new("\x1b[2m").unwrap()),
enter_underline_mode: Some(CString::new("\x1b[4m").unwrap()),
exit_underline_mode: Some(CString::new("\x1b[24m").unwrap()),
enter_reverse_mode: Some(CString::new("\x1b[7m").unwrap()),
enter_standout_mode: Some(CString::new("\x1b[7m").unwrap()),
exit_standout_mode: Some(CString::new("\x1b[27m").unwrap()),
enter_blink_mode: Some(CString::new("\x1b[5m").unwrap()),
enter_secure_mode: Some(CString::new("\x1b[8m").unwrap()),
enter_alt_charset_mode: Some(CString::new("\x1b(0").unwrap()),
exit_alt_charset_mode: Some(CString::new("\x1b(B").unwrap()),
set_a_foreground: Some(
CString::new("\x1b[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m")
.unwrap(),
),
set_a_background: Some(
CString::new("\x1b[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m")
.unwrap(),
),
exit_attribute_mode: Some(CString::new("\x1b(B\x1b[m").unwrap()),
clear_screen: Some(CString::new("\x1b[H\x1b[2J").unwrap()),
cursor_up: Some(CString::new("\x1b[A").unwrap()),
cursor_down: Some(CString::new("\n").unwrap()),
cursor_left: Some(CString::new("\x08").unwrap()),
cursor_right: Some(CString::new("\x1b[C").unwrap()),
parm_left_cursor: Some(CString::new("\x1b[%p1%dD").unwrap()),
parm_right_cursor: Some(CString::new("\x1b[%p1%dC").unwrap()),
clr_eol: Some(CString::new("\x1b[K").unwrap()),
clr_eos: Some(CString::new("\x1b[J").unwrap()),
max_colors: Some(256),
init_tabs: Some(8),
eat_newline_glitch: true,
auto_right_margin: true,
key_a1: Some(CString::new("\x1bOw").unwrap()),
key_a3: Some(CString::new("\x1bOy").unwrap()),
key_b2: Some(CString::new("\x1bOu").unwrap()),
key_backspace: Some(CString::new("\x7f").unwrap()),
key_btab: Some(CString::new("\x1b[Z").unwrap()),
key_c1: Some(CString::new("\x1bOq").unwrap()),
key_c3: Some(CString::new("\x1bOs").unwrap()),
key_dc: Some(CString::new("\x1b[3~").unwrap()),
key_down: Some(CString::new("\x1bOB").unwrap()),
key_f1: Some(CString::new("\x1bOP").unwrap()),
key_home: Some(CString::new("\x1bOH").unwrap()),
key_ic: Some(CString::new("\x1b[2~").unwrap()),
key_left: Some(CString::new("\x1bOD").unwrap()),
key_npage: Some(CString::new("\x1b[6~").unwrap()),
key_ppage: Some(CString::new("\x1b[5~").unwrap()),
key_right: Some(CString::new("\x1bOC").unwrap()),
key_sdc: Some(CString::new("\x1b[3;2~").unwrap()),
key_send: Some(CString::new("\x1b[1;2F").unwrap()),
key_sf: Some(CString::new("\x1b[1;2B").unwrap()),
key_shome: Some(CString::new("\x1b[1;2H").unwrap()),
key_sic: Some(CString::new("\x1b[2;2~").unwrap()),
key_sleft: Some(CString::new("\x1b[1;2D").unwrap()),
key_snext: Some(CString::new("\x1b[6;2~").unwrap()),
key_sprevious: Some(CString::new("\x1b[5;2~").unwrap()),
key_sr: Some(CString::new("\x1b[1;2A").unwrap()),
key_sright: Some(CString::new("\x1b[1;2C").unwrap()),
key_up: Some(CString::new("\x1bOA").unwrap()),
..Default::default()
};
let term = Arc::new(term);
*global_term = Some(term.clone());
term
}
/// Return a nonempty String capability from termcap, or None if missing or empty.
/// Panics if the given code string does not contain exactly two bytes.
fn get_str_cap(db: &terminfo::Database, code: &str) -> Option<CString> {

View file

@ -496,6 +496,19 @@ fn initialize_curses_using_fallbacks(vars: &EnvStack) {
.map(|v| v.as_string())
.unwrap_or(Default::default());
let mut success = false;
if current_term == "xterm-256color" {
// If we have xterm-256color, let's just use our hard-coded version
// instead of trying to read xterm or "ansi".
// It's almost certain we can't find terminfo.
FLOG!(
term_support,
"Could not read xterm-256color. Using fallback."
);
curses::setup_fallback_term();
return;
}
for term in FALLBACKS {
// If $TERM is already set to the fallback name we're about to use, there's no point in
// seeing if the fallback name can be used.
@ -505,8 +518,7 @@ fn initialize_curses_using_fallbacks(vars: &EnvStack) {
// `term` here is one of our hard-coded strings above; we can unwrap because we can
// guarantee it doesn't contain any interior NULs.
let success =
curses::setup(Some(&term), |term| apply_term_hacks(vars, term)).is_some();
success = curses::setup(Some(&term), |term| apply_term_hacks(vars, term)).is_some();
if is_interactive_session() {
if success {
FLOG!(warning, wgettext!("Using fallback terminal type"), term);
@ -523,6 +535,15 @@ fn initialize_curses_using_fallbacks(vars: &EnvStack) {
break;
}
}
if !success {
if is_interactive_session() {
FLOG!(
warning,
wgettext!("Could not get any terminfo database, falling back to hardcoded xterm-256color values"),
);
}
curses::setup_fallback_term();
}
}
/// Apply any platform- or environment-specific hacks to our curses [`Term`] instance.