fast image operations
Diffstat (limited to 'src/term/size/unix.rs')
-rw-r--r--src/term/size/unix.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/term/size/unix.rs b/src/term/size/unix.rs
new file mode 100644
index 0000000..718373e
--- /dev/null
+++ b/src/term/size/unix.rs
@@ -0,0 +1,67 @@
+extern crate libc;
+use std::fs::File;
+use std::mem::MaybeUninit as MU;
+use std::ops::Deref;
+use std::os::fd::IntoRawFd;
+
+use libc::*;
+
+struct Fd(i32, bool);
+impl Drop for Fd {
+ fn drop(&mut self) {
+ if self.1 {
+ unsafe { close(self.0) };
+ }
+ }
+}
+impl Fd {
+ pub fn new(x: File) -> Self {
+ Self(x.into_raw_fd(), true)
+ }
+}
+
+impl From<i32> for Fd {
+ fn from(value: i32) -> Self {
+ Self(value, false)
+ }
+}
+
+impl Deref for Fd {
+ type Target = i32;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+pub fn size() -> Option<(u16, u16)> {
+ // SAFETY: SYS
+ unsafe {
+ let mut size = MU::<winsize>::uninit();
+
+ if ioctl(
+ *File::open("/dev/tty")
+ .map(Fd::new)
+ .unwrap_or(Fd::from(STDIN_FILENO)),
+ TIOCGWINSZ.into(),
+ size.as_mut_ptr(),
+ ) != -1
+ {
+ let winsize { ws_col, ws_row, .. } = size.assume_init();
+ return Some((ws_col as _, ws_row as _)).filter(|&(w, h)| w != 0 && h != 0);
+ }
+ tput("cols").and_then(|w| tput("lines").map(|h| (w, h)))
+ }
+}
+
+pub fn tput(arg: &'static str) -> Option<u16> {
+ let x = std::process::Command::new("tput").arg(arg).output().ok()?;
+ String::from_utf8(x.stdout)
+ .ok()
+ .and_then(|x| x.parse::<u16>().ok())
+}
+
+#[test]
+fn t() {
+ println!("{:?}", size().unwrap());
+}