devela/sys/os/linux/structs/
termios.rs1#![cfg_attr(not(feature = "unsafe_syscall"), allow(dead_code))]
4
5use crate::c_uint;
6#[cfg(all(feature = "unsafe_syscall", not(miri)))]
7use crate::{iif, linux_sys_ioctl, LINUX_ERRNO, LINUX_FILENO, LINUX_IOCTL, LINUX_TERMIOS_LFLAG};
8
9#[derive(Clone, Copy, Debug, Default, PartialEq)]
17#[repr(C)]
18pub struct LinuxTermios {
19 pub c_iflag: c_uint,
21
22 pub c_oflag: c_uint,
24
25 pub c_cflag: c_uint,
27
28 pub c_lflag: c_uint,
30
31 pub c_line: u8,
33
34 pub c_cc: [u8; 19],
36}
37
38#[cfg_attr(
39 feature = "nightly_doc",
40 doc(cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck")))
41)]
42#[cfg(all(feature = "unsafe_syscall", feature = "dep_bytemuck"))]
43unsafe impl crate::_dep::bytemuck::NoUninit for LinuxTermios {}
44
45impl LinuxTermios {
46 #[must_use]
48 pub const fn new() -> Self {
49 Self {
50 c_iflag: 0,
51 c_oflag: 0,
52 c_cflag: 0,
53 c_lflag: 0,
54 c_line: 0,
55 c_cc: [0; 19],
56 }
57 }
58
59 #[must_use]
61 pub const fn as_bytes_ptr(&self) -> *const u8 {
62 self as *const Self as *const u8
63 }
64
65 #[must_use]
67 pub fn as_mut_bytes_ptr(&mut self) -> *mut u8 {
68 self as *mut Self as *mut u8
69 }
70}
71
72#[cfg(all(
73 any(
74 target_arch = "x86_64",
75 target_arch = "x86",
76 target_arch = "arm",
77 target_arch = "aarch64",
78 target_arch = "riscv32",
79 target_arch = "riscv64"
80 ),
81 feature = "unsafe_syscall",
82 not(miri),
83))]
84impl LinuxTermios {
85 #[cfg(all(feature = "unsafe_syscall", not(miri)))]
90 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_syscall")))]
91 pub fn get_state() -> Result<LinuxTermios, isize> {
92 let mut state = LinuxTermios::new();
93 let res = unsafe {
94 linux_sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCGETS, state.as_mut_bytes_ptr())
95 };
96 iif![res >= 0; Ok(state); Err(res)]
97 }
98
99 #[cfg(all(feature = "unsafe_syscall", not(miri)))]
103 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_syscall")))]
104 pub fn set_state(mut state: LinuxTermios) -> Result<(), isize> {
105 let res = unsafe {
106 linux_sys_ioctl(LINUX_FILENO::STDIN, LINUX_IOCTL::TCSETS, state.as_mut_bytes_ptr())
107 };
108 iif![res >= 0; Ok(()); Err(res)]
109 }
110
111 #[must_use]
113 pub fn is_terminal() -> bool {
114 match Self::get_state() {
115 Ok(_) => true,
116 Err(e) => e != -LINUX_ERRNO::ENOTTY && e != -LINUX_ERRNO::EINVAL,
117 }
118 }
119
120 pub fn disable_raw_mode() -> Result<(), isize> {
122 let mut state = LinuxTermios::get_state()?;
123 state.c_lflag |= LINUX_TERMIOS_LFLAG::ICANON;
124 state.c_lflag |= LINUX_TERMIOS_LFLAG::ECHO;
125 LinuxTermios::set_state(state)
126 }
127
128 pub fn enable_raw_mode() -> Result<(), isize> {
130 let mut state = Self::get_state()?;
131 state.c_lflag &= !LINUX_TERMIOS_LFLAG::ICANON;
132 state.c_lflag &= !LINUX_TERMIOS_LFLAG::ECHO;
133 LinuxTermios::set_state(state)
134 }
135
136 #[cfg(all(feature = "unsafe_syscall", not(miri)))]
138 #[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "unsafe_syscall")))]
139 pub fn get_winsize() -> Result<LinuxTerminalSize, isize> {
140 let mut winsize = LinuxTerminalSize::default();
141 let res = unsafe {
142 linux_sys_ioctl(
143 LINUX_FILENO::STDIN,
144 LINUX_IOCTL::TIOCGWINSZ,
145 &mut winsize as *mut LinuxTerminalSize as *mut u8,
146 )
147 };
148 iif![res >= 0; Ok(winsize); Err(res)]
149 }
150}
151
152#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
154#[repr(C)] pub struct LinuxTerminalSize {
156 pub rows: u16,
158
159 pub cols: u16,
161
162 pub x: u16,
164
165 pub y: u16,
167}
168
169impl LinuxTerminalSize {
170 #[must_use]
172 pub const fn pixels(self) -> [u16; 2] {
173 [self.x, self.y]
174 }
175 #[must_use]
177 pub const fn cells(self) -> [u16; 2] {
178 [self.cols, self.rows]
179 }
180
181 #[must_use]
183 pub const fn pixels_per_cell(self) -> [u16; 2] {
184 [self.x / self.cols, self.y / self.rows]
185 }
186}