#[cfg(unix)]
mod imp {
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::atomic::{AtomicPtr, AtomicUsize};
const STDIN_FD: libc::c_int = 0;
const STDOUT_FD: libc::c_int = 1;
const RESET: &[u8] = b"\x1b[?25h\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1006l\x1b[?2004l";
static mut SAVED: libc::termios = unsafe { std::mem::zeroed() };
static HAVE_SAVED: AtomicBool = AtomicBool::new(false);
static INSTALLED: AtomicBool = AtomicBool::new(false);
static EXTRA_PTR: AtomicPtr<u8> = AtomicPtr::new(std::ptr::null_mut());
static EXTRA_LEN: AtomicUsize = AtomicUsize::new(0);
extern "C" fn handler(sig: libc::c_int) {
unsafe {
let extra_ptr = EXTRA_PTR.load(Ordering::SeqCst);
let extra_len = EXTRA_LEN.load(Ordering::SeqCst);
if !extra_ptr.is_null() && extra_len > 0 {
libc::write(STDOUT_FD, extra_ptr as *const libc::c_void, extra_len);
}
libc::write(
STDOUT_FD,
RESET.as_ptr() as *const libc::c_void,
RESET.len(),
);
if HAVE_SAVED.load(Ordering::SeqCst) {
libc::tcsetattr(STDIN_FD, libc::TCSANOW, std::ptr::addr_of!(SAVED));
}
libc::signal(sig, libc::SIG_DFL);
libc::raise(sig);
}
}
pub fn install(extra: &'static [u8]) {
if INSTALLED.swap(true, Ordering::SeqCst) {
return;
}
EXTRA_PTR.store(extra.as_ptr() as *mut u8, Ordering::SeqCst);
EXTRA_LEN.store(extra.len(), Ordering::SeqCst);
unsafe {
if libc::tcgetattr(STDIN_FD, std::ptr::addr_of_mut!(SAVED)) == 0 {
HAVE_SAVED.store(true, Ordering::SeqCst);
}
for &sig in &[
libc::SIGSEGV,
libc::SIGABRT,
libc::SIGBUS,
libc::SIGILL,
libc::SIGTRAP,
libc::SIGFPE,
] {
libc::signal(sig, handler as *const () as libc::sighandler_t);
}
}
}
}
#[cfg(unix)]
pub use imp::install;
#[cfg(not(unix))]
pub fn install(_extra: &'static [u8]) {}
pub const ALT_SCREEN_EXTRA: &[u8] = b"\x1b[?1003l\x1b[?1006l\x1b[?1002l\x1b[?1000l\x1b[?1049l";