diff options
Diffstat (limited to 'src/sc.rs')
| -rw-r--r-- | src/sc.rs | 134 |
1 files changed, 0 insertions, 134 deletions
diff --git a/src/sc.rs b/src/sc.rs deleted file mode 100644 index cb20c68..0000000 --- a/src/sc.rs +++ /dev/null @@ -1,134 +0,0 @@ -use libc::{termios, winsize}; -use std::error::Error; -use std::io::{stdin, stdout, Read, Write}; -use std::sync::mpsc::{Receiver, SyncSender, TryRecvError}; - -pub fn move_cursor(row: u16, col: u16) -> Result<(), Box<dyn Error>> { - write!(stdout(), "\x1b[{};{}H", row + 1, col + 1)?; - Ok(()) -} - -pub fn clear() -> Result<(), Box<dyn Error>> { - write!(stdout(), "\x1b[2J")?; - Ok(()) -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum Key { - Up, - Down, - Left, - Right, -} - -pub struct Screen { - pub rows: u16, - pub cols: u16, - old_attr: termios, - cancel: SyncSender<()>, - keys: Receiver<Key>, -} - -impl Screen { - pub fn init() -> Result<Screen, Box<dyn Error>> { - let mut size: winsize; - unsafe { - size = std::mem::zeroed(); - if libc::ioctl(1, libc::TIOCGWINSZ, &mut size) < 0 { - return Err(Box::from("ioctl failed")); - } - } - if size.ws_col > 60 { - size.ws_col = 60; - } - if size.ws_row > 30 { - size.ws_row = 30; - } - - let mut attr; - unsafe { - attr = std::mem::zeroed(); - if libc::tcgetattr(1, &mut attr) < 0 { - return Err(Box::from("tcgetattr failed")); - } - } - - unsafe { - let mut raw = std::mem::zeroed(); - libc::cfmakeraw(&mut raw); - raw.c_cc[libc::VMIN] = 0; - raw.c_cc[libc::VTIME] = 1; - if libc::tcsetattr(1, libc::TCSANOW, &raw) < 0 { - return Err(Box::from("tcsetattr failed")); - } - } - - clear()?; - move_cursor(0, 0)?; - for _ in 0..size.ws_col { - write!(stdout(), "-")?; - } - for i in 1..size.ws_row - 1 { - move_cursor(i, 0)?; - write!(stdout(), "|")?; - move_cursor(i, size.ws_col - 1)?; - write!(stdout(), "|")?; - } - move_cursor(size.ws_row - 1, 0)?; - for _ in 0..size.ws_col { - write!(stdout(), "-")?; - } - - let (cancel_tx, cancel_rx) = std::sync::mpsc::sync_channel(0); - let (key_tx, key_rx) = std::sync::mpsc::sync_channel(4); - std::thread::spawn(move || { - let mut buf = [0; 3]; - while let Err(TryRecvError::Empty) = cancel_rx.try_recv() { - let Ok(n) = stdin().read(&mut buf) else { - continue; - }; - if n < 3 || buf[0] != 27 || buf[1] != b'[' { - continue; - } - let key = match buf[2] { - b'A' => Key::Up, - b'B' => Key::Down, - b'C' => Key::Right, - b'D' => Key::Left, - _ => { - continue; - } - }; - let _ = key_tx.try_send(key); - } - }); - - Ok(Screen { - rows: size.ws_row, - cols: size.ws_col, - old_attr: attr, - cancel: cancel_tx, - keys: key_rx, - }) - } - - pub fn read_key(&self) -> Option<Key> { - if let Ok(key) = self.keys.try_recv() { - return Some(key); - } - None - } - - pub fn in_bounds(&self, row: u16, col: u16) -> bool { - (1..self.rows - 1).contains(&row) && (1..self.cols - 1).contains(&col) - } -} - -impl Drop for Screen { - fn drop(&mut self) { - self.cancel.send(()).unwrap(); - unsafe { - libc::tcsetattr(1, libc::TCSANOW, &self.old_attr); - } - } -} |
