minicrossterm/src/input/windows_input.rs

228 lines
5.8 KiB
Rust

use std::io;
use std::io::Write;
use std::char;
use std::sync::mpsc;
use std::thread;
use super::{ Key, ITerminalInput, AsyncReader };
use winapi::um::winnt::{ INT };
use winapi::um::winuser;
use super::super::terminal::terminal;
use super::super::kernel::windows_kernel::reading;
use Context;
use std::rc::Rc;
pub struct WindowsInput
{
context: Rc<Context>,
pub display_input: bool,
}
impl WindowsInput
{
pub fn new(context: Rc<Context>) -> WindowsInput
{
WindowsInput { context, display_input: false }
}
}
impl ITerminalInput for WindowsInput
{
fn read_line(&self) -> io::Result<String>
{
let term = terminal(&self.context);
let mut chars: Vec<char> = Vec::new();
loop {
let pressed_char = unsafe { _getwch() };
// if 0 or 0xe0 we need to listen again because the next key will be an special key
if pressed_char != 0 || pressed_char != 0xe0 {
match char::from_u32(pressed_char as u32)
{
Some(c) => {
if is_line_end(c) { break; }
else { chars.push(c); }
if self.display_input
{
term.write(c);
}
},
None => { panic!("Some error needs to be returned") }
};
}
}
return Ok(chars.into_iter().collect());
}
fn read_char(&self) -> io::Result<char>
{
let term = terminal(&self.context);
let pressed_char = unsafe { _getwch() };
// we could return error but maybe option to keep listening until valid character is inputted.
if pressed_char == 0 || pressed_char == 0xe0 {
return Err(io::Error::new(io::ErrorKind::Other, "Given input char is not a valid char, mostly occurs when pressing special keys"));
}
match char::from_u32(pressed_char as u32)
{
Some(c) => {
if self.display_input
{
term.write(c);
}
return Ok(c);
}
None => Err(io::Error::new(io::ErrorKind::Other, "Could not parse given input to char"))
}
}
fn read_pressed_key(&self) -> io::Result<Key>
{
use Context;
let context = Context::new();
let buf: [u8; 1024] = unsafe { ::std::mem::zeroed() };
// reading::read(&mut buf, &context.screen_manager);
Ok(Key::Unknown)
// let pressed_char = unsafe { _getwch() };
//
// // if 0 or 0xe0 we need to listen again because the next key will be an special key
// if pressed_char == 0 || pressed_char == 0xe0 {
// let special_key: i32 = unsafe { _getwch() };
// println!("spkey {}",special_key);
// return Ok(key_from_key_code(0x26));
// } else {
// match char::from_u32(pressed_char as u32)
// {
// Some(c) => return Ok(Key::Char(c)),
// None => { panic!("Some error needs to be returned") }
// }
// }
}
fn read_async(&self) -> AsyncReader
{
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
loop
{
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
// we could return error but maybe option to keep listening until valid character is inputted.
if pressed_char == 0 || pressed_char == 0xe0 {
return;
}
tx.send(Ok(pressed_char as u8));
if pressed_char == 13
{
return;
}
}
});
AsyncReader { recv: rx }
}
fn read_until_async(&self, delimiter: u8) -> AsyncReader
{
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
loop
{
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
let end_of_stream = (pressed_char == delimiter);
// we could return error but maybe option to keep listening until valid character is inputted.
if pressed_char == 0 || pressed_char == 0xe0 || end_of_stream {
return;
}
tx.send(Ok(pressed_char as u8));
}
});
AsyncReader { recv: rx }
}
}
fn is_line_end(key: char) -> bool
{
if key as u8 == 13
{
return true;
}
return false;
}
//0 59 = F1
//0 60 = F2
//0 61 = F3
//0 62 = F4
//0 63 = F5
//0 64 = F6
//0 65 = F7
//0 66 = F8
//0 67 = F9
//0 68 = F10
//224 71 = Home
//224 72 = ↑ (up arrow)
//224 73 = Page Up
//224 75 = ← (left arrow)
//224 77 = → (right arrow)
//224 79 = End
//224 80 = ↓ (down arrow)
//224 81 = Page Down
//224 82 = Insert
//224 83 = Delete
//224 133 = F11
//224 134 = F12
fn key_from_key_code(code: INT) -> Key {
println!("code: {}", code);
println!("up winapi: {}", winuser::VK_UP);
match code {
// 59 => Key::F1,
// 60 => Key::F2,
// 61 => Key::F3,
// 62 => Key::F4,
// 63 => Key::F5,
// 64 => Key::F6,
// 65 => Key::F7,
// 66 => Key::F8,
// 67 => Key::F9,
// 68 => Key::F10,
winuser::VK_LEFT => Key::ArrowLeft,
winuser::VK_RIGHT => Key::ArrowRight,
winuser::VK_UP => Key::ArrowUp,
winuser::VK_DOWN => Key::ArrowDown,
winuser::VK_RETURN => Key::Enter,
winuser::VK_ESCAPE => Key::Escape,
winuser::VK_BACK => Key::Char('\x08'),
winuser::VK_TAB => Key::Char('\x09'),
_ => Key::Unknown,
}
}
extern "C" {
fn _getwch() -> INT;
fn _getwch_nolock() -> INT;
}