minicrossterm/src/kernel/windows_kernel/cursor.rs
2018-07-22 14:55:14 +02:00

98 lines
2.8 KiB
Rust

//! This module handles some logic for cursor interaction in the windows console.
use winapi::shared::minwindef::{FALSE, TRUE};
use winapi::um::wincon::{
SetConsoleCursorInfo, SetConsoleCursorPosition, CONSOLE_CURSOR_INFO, COORD,
};
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
use super::{csbi, handle, kernel};
use std::io::{self, ErrorKind, Result};
use std::rc::Rc;
use std::sync::Mutex;
/// This stores the cursor pos, at program level. So it can be recalled later.
static mut SAVED_CURSOR_POS: (u16, u16) = (0, 0);
/// Reset to saved cursor position
pub fn reset_to_saved_position(screen_manager: &Rc<Mutex<ScreenManager>>) {
unsafe {
set_console_cursor_position(
SAVED_CURSOR_POS.0 as i16,
SAVED_CURSOR_POS.1 as i16,
screen_manager,
);
}
}
/// Save current cursor position to recall later.
pub fn save_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) {
let position = pos(screen_manager);
unsafe {
SAVED_CURSOR_POS = (position.0, position.1);
}
}
/// get the current cursor position.
pub fn pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
if let Ok(csbi) = csbi::get_csbi(screen_manager) {
(
csbi.dwCursorPosition.X as u16,
csbi.dwCursorPosition.Y as u16,
)
} else {
(0, 0)
}
}
/// Set the cursor position to the given x and y. Note that this is 0 based.
pub fn set_console_cursor_position(x: i16, y: i16, screen_manager: &Rc<Mutex<ScreenManager>>) {
if x < 0 || x >= <i16>::max_value() {
panic!(
"Argument Out of Range Exception when setting cursor position to X: {}",
x
);
}
if y < 0 || y >= <i16>::max_value() {
panic!(
"Argument Out of Range Exception when setting cursor position to Y: {}",
y
);
}
let handle = handle::get_current_handle(screen_manager).unwrap();
let position = COORD { X: x, Y: y };
unsafe {
let success = SetConsoleCursorPosition(handle, position);
if success == 0 {
panic!("Argument out of range when trying to set cursor position.");
}
}
}
/// change the cursor visibility.
pub fn cursor_visibility(visable: bool, screen_manager: &Rc<Mutex<ScreenManager>>) -> Result<()> {
let handle = handle::get_current_handle(screen_manager).unwrap();
let cursor_info = CONSOLE_CURSOR_INFO {
dwSize: 100,
bVisible: if visable { TRUE } else { FALSE },
};
unsafe {
if !kernel::is_true(SetConsoleCursorInfo(handle, &cursor_info)) {
return Err(io::Error::new(
io::ErrorKind::Other,
"Could not get console screen buffer info",
));
}
}
Ok(())
}