use std::io::Write;
#[allow(non_camel_case_types)]
type tcflag_t = std::ffi::c_uint;
const TCSANOW: std::ffi::c_int = 0;
const TCSADRAIN: std::ffi::c_int = 0;
const ICANON: tcflag_t = 0x00000002;
const ECHO: tcflag_t = 0x00000008;
const IXON: tcflag_t = 0x00000400;
const IXANY: tcflag_t = 0x00000800;
pub fn setup_raw_mode() -> std::io::Result<termios> {
let mut termios: termios = unsafe { std::mem::zeroed() };
if unsafe { tcgetattr(TCSANOW, &mut termios) } < 0 {
return Err(std::io::Error::last_os_error());
}
let original_termios = termios.clone();
termios.c_lflag &= !(ICANON | ECHO);
termios.c_iflag &= !(IXON | 0x00001000 | IXANY);
termios.c_cc[6] = 0;
termios.c_cc[5] = 1;
if unsafe { tcsetattr(TCSANOW, TCSADRAIN, &termios) } < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(original_termios)
}
pub fn restore_termios(original_termios: &termios) -> std::io::Result<()> {
if unsafe { tcsetattr(TCSANOW, TCSADRAIN, original_termios) } < 0 {
return Err(std::io::Error::last_os_error());
}
Ok(())
}
pub fn restore(termios_enviroment: &termios) {
std::io::stdout().flush().unwrap();
restore_termios(termios_enviroment).unwrap();
}
#[derive(Clone)]
#[repr(C)]
pub struct termios {
pub c_iflag: u32,
pub c_oflag: u32,
pub c_cflag: u32,
pub c_lflag: u32,
c_line: u8,
pub c_cc: [u8; 32],
c_ispeed: u32,
c_ospeed: u32,
}
#[link(name = "c")]
extern "C" {
pub fn tcsetattr(
fd: std::ffi::c_int,
optional_actions: std::ffi::c_int,
termios_p: *const termios,
) -> std::ffi::c_int;
pub fn tcgetattr(fd: std::ffi::c_int, termios: *mut termios) -> std::ffi::c_int;
}