refactored winapi code
This commit is contained in:
parent
9df976ed29
commit
2cc40d5d28
@ -1,4 +1,3 @@
|
||||
|
||||
//! This bin folder can be used to try the examples out located in the examples directory.
|
||||
//!
|
||||
//! All you need to do is:
|
||||
@ -25,22 +24,87 @@ use input::keyboard::{async_input, input as stdin};
|
||||
|
||||
use crossterm::raw::IntoRawMode;
|
||||
|
||||
fn main()
|
||||
{
|
||||
let context = Context::new();
|
||||
use std::{thread, time};
|
||||
|
||||
fn main() {
|
||||
// let context = Context::new();
|
||||
crossterm();
|
||||
{
|
||||
// let screen = ::crossterm::screen::AlternateScreen::from(context.clone());
|
||||
// screen.into_raw_mode(context.clone());
|
||||
// let screen = ::crossterm::screen::AlternateScreen::from(context.clone());
|
||||
// screen.into_raw_mode(context.clone());
|
||||
|
||||
|
||||
async_input::async_reading_on_alternate_screen();
|
||||
// async_input::test();
|
||||
// stdin::t();
|
||||
// stdin::read_line();
|
||||
// stdin::read_char();
|
||||
// stdin::read_char();
|
||||
// async_input::async_reading_on_alternate_screen();
|
||||
// async_input::test();
|
||||
// stdin::t();
|
||||
// stdin::read_line();
|
||||
// stdin::read_char();
|
||||
// stdin::read_char();
|
||||
}
|
||||
}
|
||||
|
||||
use crossterm::raw::RawTerminal;
|
||||
use crossterm::Crossterm;
|
||||
|
||||
pub fn crossterm() {
|
||||
let crossterm = Crossterm::new();
|
||||
let mut term = crossterm.terminal();
|
||||
let mut cursor = crossterm.cursor();
|
||||
let input = crossterm.input();
|
||||
|
||||
// clear screen
|
||||
term.clear(ClearType::All);
|
||||
|
||||
let mut raw_screen = RawTerminal::new(&crossterm.context());
|
||||
raw_screen.enable();
|
||||
|
||||
let mut stdin = input.read_async().bytes();
|
||||
|
||||
let mut buf = String::new();
|
||||
|
||||
let mut counter: u16 = 1;
|
||||
|
||||
loop {
|
||||
cursor.goto(0, counter);
|
||||
term.write("test data");
|
||||
|
||||
let (term_width, term_height) = term.terminal_size();
|
||||
let (cursor_x, cursor_y) = cursor.pos();
|
||||
|
||||
if cursor_y >= term_height {
|
||||
term.scroll_up(1);
|
||||
}
|
||||
|
||||
cursor.goto(0, term_height);
|
||||
term.clear(ClearType::CurrentLine);
|
||||
term.write(format!("> {}", buf));
|
||||
|
||||
while let Some(b) = stdin.next() {
|
||||
if let Ok(b) = b {
|
||||
if b == 3 {
|
||||
term.exit();
|
||||
} else if b == 13 {
|
||||
buf.clear();
|
||||
} else {
|
||||
buf.push(b as char);
|
||||
}
|
||||
}
|
||||
}
|
||||
counter += 1;
|
||||
thread::sleep(time::Duration::from_millis(100));
|
||||
}
|
||||
}
|
||||
|
||||
use crossterm::cursor::cursor::TerminalCursor;
|
||||
use crossterm::terminal::terminal::Terminal;
|
||||
use crossterm::terminal::ClearType;
|
||||
use std::io::Read;
|
||||
|
||||
//pub fn swap_write(terminal: &mut Terminal, out: &mut RawTerminal, cursor: &mut TerminalCursor, msg: &str, input_buf: &String) {
|
||||
// let (term_width,term_height) = terminal.terminal_size();
|
||||
// let (x,y) = cursor.get_post();
|
||||
// cursor.goto(0,0);
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//}
|
||||
|
@ -5,23 +5,20 @@ use self::crossterm::Context;
|
||||
use self::crossterm::Crossterm;
|
||||
use crossterm::terminal::ClearType;
|
||||
|
||||
use std::{thread, time};
|
||||
use crossterm::raw::IntoRawMode;
|
||||
use std::{thread, time};
|
||||
|
||||
use std::io::{Read, Write, stdout};
|
||||
use std::io::{stdout, Read, Write};
|
||||
use std::time::Duration;
|
||||
|
||||
|
||||
/// this will capture the input until the given key.
|
||||
pub fn read_async_until()
|
||||
{
|
||||
pub fn read_async_until() {
|
||||
let context = Context::new();
|
||||
let input = input(&context);
|
||||
|
||||
let mut stdin = input.read_until_async(b'\r').bytes();
|
||||
|
||||
for i in 0..100
|
||||
{
|
||||
for i in 0..100 {
|
||||
let a = stdin.next();
|
||||
|
||||
println!("pressed key: {:?}", a);
|
||||
@ -41,15 +38,13 @@ pub fn read_async_until()
|
||||
}
|
||||
|
||||
/// this will read pressed characters async until `x` is typed .
|
||||
pub fn read_async()
|
||||
{
|
||||
pub fn read_async() {
|
||||
let context = Context::new();
|
||||
let input = input(&context);
|
||||
|
||||
let mut stdin = input.read_async().bytes();
|
||||
|
||||
for i in 0..100
|
||||
{
|
||||
for i in 0..100 {
|
||||
let a = stdin.next();
|
||||
|
||||
println!("pressed key: {:?}", a);
|
||||
@ -63,8 +58,7 @@ pub fn read_async()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_async_demo()
|
||||
{
|
||||
pub fn read_async_demo() {
|
||||
let crossterm = Crossterm::new();
|
||||
|
||||
// init some modules we use for this demo
|
||||
@ -82,7 +76,6 @@ pub fn read_async_demo()
|
||||
terminal.clear(ClearType::All);
|
||||
cursor.goto(1, 1);
|
||||
|
||||
|
||||
// loop until the enter key (\r) is pressed.
|
||||
loop {
|
||||
terminal.clear(ClearType::All);
|
||||
@ -103,8 +96,7 @@ pub fn read_async_demo()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn async_reading_on_alternate_screen()
|
||||
{
|
||||
pub fn async_reading_on_alternate_screen() {
|
||||
use crossterm::screen::AlternateScreen;
|
||||
|
||||
let crossterm = Crossterm::new();
|
||||
@ -126,7 +118,7 @@ pub fn async_reading_on_alternate_screen()
|
||||
terminal.clear(ClearType::All);
|
||||
cursor.goto(1, 1);
|
||||
|
||||
// panic!();
|
||||
// panic!();
|
||||
|
||||
// loop until the enter key (\r) is pressed.
|
||||
loop {
|
||||
@ -136,7 +128,11 @@ pub fn async_reading_on_alternate_screen()
|
||||
// get the next pressed key
|
||||
let pressed_key = stdin.next();
|
||||
|
||||
write!(alternate_screen, "\r{:?} <- Character pressed", pressed_key).unwrap();
|
||||
write!(
|
||||
alternate_screen,
|
||||
"\r{:?} <- Character pressed",
|
||||
pressed_key
|
||||
).unwrap();
|
||||
|
||||
// check if pressed key is enter (\r)
|
||||
if let Some(Ok(b'\r')) = pressed_key {
|
||||
@ -146,4 +142,4 @@ pub fn async_reading_on_alternate_screen()
|
||||
// wait 200 ms and reset cursor write
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,26 +3,22 @@ extern crate crossterm;
|
||||
use self::crossterm::input::input;
|
||||
use self::crossterm::Context;
|
||||
|
||||
pub fn read_char()
|
||||
{
|
||||
pub fn read_char() {
|
||||
let context = Context::new();
|
||||
let input = input(&context);
|
||||
|
||||
match input.read_char()
|
||||
{
|
||||
match input.read_char() {
|
||||
Ok(c) => println!("character pressed: {}", c),
|
||||
Err(e) => println!("error: {}", e)
|
||||
Err(e) => println!("error: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_line()
|
||||
{
|
||||
pub fn read_line() {
|
||||
let context = Context::new();
|
||||
let input = input(&context);
|
||||
|
||||
match input.read_line()
|
||||
{
|
||||
match input.read_line() {
|
||||
Ok(s) => println!("string typed: {}", s),
|
||||
Err(e) => println!("error: {}", e)
|
||||
Err(e) => println!("error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
pub mod async_input;
|
||||
pub mod input;
|
||||
pub mod input;
|
||||
|
@ -1 +1 @@
|
||||
pub mod keyboard;
|
||||
pub mod keyboard;
|
||||
|
@ -335,7 +335,7 @@ impl TerminalCursor {
|
||||
///
|
||||
/// ```
|
||||
pub fn blink(&self, blink: bool) {
|
||||
self.terminal_cursor.blink(blink);
|
||||
self.terminal_cursor.blink(blink);
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,4 +368,4 @@ impl TerminalCursor {
|
||||
/// ```
|
||||
pub fn cursor(context: &Rc<Context>) -> Box<TerminalCursor> {
|
||||
Box::from(TerminalCursor::new(context.clone()))
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,8 @@
|
||||
//! so that the cursor related actions can be preformed on both unix and windows systems.
|
||||
//!
|
||||
|
||||
pub mod cursor;
|
||||
mod ansi_cursor;
|
||||
pub mod cursor;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod winapi_cursor;
|
||||
|
||||
|
@ -22,7 +22,7 @@ impl WinApiCursor {
|
||||
|
||||
impl ITerminalCursor for WinApiCursor {
|
||||
fn goto(&self, x: u16, y: u16) {
|
||||
kernel::set_console_cursor_position(x as i16, y as i16, &self.screen_manager);
|
||||
cursor::set_console_cursor_position(x as i16, y as i16, &self.screen_manager);
|
||||
}
|
||||
|
||||
fn pos(&self) -> (u16, u16) {
|
||||
@ -58,11 +58,11 @@ impl ITerminalCursor for WinApiCursor {
|
||||
}
|
||||
|
||||
fn hide(&self) {
|
||||
kernel::cursor_visibility(false, &self.screen_manager);
|
||||
cursor::cursor_visibility(false, &self.screen_manager);
|
||||
}
|
||||
|
||||
fn show(&self) {
|
||||
kernel::cursor_visibility(true, &self.screen_manager);
|
||||
cursor::cursor_visibility(true, &self.screen_manager);
|
||||
}
|
||||
|
||||
fn blink(&self, blink: bool) {}
|
||||
|
@ -1,19 +1,16 @@
|
||||
use std::io;
|
||||
|
||||
use super::*;
|
||||
use Context;
|
||||
use std::rc::Rc;
|
||||
use Context;
|
||||
|
||||
pub struct TerminalInput
|
||||
{
|
||||
pub struct TerminalInput {
|
||||
context: Rc<Context>,
|
||||
terminal_input: Box<ITerminalInput>,
|
||||
}
|
||||
|
||||
impl TerminalInput
|
||||
{
|
||||
pub fn new(context: Rc<Context>) -> TerminalInput
|
||||
{
|
||||
impl TerminalInput {
|
||||
pub fn new(context: Rc<Context>) -> TerminalInput {
|
||||
#[cfg(target_os = "windows")]
|
||||
let input = Box::from(WindowsInput::new(context.clone()));
|
||||
|
||||
@ -26,32 +23,27 @@ impl TerminalInput
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_line(&self) -> io::Result<String>
|
||||
{
|
||||
pub fn read_line(&self) -> io::Result<String> {
|
||||
self.terminal_input.read_line()
|
||||
}
|
||||
|
||||
pub fn read_char(&self) -> io::Result<char>
|
||||
{
|
||||
return self.terminal_input.read_char()
|
||||
pub fn read_char(&self) -> io::Result<char> {
|
||||
return self.terminal_input.read_char();
|
||||
}
|
||||
|
||||
pub fn read_key(&self) -> io::Result<Key>
|
||||
{
|
||||
pub fn read_key(&self) -> io::Result<Key> {
|
||||
self.terminal_input.read_pressed_key()
|
||||
}
|
||||
|
||||
pub fn read_async(&self) -> AsyncReader
|
||||
{
|
||||
pub fn read_async(&self) -> AsyncReader {
|
||||
self.terminal_input.read_async()
|
||||
}
|
||||
|
||||
pub fn read_until_async(&self, delimiter: u8) -> AsyncReader
|
||||
{ self.terminal_input.read_until_async(delimiter)
|
||||
pub fn read_until_async(&self, delimiter: u8) -> AsyncReader {
|
||||
self.terminal_input.read_until_async(delimiter)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input(context: &Rc<Context>) -> Box<TerminalInput>
|
||||
{
|
||||
pub fn input(context: &Rc<Context>) -> Box<TerminalInput> {
|
||||
return Box::from(TerminalInput::new(context.clone()));
|
||||
}
|
||||
}
|
||||
|
@ -12,14 +12,12 @@ use self::unix_input::UnixInput;
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
mod unix_input;
|
||||
|
||||
|
||||
pub use self::input::{ input, TerminalInput };
|
||||
pub use self::input::{input, TerminalInput};
|
||||
|
||||
use std::io::Read;
|
||||
use std::sync::mpsc;
|
||||
|
||||
trait ITerminalInput
|
||||
{
|
||||
trait ITerminalInput {
|
||||
fn read_line(&self) -> io::Result<String>;
|
||||
|
||||
fn read_char(&self) -> io::Result<char>;
|
||||
@ -29,9 +27,8 @@ trait ITerminalInput
|
||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader;
|
||||
}
|
||||
|
||||
pub struct AsyncReader
|
||||
{
|
||||
recv: mpsc::Receiver<io::Result<u8>>
|
||||
pub struct AsyncReader {
|
||||
recv: mpsc::Receiver<io::Result<u8>>,
|
||||
}
|
||||
|
||||
impl Read for AsyncReader {
|
||||
@ -74,4 +71,4 @@ pub enum Key {
|
||||
Char(char),
|
||||
#[doc(hidden)]
|
||||
__More,
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,24 @@
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::char;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use std::io::Read;
|
||||
|
||||
use super::super::terminal::terminal;
|
||||
use super::super::kernel::unix_kernel::terminal::{get_tty, read_char};
|
||||
use super::{ Key, ITerminalInput, AsyncReader };
|
||||
use super::super::terminal::terminal;
|
||||
use super::{AsyncReader, ITerminalInput, Key};
|
||||
|
||||
pub struct UnixInput;
|
||||
|
||||
|
||||
impl UnixInput
|
||||
{
|
||||
pub fn new() -> UnixInput
|
||||
{
|
||||
impl UnixInput {
|
||||
pub fn new() -> UnixInput {
|
||||
UnixInput {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl ITerminalInput for UnixInput
|
||||
{
|
||||
fn read_line(&self) -> io::Result<String>
|
||||
{
|
||||
impl ITerminalInput for UnixInput {
|
||||
fn read_line(&self) -> io::Result<String> {
|
||||
let mut rv = String::new();
|
||||
io::stdin().read_line(&mut rv)?;
|
||||
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
||||
@ -32,47 +26,49 @@ impl ITerminalInput for UnixInput
|
||||
Ok(rv)
|
||||
}
|
||||
|
||||
fn read_char(&self) -> io::Result<char>
|
||||
{
|
||||
fn read_char(&self) -> io::Result<char> {
|
||||
read_char()
|
||||
}
|
||||
|
||||
fn read_pressed_key(&self) -> io::Result<Key>
|
||||
{
|
||||
fn read_pressed_key(&self) -> io::Result<Key> {
|
||||
Ok(Key::Unknown)
|
||||
}
|
||||
|
||||
fn read_async(&self) -> AsyncReader
|
||||
{
|
||||
fn read_async(&self) -> AsyncReader {
|
||||
let (send, recv) = mpsc::channel();
|
||||
|
||||
thread::spawn(move || for i in get_tty().unwrap().bytes() {
|
||||
if send.send(i).is_err() {
|
||||
return;
|
||||
thread::spawn(move || {
|
||||
for i in get_tty().unwrap().bytes() {
|
||||
if send.send(i).is_err() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AsyncReader { recv: recv }
|
||||
}
|
||||
|
||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader
|
||||
{
|
||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader {
|
||||
let (send, recv) = mpsc::channel();
|
||||
|
||||
thread::spawn(move || for i in get_tty().unwrap().bytes() {
|
||||
thread::spawn(move || {
|
||||
for i in get_tty().unwrap().bytes() {
|
||||
match i {
|
||||
Ok(byte) => {
|
||||
let end_of_stream = &byte == &delimiter;
|
||||
let send_error = send.send(Ok(byte)).is_err();
|
||||
|
||||
match i {
|
||||
Ok(byte) => {
|
||||
let end_of_stream = &byte == &delimiter;
|
||||
let send_error = send.send(Ok(byte)).is_err();
|
||||
|
||||
if end_of_stream || send_error { return; }
|
||||
},
|
||||
Err(_) => { return; }
|
||||
if end_of_stream || send_error {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AsyncReader { recv: recv }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,37 +1,34 @@
|
||||
use std::char;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::char;
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
|
||||
use super::{ Key, ITerminalInput, AsyncReader };
|
||||
use super::{AsyncReader, ITerminalInput, Key};
|
||||
|
||||
use winapi::um::winnt::{ INT };
|
||||
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;
|
||||
use Context;
|
||||
|
||||
pub struct WindowsInput
|
||||
{
|
||||
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 WindowsInput {
|
||||
pub fn new(context: Rc<Context>) -> WindowsInput {
|
||||
WindowsInput {
|
||||
context,
|
||||
display_input: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ITerminalInput for WindowsInput
|
||||
{
|
||||
fn read_line(&self) -> io::Result<String>
|
||||
{
|
||||
impl ITerminalInput for WindowsInput {
|
||||
fn read_line(&self) -> io::Result<String> {
|
||||
let term = terminal(&self.context);
|
||||
let mut chars: Vec<char> = Vec::new();
|
||||
|
||||
@ -40,19 +37,19 @@ impl ITerminalInput for WindowsInput
|
||||
|
||||
// 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)
|
||||
{
|
||||
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);
|
||||
if is_line_end(c) {
|
||||
break;
|
||||
} else {
|
||||
chars.push(c);
|
||||
}
|
||||
|
||||
},
|
||||
None => { panic!("Some error needs to be returned") }
|
||||
if self.display_input {
|
||||
term.write(c);
|
||||
}
|
||||
}
|
||||
None => panic!("Some error needs to be returned"),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -60,88 +57,85 @@ impl ITerminalInput for WindowsInput
|
||||
return Ok(chars.into_iter().collect());
|
||||
}
|
||||
|
||||
fn read_char(&self) -> io::Result<char>
|
||||
{
|
||||
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"));
|
||||
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)
|
||||
{
|
||||
match char::from_u32(pressed_char as u32) {
|
||||
Some(c) => {
|
||||
if self.display_input
|
||||
{
|
||||
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"))
|
||||
None => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not parse given input to char",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn read_pressed_key(&self) -> io::Result<Key>
|
||||
{
|
||||
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);
|
||||
// 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") }
|
||||
// }
|
||||
// }
|
||||
// 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
|
||||
{
|
||||
fn read_async(&self) -> AsyncReader {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
thread::spawn(move || {
|
||||
loop
|
||||
{
|
||||
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
|
||||
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;
|
||||
}
|
||||
// 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
|
||||
{
|
||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
thread::spawn(move || {
|
||||
loop
|
||||
{
|
||||
loop {
|
||||
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
|
||||
|
||||
let end_of_stream = (pressed_char == delimiter);
|
||||
@ -159,17 +153,14 @@ impl ITerminalInput for WindowsInput
|
||||
}
|
||||
}
|
||||
|
||||
fn is_line_end(key: char) -> bool
|
||||
{
|
||||
if key as u8 == 13
|
||||
{
|
||||
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
|
||||
@ -193,23 +184,21 @@ fn is_line_end(key: char) -> bool
|
||||
//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,
|
||||
// 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,
|
||||
@ -225,4 +214,4 @@ fn key_from_key_code(code: INT) -> Key {
|
||||
extern "C" {
|
||||
fn _getwch() -> INT;
|
||||
fn _getwch_nolock() -> INT;
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,11 @@ use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ};
|
||||
use state::commands::{IStateCommand, NoncanonicalModeCommand};
|
||||
use {libc, CommandManager, Context, StateManager};
|
||||
|
||||
use termios::{ Termios,cfmakeraw,tcsetattr,TCSADRAIN };
|
||||
use std::io::Error;
|
||||
use std::rc::Rc;
|
||||
use std::{io, mem, fs};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::rc::Rc;
|
||||
use std::{fs, io, mem};
|
||||
use termios::{cfmakeraw, tcsetattr, Termios, TCSADRAIN};
|
||||
|
||||
/// A representation of the size of the current terminal.
|
||||
#[repr(C)]
|
||||
@ -138,28 +138,26 @@ pub fn get_terminal_mode() -> io::Result<Termios> {
|
||||
///
|
||||
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
|
||||
pub fn get_tty() -> io::Result<fs::File> {
|
||||
fs::OpenOptions::new().read(true).write(true).open("/dev/tty")
|
||||
fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open("/dev/tty")
|
||||
}
|
||||
|
||||
|
||||
pub fn read_char() -> io::Result<char>
|
||||
{
|
||||
pub fn read_char() -> io::Result<char> {
|
||||
let mut buf = [0u8; 20];
|
||||
|
||||
// get tty raw handle.
|
||||
let tty_f;
|
||||
|
||||
let fd = unsafe
|
||||
{
|
||||
if libc::isatty(libc::STDIN_FILENO) == 1
|
||||
{
|
||||
libc::STDIN_FILENO
|
||||
} else {
|
||||
tty_f = fs::File::open("/dev/tty")?;
|
||||
tty_f.as_raw_fd()
|
||||
}
|
||||
};
|
||||
|
||||
let fd = unsafe {
|
||||
if libc::isatty(libc::STDIN_FILENO) == 1 {
|
||||
libc::STDIN_FILENO
|
||||
} else {
|
||||
tty_f = fs::File::open("/dev/tty")?;
|
||||
tty_f.as_raw_fd()
|
||||
}
|
||||
};
|
||||
|
||||
let mut termios = Termios::from_fd(fd)?;
|
||||
let original = termios.clone();
|
||||
@ -174,31 +172,36 @@ pub fn read_char() -> io::Result<char>
|
||||
if read < 0 {
|
||||
Err(io::Error::last_os_error())
|
||||
} else if buf[0] == b'\x03' {
|
||||
Err(io::Error::new(io::ErrorKind::Interrupted, "read interrupted"))
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Interrupted,
|
||||
"read interrupted",
|
||||
))
|
||||
} else {
|
||||
let mut pressed_char = Ok(' ');
|
||||
|
||||
if let Ok(s) = ::std::str::from_utf8(&buf[..read as usize])
|
||||
{
|
||||
if let Some(c) = s.chars().next()
|
||||
{
|
||||
pressed_char = Ok(c);
|
||||
}
|
||||
}else {
|
||||
pressed_char = Err(io::Error::new(io::ErrorKind::Interrupted, "Could not parse char to utf8 char"));
|
||||
if let Ok(s) = ::std::str::from_utf8(&buf[..read as usize]) {
|
||||
if let Some(c) = s.chars().next() {
|
||||
pressed_char = Ok(c);
|
||||
}
|
||||
} else {
|
||||
pressed_char = Err(io::Error::new(
|
||||
io::ErrorKind::Interrupted,
|
||||
"Could not parse char to utf8 char",
|
||||
));
|
||||
}
|
||||
|
||||
pressed_char
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
tcsetattr(fd, TCSADRAIN, &original)?;
|
||||
|
||||
// if the user hit ^C we want to signal SIGINT to outselves.
|
||||
if let Err(ref err) = rv {
|
||||
if err.kind() == io::ErrorKind::Interrupted {
|
||||
unsafe { libc::raise(libc::SIGINT); }
|
||||
unsafe {
|
||||
libc::raise(libc::SIGINT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,14 +3,14 @@
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use IStateCommand;
|
||||
|
||||
static mut HAS_BEEN_TRYED_TO_ENABLE: bool = false;
|
||||
static mut HAS_BEEN_TRIED_TO_ENABLE: bool = false;
|
||||
static mut IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
|
||||
static mut DOES_WINDOWS_SUPPORT_ANSI: Option<bool> = None;
|
||||
static START: Once = ONCE_INIT;
|
||||
static ENABLE_ANSI: Once = ONCE_INIT;
|
||||
|
||||
/// Try enable `ANSI escape codes` and return the result.
|
||||
pub fn try_enable_ansi_support() -> bool {
|
||||
START.call_once(|| {
|
||||
ENABLE_ANSI.call_once(|| {
|
||||
use state::commands::win_commands::EnableAnsiCommand;
|
||||
let mut command = EnableAnsiCommand::new();
|
||||
let success = command.execute();
|
||||
@ -35,7 +35,7 @@ pub fn windows_supportable() -> bool {
|
||||
/// Get whether ansi has been tried to enable before.
|
||||
pub fn has_been_tried_to_enable_ansi() -> bool {
|
||||
unsafe {
|
||||
return HAS_BEEN_TRYED_TO_ENABLE;
|
||||
return HAS_BEEN_TRIED_TO_ENABLE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,6 +56,6 @@ fn set_is_windows_ansi_supportable(is_enabled: bool) {
|
||||
/// Set the has_been_tried_to_enable property. So we can determine whether ansi has been tried to enable before.
|
||||
fn has_been_tried_to_enable(has_been_tried: bool) {
|
||||
unsafe {
|
||||
HAS_BEEN_TRYED_TO_ENABLE = has_been_tried;
|
||||
HAS_BEEN_TRIED_TO_ENABLE = has_been_tried;
|
||||
}
|
||||
}
|
||||
|
111
src/kernel/windows_kernel/csbi.rs
Normal file
111
src/kernel/windows_kernel/csbi.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use winapi::shared::minwindef::{FALSE, TRUE};
|
||||
use winapi::shared::ntdef::NULL;
|
||||
use winapi::um::minwinbase::SECURITY_ATTRIBUTES;
|
||||
use winapi::um::wincon::{
|
||||
CreateConsoleScreenBuffer, GetConsoleScreenBufferInfo, SetConsoleActiveScreenBuffer,
|
||||
SetConsoleScreenBufferSize, CONSOLE_SCREEN_BUFFER_INFO, CONSOLE_TEXTMODE_BUFFER, COORD,
|
||||
};
|
||||
use winapi::um::winnt::HANDLE;
|
||||
use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
|
||||
|
||||
use super::{handle, kernel, Empty};
|
||||
use std::io::{self, ErrorKind, Result};
|
||||
use std::mem::size_of;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
use ScreenManager;
|
||||
|
||||
/// Create a new console screen buffer info struct.
|
||||
pub fn get_csbi(screen_manager: &Rc<Mutex<ScreenManager>>) -> Result<CONSOLE_SCREEN_BUFFER_INFO> {
|
||||
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
|
||||
let success;
|
||||
|
||||
unsafe {
|
||||
success = GetConsoleScreenBufferInfo(handle::get_current_handle(screen_manager)?, &mut csbi)
|
||||
}
|
||||
|
||||
if success == 0 {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not get console screen buffer info",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(csbi)
|
||||
}
|
||||
|
||||
/// Get buffer info and handle of the current screen.
|
||||
pub fn get_csbi_and_handle(
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
) -> Result<(CONSOLE_SCREEN_BUFFER_INFO, HANDLE)> {
|
||||
let handle = handle::get_current_handle(screen_manager)?;
|
||||
let csbi = get_csbi_by_handle(&handle)?;
|
||||
|
||||
return Ok((csbi, handle));
|
||||
}
|
||||
|
||||
/// Create a new console screen buffer info struct.
|
||||
pub fn get_csbi_by_handle(handle: &HANDLE) -> Result<CONSOLE_SCREEN_BUFFER_INFO> {
|
||||
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
|
||||
|
||||
unsafe {
|
||||
if !kernel::is_true(GetConsoleScreenBufferInfo(*handle, &mut csbi)) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not get console screen buffer info",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(csbi)
|
||||
}
|
||||
|
||||
/// Set the console screen buffer size
|
||||
pub fn set_console_screen_buffer_size(
|
||||
size: COORD,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
) -> bool {
|
||||
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||
|
||||
unsafe {
|
||||
if !kernel::is_true(SetConsoleScreenBufferSize(handle, size)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create new console screen buffer. This can be used for alternate screen.
|
||||
pub fn create_console_screen_buffer() -> HANDLE {
|
||||
let mut security_attr: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES {
|
||||
nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
|
||||
lpSecurityDescriptor: NULL,
|
||||
bInheritHandle: TRUE,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
let new_screen_buffer = CreateConsoleScreenBuffer(
|
||||
GENERIC_READ | // read/write access
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, // shared
|
||||
&mut security_attr, // default security attributes
|
||||
CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
|
||||
NULL,
|
||||
);
|
||||
new_screen_buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the active screen buffer to the given handle. This can be used for alternate screen.
|
||||
pub fn set_active_screen_buffer(new_buffer: HANDLE) -> Result<()> {
|
||||
unsafe {
|
||||
if !kernel::is_true(SetConsoleActiveScreenBuffer(new_buffer)) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not set the active screen buffer",
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
@ -1,8 +1,14 @@
|
||||
//! This module handles some logic for cursor interaction in the windows console.
|
||||
|
||||
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
|
||||
use super::kernel;
|
||||
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;
|
||||
|
||||
@ -12,7 +18,7 @@ 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 {
|
||||
kernel::set_console_cursor_position(
|
||||
set_console_cursor_position(
|
||||
SAVED_CURSOR_POS.0 as i16,
|
||||
SAVED_CURSOR_POS.1 as i16,
|
||||
screen_manager,
|
||||
@ -31,9 +37,61 @@ pub fn save_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||
|
||||
/// get the current cursor position.
|
||||
pub fn pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
|
||||
let csbi = kernel::get_console_screen_buffer_info(screen_manager);
|
||||
(
|
||||
csbi.dwCursorPosition.X as u16,
|
||||
csbi.dwCursorPosition.Y as 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(())
|
||||
}
|
||||
|
72
src/kernel/windows_kernel/handle.rs
Normal file
72
src/kernel/windows_kernel/handle.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||
use winapi::um::processenv::GetStdHandle;
|
||||
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
use std::io::{self, ErrorKind, Result};
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
|
||||
|
||||
/// Get the global stored handle whits provides access to the current screen.
|
||||
pub fn get_current_handle(screen_manager: &Rc<Mutex<ScreenManager>>) -> Result<HANDLE> {
|
||||
let mut mutex = screen_manager;
|
||||
|
||||
let handle: Result<HANDLE>;
|
||||
|
||||
let mut screen_manager = mutex.lock().unwrap();
|
||||
{
|
||||
let winapi_screen_manager: &mut WinApiScreenManager = match screen_manager
|
||||
.as_any()
|
||||
.downcast_mut::<WinApiScreenManager>()
|
||||
{
|
||||
Some(win_api) => win_api,
|
||||
None => return Err(io::Error::new(io::ErrorKind::Other,"Could not convert to winapi screen manager, this could happen when the user has an ANSI screen manager and is calling the platform specific operations 'get_cursor_pos' or 'get_terminal_size'"))
|
||||
};
|
||||
|
||||
handle = Ok(*winapi_screen_manager.get_handle());
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// Get the std_output_handle of the console
|
||||
pub fn get_output_handle() -> Result<HANDLE> {
|
||||
unsafe {
|
||||
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
if !is_valid_handle(&handle) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not get output handle!",
|
||||
));
|
||||
}
|
||||
Ok(handle)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the std_input_handle of the console
|
||||
pub fn get_input_handle() -> Result<HANDLE> {
|
||||
unsafe {
|
||||
let handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
||||
if !is_valid_handle(&handle) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not get input handle",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(handle)
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the console handle is an invalid handle value.
|
||||
fn is_valid_handle(handle: &HANDLE) -> bool {
|
||||
if *handle == INVALID_HANDLE_VALUE {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
@ -8,9 +8,7 @@ use winapi::shared::minwindef::{FALSE, TRUE};
|
||||
use winapi::shared::ntdef::NULL;
|
||||
use winapi::um::consoleapi::WriteConsoleW;
|
||||
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
|
||||
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
|
||||
use winapi::um::processenv::GetStdHandle;
|
||||
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
|
||||
|
||||
use winapi::um::wincon;
|
||||
use winapi::um::wincon::{
|
||||
CreateConsoleScreenBuffer, FillConsoleOutputAttribute, FillConsoleOutputCharacterA,
|
||||
@ -23,206 +21,39 @@ use winapi::um::wincon::{
|
||||
};
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
use super::Empty;
|
||||
static mut CONSOLE_OUTPUT_HANDLE: Option<HANDLE> = None;
|
||||
static mut CONSOLE_INPUT_HANDLE: Option<HANDLE> = None;
|
||||
use super::{handle, Empty};
|
||||
|
||||
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
|
||||
use std::io::{ErrorKind, Result};
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// Get the global stored handle.
|
||||
pub fn get_current_handle(screen_manager: &Rc<Mutex<ScreenManager>>) -> HANDLE {
|
||||
let mut mx_guard = screen_manager;
|
||||
|
||||
let handle: HANDLE;
|
||||
|
||||
let mut screen_manager = mx_guard.lock().unwrap();
|
||||
{
|
||||
let winapi_screen_manager: &mut WinApiScreenManager = match screen_manager
|
||||
.as_any()
|
||||
.downcast_mut::<WinApiScreenManager>()
|
||||
{
|
||||
Some(win_api) => win_api,
|
||||
None => panic!(""),
|
||||
};
|
||||
|
||||
handle = *winapi_screen_manager.get_handle();
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
/// Get the std_output_handle of the console
|
||||
pub fn get_output_handle() -> HANDLE {
|
||||
unsafe {
|
||||
if let Some(handle) = CONSOLE_OUTPUT_HANDLE {
|
||||
handle
|
||||
} else {
|
||||
let handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
if !is_valid_handle(&handle) {
|
||||
panic!("Cannot get output handle")
|
||||
}
|
||||
|
||||
CONSOLE_OUTPUT_HANDLE = Some(handle);
|
||||
handle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the std_input_handle of the console
|
||||
pub fn get_input_handle() -> HANDLE {
|
||||
unsafe {
|
||||
if let Some(handle) = CONSOLE_INPUT_HANDLE {
|
||||
handle
|
||||
} else {
|
||||
let handle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
||||
if !is_valid_handle(&handle) {
|
||||
panic!("Cannot get input handle")
|
||||
}
|
||||
|
||||
CONSOLE_INPUT_HANDLE = Some(handle);
|
||||
handle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the console handle is an invalid handle value.
|
||||
fn is_valid_handle(handle: &HANDLE) -> bool {
|
||||
if *handle == INVALID_HANDLE_VALUE {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
/// Create a new console screen buffer info struct.
|
||||
pub fn get_console_screen_buffer_info(
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
) -> CONSOLE_SCREEN_BUFFER_INFO {
|
||||
|
||||
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
|
||||
let success;
|
||||
|
||||
unsafe { success = GetConsoleScreenBufferInfo(get_current_handle(screen_manager), &mut csbi) }
|
||||
|
||||
if success == 0 {
|
||||
panic!("Cannot get console screen buffer info");
|
||||
}
|
||||
|
||||
csbi
|
||||
}
|
||||
|
||||
/// Create a new console screen buffer info struct.
|
||||
pub fn get_std_console_screen_buffer_info() -> CONSOLE_SCREEN_BUFFER_INFO {
|
||||
|
||||
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
|
||||
let success;
|
||||
|
||||
unsafe { success = GetConsoleScreenBufferInfo(get_output_handle(), &mut csbi) }
|
||||
|
||||
if success == 0 {
|
||||
panic!("Cannot get console screen buffer info");
|
||||
}
|
||||
|
||||
csbi
|
||||
}
|
||||
|
||||
/// Get buffer info and handle of the current screen.
|
||||
pub fn get_buffer_info_and_hande(screen_manager: &Rc<Mutex<ScreenManager>>) -> (CONSOLE_SCREEN_BUFFER_INFO, HANDLE)
|
||||
{
|
||||
let handle = get_current_handle(screen_manager);
|
||||
let csbi = get_console_screen_buffer_info_from_handle(&handle);
|
||||
|
||||
return (csbi, handle)
|
||||
}
|
||||
|
||||
/// Create a new console screen buffer info struct.
|
||||
pub fn get_console_screen_buffer_info_from_handle(handle: &HANDLE) -> CONSOLE_SCREEN_BUFFER_INFO {
|
||||
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
|
||||
let success;
|
||||
|
||||
unsafe { success = GetConsoleScreenBufferInfo(*handle, &mut csbi) }
|
||||
|
||||
if success == 0 {
|
||||
panic!("Cannot get console screen buffer info");
|
||||
}
|
||||
|
||||
csbi
|
||||
}
|
||||
|
||||
/// Get the largest console window size possible.
|
||||
pub fn get_largest_console_window_size() -> COORD {
|
||||
let output_handle = get_output_handle();
|
||||
let output_handle = handle::get_output_handle().unwrap();
|
||||
|
||||
unsafe { GetLargestConsoleWindowSize(output_handle) }
|
||||
}
|
||||
|
||||
/// Get the original color of the terminal.
|
||||
pub fn get_original_console_color(screen_manager: &Rc<Mutex<ScreenManager>>) -> u16 {
|
||||
let console_buffer_info = get_console_screen_buffer_info(screen_manager);
|
||||
console_buffer_info.wAttributes as u16
|
||||
}
|
||||
|
||||
/// Set the console mode to the given console mode.
|
||||
pub fn set_console_mode(handle: &HANDLE, console_mode: u32) -> bool {
|
||||
unsafe {
|
||||
let success = SetConsoleMode(*handle, console_mode);
|
||||
return is_true(success);
|
||||
return is_true(SetConsoleMode(*handle, console_mode));
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the console mode.
|
||||
pub fn get_console_mode(handle: &HANDLE, current_mode: &mut u32) -> bool {
|
||||
unsafe {
|
||||
let success = GetConsoleMode(*handle, &mut *current_mode);
|
||||
return is_true(success);
|
||||
}
|
||||
}
|
||||
|
||||
/// 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!("X: {}, Argument Out of Range Exception", x);
|
||||
}
|
||||
|
||||
if y < 0 || y >= <i16>::max_value() {
|
||||
panic!("Y: {}, Argument Out of Range Exception", y);
|
||||
}
|
||||
|
||||
let handle = get_current_handle(screen_manager);
|
||||
|
||||
let position = COORD { X: x, Y: y };
|
||||
|
||||
unsafe {
|
||||
let success = SetConsoleCursorPosition(handle, position);
|
||||
|
||||
if success == 0 {
|
||||
panic!("Argument out of range.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// change the cursor visibility.
|
||||
pub fn cursor_visibility(visable: bool, screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||
let handle = get_current_handle(screen_manager);
|
||||
|
||||
let cursor_info = CONSOLE_CURSOR_INFO {
|
||||
dwSize: 100,
|
||||
bVisible: if visable { TRUE } else { FALSE },
|
||||
};
|
||||
|
||||
unsafe {
|
||||
SetConsoleCursorInfo(handle, &cursor_info);
|
||||
return is_true(GetConsoleMode(*handle, &mut *current_mode));
|
||||
}
|
||||
}
|
||||
|
||||
/// Change the console text attribute.
|
||||
pub fn set_console_text_attribute(value: u16, screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||
let handle = get_current_handle(screen_manager);
|
||||
pub fn set_console_text_attribute(value: u16, screen_manager: &Rc<Mutex<ScreenManager>>) -> bool {
|
||||
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||
|
||||
unsafe {
|
||||
SetConsoleTextAttribute(handle, value);
|
||||
return is_true(SetConsoleTextAttribute(handle, value));
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,71 +63,17 @@ pub fn set_console_info(
|
||||
rect: &SMALL_RECT,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
) -> bool {
|
||||
let handle = get_current_handle(screen_manager);
|
||||
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||
|
||||
let absolute = match absolute {
|
||||
true => 1,
|
||||
false => 0,
|
||||
};
|
||||
unsafe {
|
||||
let success = SetConsoleWindowInfo(handle, absolute, rect);
|
||||
is_true(success)
|
||||
return is_true(SetConsoleWindowInfo(handle, absolute, rect));
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the console screen buffer size
|
||||
pub fn set_console_screen_buffer_size(
|
||||
size: COORD,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
) -> bool {
|
||||
|
||||
let handle = get_current_handle(screen_manager);
|
||||
|
||||
unsafe {
|
||||
let success = SetConsoleScreenBufferSize(handle, size);
|
||||
is_true(success)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Create new console screen buffer. This can be used for alternate screen.
|
||||
pub fn create_console_screen_buffer() -> HANDLE {
|
||||
use std::mem::size_of;
|
||||
use winapi::shared::ntdef::NULL;
|
||||
use winapi::um::minwinbase::SECURITY_ATTRIBUTES;
|
||||
use winapi::um::wincon::CONSOLE_TEXTMODE_BUFFER;
|
||||
use winapi::um::winnt::{FILE_SHARE_READ, FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE};
|
||||
|
||||
unsafe {
|
||||
let mut security_attr: SECURITY_ATTRIBUTES = SECURITY_ATTRIBUTES {
|
||||
nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
|
||||
lpSecurityDescriptor: NULL,
|
||||
bInheritHandle: TRUE,
|
||||
};
|
||||
|
||||
let new_screen_buffer = CreateConsoleScreenBuffer(
|
||||
GENERIC_READ | // read/write access
|
||||
GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, // shared
|
||||
&mut security_attr, // default security attributes
|
||||
CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
|
||||
NULL,
|
||||
);
|
||||
new_screen_buffer
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the active screen buffer to the given handle. This can be used for alternate screen.
|
||||
pub fn set_active_screen_buffer(new_buffer: HANDLE) {
|
||||
unsafe {
|
||||
if !is_true(SetConsoleActiveScreenBuffer(new_buffer)) {
|
||||
panic!("Cannot set active screen buffer");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Parse integer to an bool
|
||||
pub fn is_true(value: i32) -> bool {
|
||||
if value == 0 {
|
||||
@ -305,3 +82,9 @@ pub fn is_true(value: i32) -> bool {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
///// Get the original color of the terminal.
|
||||
//pub fn get_original_console_color(screen_manager: &Rc<Mutex<ScreenManager>>) -> u16 {
|
||||
// let console_buffer_info = csbi::get_console_screen_buffer_info(screen_manager);
|
||||
// console_buffer_info.wAttributes as u16
|
||||
//}
|
||||
|
@ -5,7 +5,9 @@ pub mod cursor;
|
||||
pub mod kernel;
|
||||
pub mod terminal;
|
||||
pub mod writing;
|
||||
pub mod reading;
|
||||
//pub mod reading;
|
||||
pub mod csbi;
|
||||
pub mod handle;
|
||||
|
||||
use self::winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
|
||||
use shared::traits::Empty;
|
||||
|
@ -1,84 +1,84 @@
|
||||
use { Context, ScreenManager };
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use winapi::um::consoleapi::ReadConsoleW;
|
||||
use winapi::um::winnt::HANDLE;
|
||||
use winapi::um::wincon::{ COORD, PSMALL_RECT, ReadConsoleOutputA, CHAR_INFO, };
|
||||
use winapi::shared::minwindef::{ DWORD, LPDWORD, LPVOID };
|
||||
use winapi::shared::ntdef::NULL;
|
||||
|
||||
use super::kernel;
|
||||
use winapi::ctypes::c_void;
|
||||
|
||||
pub fn read(buf: &mut [u8], screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||
// // Read more if the buffer is empty
|
||||
// let mut utf16: Vec<u16> = Vec::new();
|
||||
// let mut num: DWORD = 0;
|
||||
//use { Context, ScreenManager };
|
||||
//use std::rc::Rc;
|
||||
//use std::sync::Mutex;
|
||||
//
|
||||
//use winapi::um::consoleapi::ReadConsoleW;
|
||||
//use winapi::um::winnt::HANDLE;
|
||||
//use winapi::um::wincon::{ COORD, PSMALL_RECT, ReadConsoleOutputA, CHAR_INFO, };
|
||||
//use winapi::shared::minwindef::{ DWORD, LPDWORD, LPVOID };
|
||||
//use winapi::shared::ntdef::NULL;
|
||||
//
|
||||
//use super::kernel;
|
||||
//use winapi::ctypes::c_void;
|
||||
//
|
||||
//pub fn read(buf: &mut [u8], screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||
//// // Read more if the buffer is empty
|
||||
//// let mut utf16: Vec<u16> = Vec::new();
|
||||
//// let mut num: DWORD = 0;
|
||||
////
|
||||
//// let handle = kernel::get_current_handle(&screen_manager);
|
||||
////
|
||||
//// unsafe {
|
||||
//// ReadConsoleW(handle,
|
||||
//// utf16.as_mut_ptr() as LPVOID,
|
||||
//// utf16.len() as u32,
|
||||
//// &mut num as LPDWORD,
|
||||
//// ptr::mut_null())
|
||||
//// };
|
||||
////
|
||||
//// utf16.truncate(num as uint);
|
||||
//// let utf8 = match from_utf16(utf16.as_slice()) {
|
||||
//// Some(utf8) => utf8.into_bytes(),
|
||||
//// None => {}
|
||||
//// };
|
||||
////
|
||||
//// panic!(utf8);
|
||||
//
|
||||
//}
|
||||
//
|
||||
//pub fn read_line(screen_manager: &Rc<Mutex<ScreenManager>>) -> ::std::io::Result<String>
|
||||
//{
|
||||
// const BUFFER_LENGHT: u32 = 1024;
|
||||
// let mut buffer: &mut [CHAR_INFO; BUFFER_LENGHT as usize] = unsafe {::std::mem::zeroed() };
|
||||
//
|
||||
// let handle = kernel::get_current_handle(&screen_manager);
|
||||
//
|
||||
// let mut dw_mode: DWORD = 0;
|
||||
// let console_mode = kernel::get_console_mode(&handle, &mut dw_mode);
|
||||
//
|
||||
// let ptr = buffer.as_ptr() as *const _ as *mut c_void;
|
||||
// let mut chars_read: u32 = 0;
|
||||
//
|
||||
// panic!();
|
||||
// unsafe
|
||||
// {
|
||||
// ReadConsoleW(handle, ptr, BUFFER_LENGHT , &mut chars_read, unsafe {::std::mem::zeroed() });
|
||||
// }
|
||||
//
|
||||
// Ok(String::new())
|
||||
//}
|
||||
//
|
||||
///// Read the console outptut.
|
||||
//pub fn read_console_output(
|
||||
// read_buffer: &HANDLE,
|
||||
// copy_buffer: &mut [CHAR_INFO; 160],
|
||||
// buffer_size: COORD,
|
||||
// buffer_coord: COORD,
|
||||
// source_buffer: PSMALL_RECT,
|
||||
//) {
|
||||
//
|
||||
//
|
||||
// unsafe {
|
||||
// ReadConsoleW(handle,
|
||||
// utf16.as_mut_ptr() as LPVOID,
|
||||
// utf16.len() as u32,
|
||||
// &mut num as LPDWORD,
|
||||
// ptr::mut_null())
|
||||
// };
|
||||
//
|
||||
// utf16.truncate(num as uint);
|
||||
// let utf8 = match from_utf16(utf16.as_slice()) {
|
||||
// Some(utf8) => utf8.into_bytes(),
|
||||
// None => {}
|
||||
// };
|
||||
//
|
||||
// panic!(utf8);
|
||||
|
||||
}
|
||||
|
||||
pub fn read_line(screen_manager: &Rc<Mutex<ScreenManager>>) -> ::std::io::Result<String>
|
||||
{
|
||||
const BUFFER_LENGHT: u32 = 1024;
|
||||
let mut buffer: &mut [CHAR_INFO; BUFFER_LENGHT as usize] = unsafe {::std::mem::zeroed() };
|
||||
|
||||
let handle = kernel::get_current_handle(&screen_manager);
|
||||
|
||||
let mut dw_mode: DWORD = 0;
|
||||
let console_mode = kernel::get_console_mode(&handle, &mut dw_mode);
|
||||
|
||||
let ptr = buffer.as_ptr() as *const _ as *mut c_void;
|
||||
let mut chars_read: u32 = 0;
|
||||
|
||||
panic!();
|
||||
unsafe
|
||||
{
|
||||
ReadConsoleW(handle, ptr, BUFFER_LENGHT , &mut chars_read, unsafe {::std::mem::zeroed() });
|
||||
}
|
||||
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
/// Read the console outptut.
|
||||
pub fn read_console_output(
|
||||
read_buffer: &HANDLE,
|
||||
copy_buffer: &mut [CHAR_INFO; 160],
|
||||
buffer_size: COORD,
|
||||
buffer_coord: COORD,
|
||||
source_buffer: PSMALL_RECT,
|
||||
) {
|
||||
|
||||
|
||||
unsafe {
|
||||
if !kernel::is_true(
|
||||
ReadConsoleOutputA(
|
||||
*read_buffer, // screen buffer to read from
|
||||
copy_buffer.as_mut_ptr(), // buffer to copy into
|
||||
buffer_size, // col-row size of chiBuffer
|
||||
buffer_coord, // top left dest. cell in chiBuffer
|
||||
source_buffer,
|
||||
), // screen buffer source rectangle
|
||||
) {
|
||||
panic!("Cannot read console output");
|
||||
}
|
||||
}
|
||||
}
|
||||
// if !kernel::is_true(
|
||||
// ReadConsoleOutputA(
|
||||
// *read_buffer, // screen buffer to read from
|
||||
// copy_buffer.as_mut_ptr(), // buffer to copy into
|
||||
// buffer_size, // col-row size of chiBuffer
|
||||
// buffer_coord, // top left dest. cell in chiBuffer
|
||||
// source_buffer,
|
||||
// ), // screen buffer source rectangle
|
||||
// ) {
|
||||
// panic!("Cannot read console output");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -2,13 +2,18 @@ use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
use ScreenManager;
|
||||
|
||||
use super::csbi;
|
||||
|
||||
/// Get the terminal size
|
||||
pub fn terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
|
||||
let csbi = super::kernel::get_console_screen_buffer_info(screen_manager);
|
||||
(
|
||||
(csbi.srWindow.Right - csbi.srWindow.Left) as u16,
|
||||
(csbi.srWindow.Bottom - csbi.srWindow.Top) as u16,
|
||||
)
|
||||
if let Ok(csbi) = csbi::get_csbi(screen_manager) {
|
||||
(
|
||||
(csbi.srWindow.Right - csbi.srWindow.Left) as u16,
|
||||
(csbi.srWindow.Bottom - csbi.srWindow.Top) as u16,
|
||||
)
|
||||
} else {
|
||||
return (0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Exit the current process.
|
||||
|
@ -1,14 +1,19 @@
|
||||
use { Context, ScreenManager };
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use winapi::um::wincon;
|
||||
use winapi::um::winnt::HANDLE;
|
||||
use winapi::um::consoleapi::WriteConsoleW;
|
||||
use winapi::um::wincon::{WriteConsoleOutputA, PSMALL_RECT, FillConsoleOutputAttribute, FillConsoleOutputCharacterA, COORD, CHAR_INFO};
|
||||
use winapi::ctypes::c_void;
|
||||
use winapi::shared::ntdef::NULL;
|
||||
use winapi::um::consoleapi::WriteConsoleW;
|
||||
use winapi::um::wincon::{
|
||||
self, FillConsoleOutputAttribute, FillConsoleOutputCharacterA, WriteConsoleOutputA, CHAR_INFO,
|
||||
COORD, PSMALL_RECT,
|
||||
};
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
use super::kernel;
|
||||
use super::{csbi, handle, kernel};
|
||||
use {Context, ScreenManager};
|
||||
|
||||
use std::io::{self, ErrorKind, Result};
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// Fill a certain block with characters.
|
||||
pub fn fill_console_output_character(
|
||||
@ -17,8 +22,7 @@ pub fn fill_console_output_character(
|
||||
cells_to_write: u32,
|
||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||
) -> bool {
|
||||
|
||||
let handle = kernel::get_current_handle(screen_manager);
|
||||
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||
|
||||
unsafe {
|
||||
// fill the cells in console with blanks
|
||||
@ -42,7 +46,7 @@ pub fn fill_console_output_attribute(
|
||||
) -> bool {
|
||||
// Get the position of the current console window
|
||||
|
||||
let (csbi, mut handle) = kernel::get_buffer_info_and_hande(screen_manager);
|
||||
let (csbi, mut handle) = csbi::get_csbi_and_handle(screen_manager).unwrap();
|
||||
|
||||
let success;
|
||||
|
||||
@ -66,9 +70,7 @@ pub fn write_console_output(
|
||||
buffer_size: COORD,
|
||||
buffer_coord: COORD,
|
||||
source_buffer: PSMALL_RECT,
|
||||
) {
|
||||
use self::wincon::WriteConsoleOutputA;
|
||||
|
||||
) -> Result<()> {
|
||||
unsafe {
|
||||
if !kernel::is_true(
|
||||
WriteConsoleOutputA(
|
||||
@ -79,27 +81,34 @@ pub fn write_console_output(
|
||||
source_buffer,
|
||||
), // screen buffer source rectangle
|
||||
) {
|
||||
panic!("Cannot write to console output");
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not write to terminal",
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use winapi::ctypes::c_void;
|
||||
use std::str;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Write utf8 buffer to console.
|
||||
pub fn write_char_buffer(handle: &HANDLE, buf: &[u8]) -> ::std::io::Result<usize> {
|
||||
// get string from u8[] and parse it to an c_str
|
||||
let mut utf8 = match str::from_utf8(buf) {
|
||||
Ok(string) => string,
|
||||
Err(_) => "123",
|
||||
Err(_) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Could not parse input to utf8 string.",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let utf16: Vec<u16> = utf8.encode_utf16().collect();
|
||||
let utf16_ptr: *const c_void = utf16.as_ptr() as *const _ as *const c_void;
|
||||
|
||||
// get buffer info
|
||||
let csbi = kernel::get_console_screen_buffer_info_from_handle(handle);
|
||||
let csbi = csbi::get_csbi_by_handle(handle)?;
|
||||
|
||||
// get current position
|
||||
let current_pos = COORD {
|
||||
@ -108,7 +117,6 @@ pub fn write_char_buffer(handle: &HANDLE, buf: &[u8]) -> ::std::io::Result<usize
|
||||
};
|
||||
|
||||
let mut cells_written: u32 = 0;
|
||||
|
||||
let mut success = false;
|
||||
// write to console
|
||||
unsafe {
|
||||
@ -121,10 +129,9 @@ pub fn write_char_buffer(handle: &HANDLE, buf: &[u8]) -> ::std::io::Result<usize
|
||||
));
|
||||
}
|
||||
|
||||
match success
|
||||
{
|
||||
// think this is wrong could be done better!
|
||||
true => Ok(utf8.as_bytes().len()),
|
||||
false => Ok(0)
|
||||
}
|
||||
}
|
||||
match success {
|
||||
// think this is wrong could be done better!
|
||||
true => Ok(utf8.as_bytes().len()),
|
||||
false => Ok(0),
|
||||
}
|
||||
}
|
||||
|
@ -9,15 +9,15 @@ mod kernel;
|
||||
mod state;
|
||||
|
||||
pub mod cursor;
|
||||
pub mod input;
|
||||
pub mod manager;
|
||||
pub mod style;
|
||||
pub mod terminal;
|
||||
pub mod input;
|
||||
|
||||
pub use state::context::Context;
|
||||
pub use shared::crossterm::Crossterm;
|
||||
pub use shared::screen;
|
||||
pub use shared::raw;
|
||||
pub use shared::screen;
|
||||
pub use state::context::Context;
|
||||
|
||||
use manager::ScreenManager;
|
||||
use state::command_manager::CommandManager;
|
||||
|
@ -3,14 +3,14 @@
|
||||
//! This module uses the stdout to write to the console.
|
||||
|
||||
use std::any::Any;
|
||||
use std::io::{self, Write, Read };
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use super::IScreenManager;
|
||||
|
||||
pub struct AnsiScreenManager {
|
||||
pub is_alternate_screen: bool,
|
||||
output: Box<Write>,
|
||||
input: Box<Read>
|
||||
input: Box<Read>,
|
||||
}
|
||||
|
||||
impl IScreenManager for AnsiScreenManager {
|
||||
@ -30,19 +30,19 @@ impl IScreenManager for AnsiScreenManager {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
// fn read_line(&mut self) -> io::Result<String>
|
||||
// {
|
||||
// let mut rv = String::new();
|
||||
// self.input.read_line(&mut rv)?;
|
||||
// let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
||||
// rv.truncate(len);
|
||||
// Ok(rv)
|
||||
// }
|
||||
//
|
||||
// fn read_char(&mut self) -> io::Result<String>
|
||||
// {
|
||||
//
|
||||
// }
|
||||
// fn read_line(&mut self) -> io::Result<String>
|
||||
// {
|
||||
// let mut rv = String::new();
|
||||
// self.input.read_line(&mut rv)?;
|
||||
// let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
||||
// rv.truncate(len);
|
||||
// Ok(rv)
|
||||
// }
|
||||
//
|
||||
// fn read_char(&mut self) -> io::Result<String>
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.output.write(buf)
|
||||
|
@ -45,8 +45,7 @@ impl ScreenManager {
|
||||
}
|
||||
|
||||
/// Write an ANSI code as &str
|
||||
pub fn write_str(&mut self, string: &str) -> io::Result<usize>
|
||||
{
|
||||
pub fn write_str(&mut self, string: &str) -> io::Result<usize> {
|
||||
self.screen_manager.write_str(string)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
use super::IScreenManager;
|
||||
|
||||
use kernel::windows_kernel::kernel;
|
||||
use kernel::windows_kernel::writing;
|
||||
use kernel::windows_kernel::{handle, kernel, writing};
|
||||
use winapi::um::wincon::ENABLE_PROCESSED_OUTPUT;
|
||||
use winapi::um::winnt::HANDLE;
|
||||
|
||||
@ -20,13 +18,11 @@ impl IScreenManager for WinApiScreenManager {
|
||||
self.is_alternate_screen = is_alternate_screen;
|
||||
}
|
||||
|
||||
fn write_string(&mut self, string: String) -> io::Result<usize>
|
||||
{
|
||||
fn write_string(&mut self, string: String) -> io::Result<usize> {
|
||||
self.write(string.as_bytes())
|
||||
}
|
||||
|
||||
fn write_str(&mut self, string: &str) -> io::Result<usize>
|
||||
{
|
||||
fn write_str(&mut self, string: &str) -> io::Result<usize> {
|
||||
self.write(string.as_bytes())
|
||||
}
|
||||
|
||||
@ -51,9 +47,9 @@ impl IScreenManager for WinApiScreenManager {
|
||||
impl WinApiScreenManager {
|
||||
pub fn new() -> Self {
|
||||
WinApiScreenManager {
|
||||
output: kernel::get_output_handle(),
|
||||
output: handle::get_output_handle().unwrap(),
|
||||
is_alternate_screen: false,
|
||||
alternate_handle: kernel::get_output_handle(),
|
||||
alternate_handle: handle::get_output_handle().unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +65,6 @@ impl WinApiScreenManager {
|
||||
pub fn get_handle(&mut self) -> &HANDLE {
|
||||
if self.is_alternate_screen {
|
||||
return &self.alternate_handle;
|
||||
|
||||
} else {
|
||||
return &self.output;
|
||||
}
|
||||
|
@ -22,20 +22,18 @@
|
||||
//! let cursor = crossterm.cursor();
|
||||
//! let terminal = crossterm.terminal();
|
||||
|
||||
|
||||
|
||||
use super::super::cursor;
|
||||
use super::super::input::input;
|
||||
use super::super::style;
|
||||
use super::super::terminal::terminal;
|
||||
use super::super::input::input;
|
||||
|
||||
use Context;
|
||||
|
||||
use std::convert::From;
|
||||
use std::fmt::Display;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::convert::From;
|
||||
|
||||
/// Because it can seem a little odd to constantly create an `Context` and provide it to modules like: `cursor, color and terminal`.
|
||||
/// You can better use `Crossterm` for accessing these modules.
|
||||
@ -48,22 +46,21 @@ use std::convert::From;
|
||||
/// let cursor = crossterm.cursor();
|
||||
/// let terminal = crossterm.terminal();
|
||||
pub struct Crossterm {
|
||||
context: Rc<Context>
|
||||
context: Rc<Context>,
|
||||
}
|
||||
|
||||
/// Create `Crossterm` instance from `Context`
|
||||
impl From<Rc<Context>> for Crossterm
|
||||
{
|
||||
impl From<Rc<Context>> for Crossterm {
|
||||
fn from(context: Rc<Context>) -> Self {
|
||||
return Crossterm {
|
||||
context: context
|
||||
}
|
||||
return Crossterm { context: context };
|
||||
}
|
||||
}
|
||||
|
||||
impl Crossterm {
|
||||
pub fn new() -> Crossterm {
|
||||
return Crossterm { context: Context::new() };
|
||||
return Crossterm {
|
||||
context: Context::new(),
|
||||
};
|
||||
}
|
||||
|
||||
/// Get an Terminal implementation whereon terminal related actions can be performed.
|
||||
@ -80,8 +77,7 @@ impl Crossterm {
|
||||
/// let mut terminal = crossterm.terminal();
|
||||
///
|
||||
/// ```
|
||||
pub fn terminal(&self) -> terminal::Terminal
|
||||
{
|
||||
pub fn terminal(&self) -> terminal::Terminal {
|
||||
return terminal::Terminal::new(self.context.clone());
|
||||
}
|
||||
|
||||
@ -102,9 +98,8 @@ impl Crossterm {
|
||||
/// cursor.goto(5,10);
|
||||
///
|
||||
/// ```
|
||||
pub fn cursor(&self) -> cursor::TerminalCursor
|
||||
{
|
||||
return cursor::TerminalCursor::new(self.context.clone())
|
||||
pub fn cursor(&self) -> cursor::TerminalCursor {
|
||||
return cursor::TerminalCursor::new(self.context.clone());
|
||||
}
|
||||
|
||||
/// Get an Color implementation whereon color related actions can be performed.
|
||||
@ -123,13 +118,11 @@ impl Crossterm {
|
||||
/// let mut terminal_color = crossterm.color();
|
||||
///
|
||||
/// ```
|
||||
pub fn color(&self) -> style::TerminalColor
|
||||
{
|
||||
pub fn color(&self) -> style::TerminalColor {
|
||||
return style::TerminalColor::new(self.context.clone());
|
||||
}
|
||||
|
||||
pub fn input(&self) -> input::TerminalInput
|
||||
{
|
||||
pub fn input(&self) -> input::TerminalInput {
|
||||
return input::TerminalInput::new(self.context.clone());
|
||||
}
|
||||
|
||||
@ -179,8 +172,7 @@ impl Crossterm {
|
||||
/// crossterm.write("Some text \n Some text on new line.");
|
||||
///
|
||||
/// ```
|
||||
pub fn write<D: Display>(&self, value: D)
|
||||
{
|
||||
pub fn write<D: Display>(&self, value: D) {
|
||||
self.terminal().write(value)
|
||||
}
|
||||
|
||||
@ -188,4 +180,4 @@ impl Crossterm {
|
||||
pub fn context(&self) -> Rc<Context> {
|
||||
self.context.clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,13 +50,13 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
|
||||
let mut does_support = true;
|
||||
|
||||
if cfg!(target_os = "windows") {
|
||||
#[cfg(windows)]
|
||||
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
|
||||
#[cfg(windows)]
|
||||
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
|
||||
|
||||
// Try to enable ansi on windows if not than use WINAPI.
|
||||
// does_support = try_enable_ansi_support();
|
||||
does_support = try_enable_ansi_support();
|
||||
|
||||
does_support = false;
|
||||
// does_support = false;
|
||||
if !does_support {
|
||||
term = Some(winapi_impl);
|
||||
}
|
||||
|
@ -6,5 +6,5 @@ pub mod crossterm;
|
||||
pub mod functions;
|
||||
pub mod traits;
|
||||
|
||||
pub mod screen;
|
||||
pub mod raw;
|
||||
pub mod screen;
|
||||
|
@ -29,6 +29,25 @@ pub struct RawTerminal {
|
||||
command_id: u16,
|
||||
}
|
||||
|
||||
impl RawTerminal {
|
||||
pub fn new(context: &Rc<Context>) -> RawTerminal {
|
||||
let command_id = EnableRawModeCommand::new(&context.state_manager);
|
||||
|
||||
RawTerminal {
|
||||
context: context.clone(),
|
||||
command_id: command_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable(&self) -> bool {
|
||||
CommandManager::execute(self.context.clone(), self.command_id)
|
||||
}
|
||||
|
||||
pub fn disable(&self) -> bool {
|
||||
CommandManager::undo(self.context.clone(), self.command_id)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait withs contains a method for switching into raw mode.
|
||||
pub trait IntoRawMode: Write + Sized {
|
||||
fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
|
||||
|
@ -87,9 +87,9 @@ use shared::functions;
|
||||
use state::commands::*;
|
||||
use Context;
|
||||
|
||||
use std::convert::From;
|
||||
use std::io::{self, Write};
|
||||
use std::rc::Rc;
|
||||
use std::convert::From;
|
||||
|
||||
pub struct AlternateScreen {
|
||||
context: Rc<Context>,
|
||||
@ -167,8 +167,7 @@ impl Drop for AlternateScreen {
|
||||
|
||||
use super::super::shared::crossterm::Crossterm;
|
||||
|
||||
impl From<Crossterm> for AlternateScreen
|
||||
{
|
||||
impl From<Crossterm> for AlternateScreen {
|
||||
fn from(crossterm: Crossterm) -> Self {
|
||||
let command_id = get_to_alternate_screen_command(crossterm.context());
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
use super::IStateCommand;
|
||||
use {Context, StateManager};
|
||||
|
||||
use kernel::windows_kernel::{ansi_support, kernel};
|
||||
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
|
||||
use std::mem;
|
||||
use winapi::shared::minwindef::DWORD;
|
||||
use winapi::um::wincon;
|
||||
@ -34,7 +34,7 @@ impl IStateCommand for EnableAnsiCommand {
|
||||
if ansi_support::has_been_tried_to_enable_ansi() && ansi_support::ansi_enabled() {
|
||||
return ansi_support::windows_supportable();
|
||||
} else {
|
||||
let output_handle = kernel::get_output_handle();
|
||||
let output_handle = handle::get_output_handle().unwrap();
|
||||
|
||||
let mut dw_mode: DWORD = 0;
|
||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
||||
@ -51,7 +51,7 @@ impl IStateCommand for EnableAnsiCommand {
|
||||
|
||||
fn undo(&mut self) -> bool {
|
||||
if ansi_support::ansi_enabled() {
|
||||
let output_handle = kernel::get_output_handle();
|
||||
let output_handle = handle::get_output_handle().unwrap();
|
||||
|
||||
let mut dw_mode: DWORD = 0;
|
||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
||||
@ -96,7 +96,7 @@ impl EnableRawModeCommand {
|
||||
|
||||
impl IStateCommand for EnableRawModeCommand {
|
||||
fn execute(&mut self) -> bool {
|
||||
let input_handle = kernel::get_input_handle();
|
||||
let input_handle = handle::get_input_handle().unwrap();
|
||||
|
||||
let mut dw_mode: DWORD = 0;
|
||||
if !kernel::get_console_mode(&input_handle, &mut dw_mode) {
|
||||
@ -113,7 +113,7 @@ impl IStateCommand for EnableRawModeCommand {
|
||||
}
|
||||
|
||||
fn undo(&mut self) -> bool {
|
||||
let output_handle = kernel::get_output_handle();
|
||||
let output_handle = handle::get_output_handle().unwrap();
|
||||
|
||||
let mut dw_mode: DWORD = 0;
|
||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
||||
@ -155,13 +155,13 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
|
||||
fn execute(&mut self) -> bool {
|
||||
use super::super::super::manager::WinApiScreenManager;
|
||||
|
||||
let handle = kernel::get_output_handle();
|
||||
let handle = handle::get_output_handle().unwrap();
|
||||
|
||||
// create a new screen buffer to copy to.
|
||||
let new_handle = kernel::create_console_screen_buffer();
|
||||
let new_handle = csbi::create_console_screen_buffer();
|
||||
|
||||
// Make the new screen buffer the active screen buffer.
|
||||
kernel::set_active_screen_buffer(new_handle);
|
||||
csbi::set_active_screen_buffer(new_handle);
|
||||
|
||||
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
||||
screen_manager.toggle_is_alternate_screen(true);
|
||||
@ -180,8 +180,8 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
|
||||
}
|
||||
|
||||
fn undo(&mut self) -> bool {
|
||||
let handle = kernel::get_output_handle();
|
||||
kernel::set_active_screen_buffer(handle);
|
||||
let handle = handle::get_output_handle().unwrap();
|
||||
csbi::set_active_screen_buffer(handle);
|
||||
|
||||
{
|
||||
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
||||
|
@ -48,16 +48,16 @@
|
||||
|
||||
use {ScreenManager, StateManager};
|
||||
|
||||
use std::marker::Sync;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
use std::marker::Sync;
|
||||
/// This type is the context of the current terminal. The context is a wrapper for states changes of the terminal and can be used for managing the output of the terminal.
|
||||
pub struct Context {
|
||||
pub screen_manager: Rc<Mutex<ScreenManager>>,
|
||||
pub state_manager: Mutex<StateManager>,
|
||||
}
|
||||
|
||||
impl Context{
|
||||
impl Context {
|
||||
/// Create new Context instance so that you can provide it to other modules like terminal, cursor and color
|
||||
///
|
||||
/// This context type is just an wrapper that crossterm uses for managing the state the terminal.
|
||||
|
@ -9,9 +9,8 @@ use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// This struct is an ansi implementation for color related actions.
|
||||
pub struct AnsiColor
|
||||
{
|
||||
screen_manager: Rc<Mutex<ScreenManager>>
|
||||
pub struct AnsiColor {
|
||||
screen_manager: Rc<Mutex<ScreenManager>>,
|
||||
}
|
||||
|
||||
impl AnsiColor {
|
||||
@ -21,7 +20,7 @@ impl AnsiColor {
|
||||
}
|
||||
|
||||
impl ITerminalColor for AnsiColor {
|
||||
fn set_fg(&self, fg_color: Color ) {
|
||||
fn set_fg(&self, fg_color: Color) {
|
||||
let mx_guard = &self.screen_manager;
|
||||
let mut screen = mx_guard.lock().unwrap();
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
use super::super::super::manager::WinApiScreenManager;
|
||||
use super::super::{Color, ColorType};
|
||||
use super::ITerminalColor;
|
||||
use kernel::windows_kernel::kernel;
|
||||
use kernel::windows_kernel::{csbi, kernel};
|
||||
use winapi::um::wincon;
|
||||
use ScreenManager;
|
||||
use super::super::super::manager::WinApiScreenManager;
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::sync::Mutex;
|
||||
@ -25,7 +25,7 @@ impl ITerminalColor for WinApiColor {
|
||||
fn set_fg(&self, fg_color: Color) {
|
||||
let color_value = &self.color_value(fg_color, ColorType::Foreground);
|
||||
|
||||
let csbi = kernel::get_console_screen_buffer_info(&self.screen_manager);
|
||||
let csbi = csbi::get_csbi(&self.screen_manager).unwrap();
|
||||
|
||||
// Notice that the color values are stored in wAttribute.
|
||||
// So we need to use bitwise operators to check if the values exists or to get current console colors.
|
||||
@ -46,7 +46,7 @@ impl ITerminalColor for WinApiColor {
|
||||
fn set_bg(&self, bg_color: Color) {
|
||||
let color_value = &self.color_value(bg_color, ColorType::Background);
|
||||
|
||||
let (csbi,handle) = kernel::get_buffer_info_and_hande(&self.screen_manager);
|
||||
let (csbi, handle) = csbi::get_csbi_and_handle(&self.screen_manager).unwrap();
|
||||
|
||||
// Notice that the color values are stored in wAttribute.
|
||||
// So wee need to use bitwise operators to check if the values exists or to get current console colors.
|
||||
|
@ -32,8 +32,7 @@ impl Default for ObjectStyle {
|
||||
|
||||
impl ObjectStyle {
|
||||
/// Apply an `StyledObject` to the passed displayable object.
|
||||
pub fn apply_to<D: Display>(&self, val: D, context: Rc<Context>) -> StyledObject<D>
|
||||
{
|
||||
pub fn apply_to<D: Display>(&self, val: D, context: Rc<Context>) -> StyledObject<D> {
|
||||
StyledObject {
|
||||
object_style: self.clone(),
|
||||
context: context,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use Context;
|
||||
|
||||
use std::fmt::{self,Display};
|
||||
use std::fmt::{self, Display};
|
||||
use std::io::Write;
|
||||
use std::rc::Rc;
|
||||
|
||||
@ -21,7 +21,7 @@ pub struct StyledObject<D: Display> {
|
||||
pub context: Rc<Context>,
|
||||
}
|
||||
|
||||
impl<D: Display> StyledObject<D>{
|
||||
impl<D: Display> StyledObject<D> {
|
||||
/// Set the foreground of the styled object to the passed `Color`
|
||||
///
|
||||
/// #Example
|
||||
@ -146,10 +146,8 @@ impl<D: Display> StyledObject<D>{
|
||||
}
|
||||
}
|
||||
|
||||
impl <D:Display> Display for StyledObject<D>
|
||||
{
|
||||
impl<D: Display> Display for StyledObject<D> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
|
||||
let mut colored_terminal = super::super::color(&self.context);
|
||||
let mut reset = true;
|
||||
|
||||
@ -164,7 +162,7 @@ impl <D:Display> Display for StyledObject<D>
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
for attr in self.object_style.attrs.iter() {
|
||||
for attr in self.object_style.attrs.iter() {
|
||||
let mutex = &self.context.screen_manager;
|
||||
{
|
||||
let mut screen = mutex.lock().unwrap();
|
||||
|
@ -1,8 +1,8 @@
|
||||
//! This is an `ANSI escape code` specific implementation for terminal related action.
|
||||
//! This module is used for windows 10 terminals and unix terminals by default.
|
||||
|
||||
use super::{ClearType, ITerminal, Rc};
|
||||
use super::super::cursor::cursor;
|
||||
use super::{ClearType, ITerminal, Rc};
|
||||
use shared::functions;
|
||||
use Context;
|
||||
|
||||
@ -48,7 +48,6 @@ impl ITerminal for AnsiTerminal {
|
||||
fn scroll_up(&self, count: i16) {
|
||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||
{
|
||||
panic!();
|
||||
screen.write_string(format!(csi!("{}S"), count));
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ impl Terminal {
|
||||
///
|
||||
/// ```
|
||||
pub fn terminal_size(&self) -> (u16, u16) {
|
||||
return self.terminal.terminal_size();
|
||||
return self.terminal.terminal_size();
|
||||
}
|
||||
|
||||
/// Scroll `n` lines up in the current terminal.
|
||||
@ -176,7 +176,9 @@ impl Terminal {
|
||||
/// }
|
||||
///
|
||||
/// ```
|
||||
pub fn paint<D>(&self, val: D) -> style::StyledObject<D> where D: fmt::Display
|
||||
pub fn paint<D>(&self, val: D) -> style::StyledObject<D>
|
||||
where
|
||||
D: fmt::Display,
|
||||
{
|
||||
style::ObjectStyle::new().apply_to(val, self.context.clone())
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use super::super::shared::functions;
|
||||
use super::super::ScreenManager;
|
||||
use super::{ClearType, ITerminal, Rc};
|
||||
use cursor::cursor;
|
||||
use kernel::windows_kernel::{kernel, terminal, writing};
|
||||
use kernel::windows_kernel::{csbi, kernel, terminal, writing};
|
||||
use winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
|
||||
use Context;
|
||||
|
||||
@ -24,7 +24,7 @@ impl WinApiTerminal {
|
||||
|
||||
impl ITerminal for WinApiTerminal {
|
||||
fn clear(&self, clear_type: ClearType) {
|
||||
let csbi = kernel::get_console_screen_buffer_info(&self.context.screen_manager);
|
||||
let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();
|
||||
let pos = cursor(&self.context).pos();
|
||||
|
||||
match clear_type {
|
||||
@ -41,18 +41,18 @@ impl ITerminal for WinApiTerminal {
|
||||
}
|
||||
|
||||
fn scroll_up(&self, count: i16) {
|
||||
let csbi = kernel::get_console_screen_buffer_info(&self.context.screen_manager);
|
||||
let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();
|
||||
|
||||
// Set srctWindow to the current window size and location.
|
||||
let mut srct_window = csbi.srWindow;
|
||||
|
||||
|
||||
// Check whether the window is too close to the screen buffer top
|
||||
if srct_window.Top >= count {
|
||||
srct_window.Top -= count; // move top down
|
||||
srct_window.Top -= count; // move top down
|
||||
srct_window.Bottom = count; // move bottom down
|
||||
|
||||
let success = kernel::set_console_info(false, &mut srct_window, &self.context.screen_manager);
|
||||
let success =
|
||||
kernel::set_console_info(false, &mut srct_window, &self.context.screen_manager);
|
||||
if success {
|
||||
panic!("Something went wrong when scrolling down");
|
||||
}
|
||||
@ -60,20 +60,22 @@ impl ITerminal for WinApiTerminal {
|
||||
}
|
||||
|
||||
fn scroll_down(&self, count: i16) {
|
||||
|
||||
let csbi = kernel::get_console_screen_buffer_info(&self.context.screen_manager);
|
||||
let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();
|
||||
// Set srctWindow to the current window size and location.
|
||||
let mut srct_window = csbi.srWindow;
|
||||
|
||||
panic!("window top: {} , window bottom: {} | {}, {}", srct_window.Top, srct_window.Bottom, csbi.dwSize.Y, csbi.dwSize.X);
|
||||
// panic!("window top: {} , window bottom: {} | {}, {}", srct_window.Top, srct_window.Bottom, csbi.dwSize.Y, csbi.dwSize.X);
|
||||
|
||||
// Set srctWindow to the current window size and location.
|
||||
srct_window = csbi.srWindow;
|
||||
|
||||
// Check whether the window is too close to the screen buffer top
|
||||
if srct_window.Bottom < csbi.dwSize.Y - count {
|
||||
srct_window.Top += count; // move top down
|
||||
srct_window.Bottom += count; // move bottom down
|
||||
|
||||
let success = kernel::set_console_info(false, &mut srct_window, &self.context.screen_manager);
|
||||
|
||||
let success =
|
||||
kernel::set_console_info(true, &mut srct_window, &self.context.screen_manager);
|
||||
if success {
|
||||
panic!("Something went wrong when scrolling down");
|
||||
}
|
||||
@ -91,7 +93,7 @@ impl ITerminal for WinApiTerminal {
|
||||
}
|
||||
|
||||
// Get the position of the current console window
|
||||
let csbi = kernel::get_console_screen_buffer_info(&self.context.screen_manager);
|
||||
let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();
|
||||
let mut success = false;
|
||||
|
||||
// If the buffer is smaller than this new window size, resize the
|
||||
@ -120,7 +122,7 @@ impl ITerminal for WinApiTerminal {
|
||||
}
|
||||
|
||||
if resize_buffer {
|
||||
success = kernel::set_console_screen_buffer_size(size, &self.context.screen_manager);
|
||||
success = csbi::set_console_screen_buffer_size(size, &self.context.screen_manager);
|
||||
|
||||
if !success {
|
||||
panic!("Something went wrong when setting screen buffer size.");
|
||||
@ -137,7 +139,7 @@ impl ITerminal for WinApiTerminal {
|
||||
if success {
|
||||
// If we resized the buffer, un-resize it.
|
||||
if resize_buffer {
|
||||
kernel::set_console_screen_buffer_size(csbi.dwSize, &self.context.screen_manager);
|
||||
csbi::set_console_screen_buffer_size(csbi.dwSize, &self.context.screen_manager);
|
||||
}
|
||||
|
||||
let bounds = kernel::get_largest_console_window_size();
|
||||
|
Loading…
Reference in New Issue
Block a user