devela/sys/os/linux/structs/
termios.rs#![cfg_attr(not(feature = "unsafe_syscall"), allow(dead_code))]
use crate::c_uint;
#[cfg(all(feature = "unsafe_syscall", not(miri)))]
use crate::{iif, linux_sys_ioctl, LINUX_ERRNO, LINUX_FILENO, LINUX_IOCTL, LINUX_TERMIOS_LFLAG};
#[derive(Clone, Copy, Debug, Default, PartialEq)]
#[repr(C)]
pub struct LinuxTermios {
pub c_iflag: c_uint,
pub c_oflag: c_uint,
pub c_cflag: c_uint,
pub c_lflag: c_uint,
pub c_line: u8,
pub c_cc: [u8; 19],
}
#[cfg_attr(
feature = "nightly_doc",
doc(cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck")))
)]
#[cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck"))]
unsafe impl crate::_dep::bytemuck::NoUninit for LinuxTermios {}
impl LinuxTermios {
#[must_use]
pub const fn new() -> Self {
Self {
c_iflag: 0,
c_oflag: 0,
c_cflag: 0,
c_lflag: 0,
c_line: 0,
c_cc: [0; 19],
}
}
#[must_use]
pub const fn as_bytes_ptr(&self) -> *const u8 {
self as *const Self as *const u8
}
#[must_use]
pub fn as_mut_bytes_ptr(&mut self) -> *mut u8 {
self as *mut Self as *mut u8
}
}
#[cfg(all(
any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "arm",
target_arch = "aarch64",
target_arch = "riscv32",
target_arch = "riscv64"
),
feature = "unsafe_syscall",
not(miri),
))]
impl LinuxTermios {
#[cfg(all(feature = "unsafe_syscall", not(miri)))]
#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_syscall")))]
pub fn get_state() -> Result<LinuxTermios, isize> {
let mut state = LinuxTermios::new();
let res = unsafe {
linux_sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCGETS, state.as_mut_bytes_ptr())
};
iif![res >= 0; Ok(state); Err(res)]
}
#[cfg(all(feature = "unsafe_syscall", not(miri)))]
#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_syscall")))]
pub fn set_state(mut state: LinuxTermios) -> Result<(), isize> {
let res = unsafe {
linux_sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCSETS, state.as_mut_bytes_ptr())
};
iif![res >= 0; Ok(()); Err(res)]
}
#[must_use]
pub fn is_terminal() -> bool {
match Self::get_state() {
Ok(_) => true,
Err(e) => e != -LINUX_ERRNO::ENOTTY && e != -LINUX_ERRNO::EINVAL,
}
}
pub fn disable_raw_mode() -> Result<(), isize> {
let mut state = LinuxTermios::get_state()?;
state.c_lflag |= LINUX_TERMIOS_LFLAG::ICANON;
state.c_lflag |= LINUX_TERMIOS_LFLAG::ECHO;
LinuxTermios::set_state(state)
}
pub fn enable_raw_mode() -> Result<(), isize> {
let mut state = Self::get_state()?;
state.c_lflag &= !LINUX_TERMIOS_LFLAG::ICANON;
state.c_lflag &= !LINUX_TERMIOS_LFLAG::ECHO;
LinuxTermios::set_state(state)
}
#[cfg(all(feature = "unsafe_syscall", not(miri)))]
#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_syscall")))]
pub fn get_winsize() -> Result<LinuxTerminalSize, isize> {
let mut winsize = LinuxTerminalSize::default();
let res = unsafe {
linux_sys_ioctl(
LINUX_FILENO::STDIN,
LINUX_IOCTL::TIOCGWINSZ,
&mut winsize as *mut LinuxTerminalSize as *mut u8,
)
};
iif![res >= 0; Ok(winsize); Err(res)]
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
#[repr(C)] pub struct LinuxTerminalSize {
pub rows: u16,
pub cols: u16,
pub x: u16,
pub y: u16,
}
impl LinuxTerminalSize {
#[must_use]
pub const fn pixels(self) -> [u16; 2] {
[self.x, self.y]
}
#[must_use]
pub const fn cells(self) -> [u16; 2] {
[self.cols, self.rows]
}
#[must_use]
pub const fn pixels_per_cell(self) -> [u16; 2] {
[self.x / self.cols, self.y / self.rows]
}
}