#![allow(unsafe_code)]
use super::modes::not_a_terminal;
use std::io;
const STDIN: i32 = 0;
const TCSANOW: i32 = 0;
#[repr(C, align(16))]
#[derive(Clone)]
struct Termios([u8; 256]);
extern "C" {
fn isatty(fd: i32) -> i32;
fn tcgetattr(fd: i32, termios: *mut Termios) -> i32;
fn tcsetattr(fd: i32, optional_actions: i32, termios: *const Termios) -> i32;
fn cfmakeraw(termios: *mut Termios);
}
pub(super) struct Saved(Termios);
pub(super) fn enable() -> io::Result<Saved> {
if unsafe { isatty(STDIN) } != 1 {
return Err(not_a_terminal());
}
let mut original = Termios([0; 256]);
if unsafe { tcgetattr(STDIN, &mut original) } != 0 {
return Err(io::Error::last_os_error());
}
let mut raw = original.clone();
unsafe { cfmakeraw(&mut raw) };
if unsafe { tcsetattr(STDIN, TCSANOW, &raw) } != 0 {
return Err(io::Error::last_os_error());
}
Ok(Saved(original))
}
pub(super) fn restore(saved: &Saved) {
unsafe { tcsetattr(STDIN, TCSANOW, &saved.0) };
}