k_board 1.2.0

A keyboard event handler that allows dynamic development
Documentation
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();
}

// look at https://linux.die.net/man/3/termios
#[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" {
    /*tcsetattr() sets the parameters associated with the terminal
    (unless support is required from the underlying hardware that is
    not available) from the termios structure referred to by termios_p.
    optional_actions specifies when the changes take effect*/
    pub fn tcsetattr(
        fd: std::ffi::c_int,
        optional_actions: std::ffi::c_int,
        termios_p: *const termios,
    ) -> std::ffi::c_int;
    /*tcgetattr() gets the parameters associated with the object referred
    by fd and stores them in the termios structure referenced by termios_p.
    This function may be invoked from a background process; however, the terminal
    attributes may be subsequently changed by a foreground process.*/
    pub fn tcgetattr(fd: std::ffi::c_int, termios: *mut termios) -> std::ffi::c_int;
}