use color::Color;
use general::*;
use initialize::end_window;
use std::sync::Mutex;
use std::time::Duration;
use window::Window;
#[repr(i32)]
pub enum CursorVisibility {
Invisible = 0,
Normal,
HighlyVisible,
}
pub struct BitsPerSecond {
bps: i32,
}
impl BitsPerSecond {
pub fn new(bps: i32) -> Self {
BitsPerSecond { bps }
}
pub fn bits_per_second(&self) -> i32 {
self.bps
}
}
pub enum InputBufferingMode {
Buffered,
UnbufferedWithSignals,
UnbufferedNoSignals,
}
pub struct Curses {
window: Window,
key_name_mutex: Mutex<()>,
color: Option<Color>,
}
impl Curses {
pub(crate) fn new(window: Window) -> Self {
Curses {
window,
key_name_mutex: Mutex::new(()),
color: None,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn window_mut(&mut self) -> &mut Window {
&mut self.window
}
pub fn has_colors(&self) -> bool {
pancurses::has_colors()
}
pub fn start_color(&mut self) -> Result<(), ()> {
if self.color.is_none() {
check(pancurses::start_color())?;
self.color = Some(Color::new());
}
Ok(())
}
pub fn color(&self) -> &Color {
self.color
.as_ref()
.expect("Color subsystem has not yet been successfully started")
}
pub fn color_mut(&mut self) -> &mut Color {
self.color
.as_mut()
.expect("Color subsystem has not yet been successfully started")
}
pub fn set_cursor_visibility(&mut self, visibility: CursorVisibility) -> Result<(), ()> {
check(pancurses::curs_set(unsafe {
std::mem::transmute(visibility)
}))
}
pub fn define_program_mode(&mut self) -> Result<(), ()> {
check(pancurses::def_prog_mode())
}
pub fn define_shell_mode(&mut self) -> Result<(), ()> {
check(pancurses::def_shell_mode())
}
pub fn restore_program_mode(&mut self) -> Result<(), ()> {
check(pancurses::reset_prog_mode())
}
pub fn restore_shell_mode(&mut self) -> Result<(), ()> {
check(pancurses::reset_shell_mode())
}
pub fn output_rate(&self) -> BitsPerSecond {
BitsPerSecond {
bps: pancurses::baudrate(),
}
}
pub fn delay_output(&mut self, time: Duration) -> Result<(), ()> {
check(pancurses::delay_output(as_millis(time)))
}
pub fn update(&mut self) -> Result<(), ()> {
check(pancurses::doupdate())
}
pub fn set_echo_input(&mut self, echo: bool) -> Result<(), ()> {
if echo {
check(pancurses::echo())
} else {
check(pancurses::noecho())
}
}
pub fn set_input_buffering_mode(&mut self, mode: InputBufferingMode) -> Result<(), ()> {
match mode {
InputBufferingMode::Buffered => {
let l = check(pancurses::noraw());
let r = check(pancurses::nocbreak());
l.and(r)
}
InputBufferingMode::UnbufferedWithSignals => {
let l = check(pancurses::noraw());
let r = check(pancurses::cbreak());
l.and(r)
}
InputBufferingMode::UnbufferedNoSignals => {
let l = check(pancurses::cbreak());
let r = check(pancurses::raw());
l.and(r)
}
}
}
pub fn set_translate_new_lines(&mut self, translate: bool) -> Result<(), ()> {
if translate {
check(pancurses::nl())
} else {
check(pancurses::nonl())
}
}
pub fn flush_input(&mut self) -> Result<(), ()> {
check(pancurses::flushinp())
}
pub fn set_timeout(&mut self, duration: Duration) -> Result<(), ()> {
let tenths = as_millis(duration) / 100;
if tenths < 1 || tenths > 255 {
Err(())?
}
check(pancurses::half_delay(tenths))
}
pub fn end_curses(self) -> Result<(), ()> {
let r = end_window();
std::mem::forget(self);
r
}
pub fn flash(&mut self) -> Result<(), ()> {
check(pancurses::flash())
}
pub fn key_name(&self, key_code: i32) -> Option<String> {
let _key_name = self.key_name_mutex.lock().unwrap();
pancurses::keyname(key_code)
}
pub fn mouse_read(&self) -> Result<MouseEvent, ()> {
pancurses::getmouse().map_err(|_| ())
}
pub fn mouse_interval(&self) -> Duration {
Duration::from_millis(pancurses::mouseinterval(-1) as u64)
}
pub fn set_mouse_interval(&mut self, interval: Duration) -> Result<(), ()> {
pancurses::mouseinterval(as_millis(interval));
Ok(())
}
pub fn set_mouse_mask(
&mut self,
mask: MouseMask,
old_mask: Option<&mut MouseMask>,
) -> Result<MouseMask, ()> {
let old_mask_ptr = match old_mask {
Some(mask) => mask,
None => std::ptr::null_mut(),
};
Ok(pancurses::mousemask(mask, old_mask_ptr))
}
pub fn sleep(&mut self, duration: Duration) -> Result<(), ()> {
check(pancurses::napms(as_millis(duration)))
}
pub fn resize_terminal(&mut self, rows: i32, columns: i32) -> Result<(), ()> {
check(pancurses::resize_term(rows, columns))
}
pub fn beep(&mut self) -> Result<(), ()> {
check(pancurses::beep())
}
pub fn set_force_blink(&mut self, blink: bool) -> Result<(), ()> {
check(pancurses::set_blink(blink))
}
pub fn set_title<T: AsRef<str>>(&mut self, title: T) -> Result<(), ()> {
Ok(pancurses::set_title(title.as_ref()))
}
}
impl Drop for Curses {
fn drop(&mut self) {
end_window().unwrap();
}
}