use std::io;
use crate::mat;
pub mod key;
pub use key::{Key, Keys, ReadKeys};
pub struct Raw {
fd: libc::c_int,
backup: libc::termios,
}
impl Raw {
#[inline]
fn new() -> io::Result<Self> {
let fd = libc::STDOUT_FILENO;
let mut termios = c::getattr(fd)?;
let backup = termios;
c::makeraw(&mut termios);
c::setattr(fd, &termios)?;
Ok(Raw { fd, backup })
}
}
impl Drop for Raw {
#[inline]
fn drop(&mut self) {
_ = c::setattr(self.fd, &self.backup);
}
}
#[inline]
pub fn uncook() -> io::Result<Raw> {
Raw::new()
}
#[inline]
pub fn size() -> io::Result<mat::Size> {
let winsize = c::winsize()?;
Ok((winsize.ws_col as usize, winsize.ws_row as usize).into())
}
#[inline]
pub fn size_in_pixels() -> io::Result<mat::Size> {
let winsize = c::winsize()?;
Ok((winsize.ws_xpixel as usize, winsize.ws_ypixel as usize).into())
}
#[inline]
pub fn glyph_aspect_ratio() -> io::Result<f32> {
let size = size()?;
let size_px = size_in_pixels()?;
Ok((size.height as f32 / size.width as f32) * (size_px.width as f32 / size_px.height as f32))
}
mod c {
use std::io;
use std::mem;
#[inline]
pub fn getattr(fd: libc::c_int) -> io::Result<libc::termios> {
unsafe {
let mut termios = mem::zeroed();
libc::tcgetattr(fd, &mut termios).to_result()?;
Ok(termios)
}
}
#[inline]
pub fn setattr(fd: libc::c_int, termios: &libc::termios) -> io::Result<()> {
unsafe {
libc::tcsetattr(fd, libc::TCSANOW, termios).to_result()?;
Ok(())
}
}
#[inline]
pub fn makeraw(termios: &mut libc::termios) {
unsafe {
libc::cfmakeraw(termios);
}
termios.c_cc[libc::VMIN] = 0;
termios.c_cc[libc::VTIME] = 0;
}
#[inline]
pub fn winsize() -> io::Result<libc::winsize> {
unsafe {
let mut winsize: libc::winsize = mem::zeroed();
libc::ioctl(libc::STDOUT_FILENO, libc::TIOCGWINSZ, &mut winsize).to_result()?;
Ok(winsize)
}
}
trait ToResult: Sized {
fn to_result(self) -> io::Result<Self>;
}
impl ToResult for libc::c_int {
#[inline]
fn to_result(self) -> io::Result<Self> {
if self < 0 {
Err(io::Error::last_os_error())
} else {
Ok(self)
}
}
}
}