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.
|
//! This bin folder can be used to try the examples out located in the examples directory.
|
||||||
//!
|
//!
|
||||||
//! All you need to do is:
|
//! All you need to do is:
|
||||||
@ -25,22 +24,87 @@ use input::keyboard::{async_input, input as stdin};
|
|||||||
|
|
||||||
use crossterm::raw::IntoRawMode;
|
use crossterm::raw::IntoRawMode;
|
||||||
|
|
||||||
fn main()
|
use std::{thread, time};
|
||||||
{
|
|
||||||
let context = Context::new();
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// let context = Context::new();
|
||||||
|
crossterm();
|
||||||
{
|
{
|
||||||
// let screen = ::crossterm::screen::AlternateScreen::from(context.clone());
|
// let screen = ::crossterm::screen::AlternateScreen::from(context.clone());
|
||||||
// screen.into_raw_mode(context.clone());
|
// screen.into_raw_mode(context.clone());
|
||||||
|
|
||||||
|
// async_input::async_reading_on_alternate_screen();
|
||||||
async_input::async_reading_on_alternate_screen();
|
// async_input::test();
|
||||||
// async_input::test();
|
// stdin::t();
|
||||||
// stdin::t();
|
// stdin::read_line();
|
||||||
// stdin::read_line();
|
// stdin::read_char();
|
||||||
// stdin::read_char();
|
// 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 self::crossterm::Crossterm;
|
||||||
use crossterm::terminal::ClearType;
|
use crossterm::terminal::ClearType;
|
||||||
|
|
||||||
use std::{thread, time};
|
|
||||||
use crossterm::raw::IntoRawMode;
|
use crossterm::raw::IntoRawMode;
|
||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
use std::io::{Read, Write, stdout};
|
use std::io::{stdout, Read, Write};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|
||||||
/// this will capture the input until the given key.
|
/// this will capture the input until the given key.
|
||||||
pub fn read_async_until()
|
pub fn read_async_until() {
|
||||||
{
|
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let input = input(&context);
|
let input = input(&context);
|
||||||
|
|
||||||
let mut stdin = input.read_until_async(b'\r').bytes();
|
let mut stdin = input.read_until_async(b'\r').bytes();
|
||||||
|
|
||||||
for i in 0..100
|
for i in 0..100 {
|
||||||
{
|
|
||||||
let a = stdin.next();
|
let a = stdin.next();
|
||||||
|
|
||||||
println!("pressed key: {:?}", a);
|
println!("pressed key: {:?}", a);
|
||||||
@ -41,15 +38,13 @@ pub fn read_async_until()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// this will read pressed characters async until `x` is typed .
|
/// this will read pressed characters async until `x` is typed .
|
||||||
pub fn read_async()
|
pub fn read_async() {
|
||||||
{
|
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let input = input(&context);
|
let input = input(&context);
|
||||||
|
|
||||||
let mut stdin = input.read_async().bytes();
|
let mut stdin = input.read_async().bytes();
|
||||||
|
|
||||||
for i in 0..100
|
for i in 0..100 {
|
||||||
{
|
|
||||||
let a = stdin.next();
|
let a = stdin.next();
|
||||||
|
|
||||||
println!("pressed key: {:?}", a);
|
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();
|
let crossterm = Crossterm::new();
|
||||||
|
|
||||||
// init some modules we use for this demo
|
// init some modules we use for this demo
|
||||||
@ -82,7 +76,6 @@ pub fn read_async_demo()
|
|||||||
terminal.clear(ClearType::All);
|
terminal.clear(ClearType::All);
|
||||||
cursor.goto(1, 1);
|
cursor.goto(1, 1);
|
||||||
|
|
||||||
|
|
||||||
// loop until the enter key (\r) is pressed.
|
// loop until the enter key (\r) is pressed.
|
||||||
loop {
|
loop {
|
||||||
terminal.clear(ClearType::All);
|
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;
|
use crossterm::screen::AlternateScreen;
|
||||||
|
|
||||||
let crossterm = Crossterm::new();
|
let crossterm = Crossterm::new();
|
||||||
@ -126,7 +118,7 @@ pub fn async_reading_on_alternate_screen()
|
|||||||
terminal.clear(ClearType::All);
|
terminal.clear(ClearType::All);
|
||||||
cursor.goto(1, 1);
|
cursor.goto(1, 1);
|
||||||
|
|
||||||
// panic!();
|
// panic!();
|
||||||
|
|
||||||
// loop until the enter key (\r) is pressed.
|
// loop until the enter key (\r) is pressed.
|
||||||
loop {
|
loop {
|
||||||
@ -136,7 +128,11 @@ pub fn async_reading_on_alternate_screen()
|
|||||||
// get the next pressed key
|
// get the next pressed key
|
||||||
let pressed_key = stdin.next();
|
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)
|
// check if pressed key is enter (\r)
|
||||||
if let Some(Ok(b'\r')) = pressed_key {
|
if let Some(Ok(b'\r')) = pressed_key {
|
||||||
|
@ -3,26 +3,22 @@ extern crate crossterm;
|
|||||||
use self::crossterm::input::input;
|
use self::crossterm::input::input;
|
||||||
use self::crossterm::Context;
|
use self::crossterm::Context;
|
||||||
|
|
||||||
pub fn read_char()
|
pub fn read_char() {
|
||||||
{
|
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
let input = input(&context);
|
let input = input(&context);
|
||||||
|
|
||||||
match input.read_char()
|
match input.read_char() {
|
||||||
{
|
|
||||||
Ok(c) => println!("character pressed: {}", c),
|
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 context = Context::new();
|
||||||
let input = input(&context);
|
let input = input(&context);
|
||||||
|
|
||||||
match input.read_line()
|
match input.read_line() {
|
||||||
{
|
|
||||||
Ok(s) => println!("string typed: {}", s),
|
Ok(s) => println!("string typed: {}", s),
|
||||||
Err(e) => println!("error: {}", e)
|
Err(e) => println!("error: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -335,7 +335,7 @@ impl TerminalCursor {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn blink(&self, blink: bool) {
|
pub fn blink(&self, blink: bool) {
|
||||||
self.terminal_cursor.blink(blink);
|
self.terminal_cursor.blink(blink);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
//! so that the cursor related actions can be preformed on both unix and windows systems.
|
//! so that the cursor related actions can be preformed on both unix and windows systems.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
pub mod cursor;
|
|
||||||
mod ansi_cursor;
|
mod ansi_cursor;
|
||||||
|
pub mod cursor;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
mod winapi_cursor;
|
mod winapi_cursor;
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ impl WinApiCursor {
|
|||||||
|
|
||||||
impl ITerminalCursor for WinApiCursor {
|
impl ITerminalCursor for WinApiCursor {
|
||||||
fn goto(&self, x: u16, y: u16) {
|
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) {
|
fn pos(&self) -> (u16, u16) {
|
||||||
@ -58,11 +58,11 @@ impl ITerminalCursor for WinApiCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn hide(&self) {
|
fn hide(&self) {
|
||||||
kernel::cursor_visibility(false, &self.screen_manager);
|
cursor::cursor_visibility(false, &self.screen_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show(&self) {
|
fn show(&self) {
|
||||||
kernel::cursor_visibility(true, &self.screen_manager);
|
cursor::cursor_visibility(true, &self.screen_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blink(&self, blink: bool) {}
|
fn blink(&self, blink: bool) {}
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use Context;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use Context;
|
||||||
|
|
||||||
pub struct TerminalInput
|
pub struct TerminalInput {
|
||||||
{
|
|
||||||
context: Rc<Context>,
|
context: Rc<Context>,
|
||||||
terminal_input: Box<ITerminalInput>,
|
terminal_input: Box<ITerminalInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TerminalInput
|
impl TerminalInput {
|
||||||
{
|
pub fn new(context: Rc<Context>) -> TerminalInput {
|
||||||
pub fn new(context: Rc<Context>) -> TerminalInput
|
|
||||||
{
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
let input = Box::from(WindowsInput::new(context.clone()));
|
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()
|
self.terminal_input.read_line()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_char(&self) -> io::Result<char>
|
pub fn read_char(&self) -> io::Result<char> {
|
||||||
{
|
return self.terminal_input.read_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()
|
self.terminal_input.read_pressed_key()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_async(&self) -> AsyncReader
|
pub fn read_async(&self) -> AsyncReader {
|
||||||
{
|
|
||||||
self.terminal_input.read_async()
|
self.terminal_input.read_async()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_until_async(&self, delimiter: u8) -> AsyncReader
|
pub fn read_until_async(&self, delimiter: u8) -> AsyncReader {
|
||||||
{ self.terminal_input.read_until_async(delimiter)
|
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()));
|
return Box::from(TerminalInput::new(context.clone()));
|
||||||
}
|
}
|
@ -12,14 +12,12 @@ use self::unix_input::UnixInput;
|
|||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
mod unix_input;
|
mod unix_input;
|
||||||
|
|
||||||
|
pub use self::input::{input, TerminalInput};
|
||||||
pub use self::input::{ input, TerminalInput };
|
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
trait ITerminalInput
|
trait ITerminalInput {
|
||||||
{
|
|
||||||
fn read_line(&self) -> io::Result<String>;
|
fn read_line(&self) -> io::Result<String>;
|
||||||
|
|
||||||
fn read_char(&self) -> io::Result<char>;
|
fn read_char(&self) -> io::Result<char>;
|
||||||
@ -29,9 +27,8 @@ trait ITerminalInput
|
|||||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader;
|
fn read_until_async(&self, delimiter: u8) -> AsyncReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AsyncReader
|
pub struct AsyncReader {
|
||||||
{
|
recv: mpsc::Receiver<io::Result<u8>>,
|
||||||
recv: mpsc::Receiver<io::Result<u8>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Read for AsyncReader {
|
impl Read for AsyncReader {
|
||||||
|
@ -1,30 +1,24 @@
|
|||||||
use std::io;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::char;
|
use std::char;
|
||||||
|
use std::io;
|
||||||
|
use std::io::Read;
|
||||||
|
use std::io::Write;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
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::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;
|
pub struct UnixInput;
|
||||||
|
|
||||||
|
impl UnixInput {
|
||||||
impl UnixInput
|
pub fn new() -> UnixInput {
|
||||||
{
|
|
||||||
pub fn new() -> UnixInput
|
|
||||||
{
|
|
||||||
UnixInput {}
|
UnixInput {}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalInput for UnixInput
|
impl ITerminalInput for UnixInput {
|
||||||
{
|
fn read_line(&self) -> io::Result<String> {
|
||||||
fn read_line(&self) -> io::Result<String>
|
|
||||||
{
|
|
||||||
let mut rv = String::new();
|
let mut rv = String::new();
|
||||||
io::stdin().read_line(&mut rv)?;
|
io::stdin().read_line(&mut rv)?;
|
||||||
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
||||||
@ -32,47 +26,49 @@ impl ITerminalInput for UnixInput
|
|||||||
Ok(rv)
|
Ok(rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_char(&self) -> io::Result<char>
|
fn read_char(&self) -> io::Result<char> {
|
||||||
{
|
|
||||||
read_char()
|
read_char()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_pressed_key(&self) -> io::Result<Key>
|
fn read_pressed_key(&self) -> io::Result<Key> {
|
||||||
{
|
|
||||||
Ok(Key::Unknown)
|
Ok(Key::Unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_async(&self) -> AsyncReader
|
fn read_async(&self) -> AsyncReader {
|
||||||
{
|
|
||||||
let (send, recv) = mpsc::channel();
|
let (send, recv) = mpsc::channel();
|
||||||
|
|
||||||
thread::spawn(move || for i in get_tty().unwrap().bytes() {
|
thread::spawn(move || {
|
||||||
if send.send(i).is_err() {
|
for i in get_tty().unwrap().bytes() {
|
||||||
return;
|
if send.send(i).is_err() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AsyncReader { recv: recv }
|
AsyncReader { recv: recv }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader
|
fn read_until_async(&self, delimiter: u8) -> AsyncReader {
|
||||||
{
|
|
||||||
let (send, recv) = mpsc::channel();
|
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 {
|
if end_of_stream || send_error {
|
||||||
Ok(byte) => {
|
return;
|
||||||
let end_of_stream = &byte == &delimiter;
|
}
|
||||||
let send_error = send.send(Ok(byte)).is_err();
|
}
|
||||||
|
Err(_) => {
|
||||||
if end_of_stream || send_error { return; }
|
return;
|
||||||
},
|
}
|
||||||
Err(_) => { return; }
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AsyncReader { recv: recv }
|
AsyncReader { recv: recv }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,37 +1,34 @@
|
|||||||
|
use std::char;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::char;
|
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::thread;
|
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 winapi::um::winuser;
|
||||||
|
|
||||||
use super::super::terminal::terminal;
|
use super::super::terminal::terminal;
|
||||||
use super::super::kernel::windows_kernel::reading;
|
|
||||||
use Context;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use Context;
|
||||||
|
|
||||||
pub struct WindowsInput
|
pub struct WindowsInput {
|
||||||
{
|
|
||||||
context: Rc<Context>,
|
context: Rc<Context>,
|
||||||
pub display_input: bool,
|
pub display_input: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowsInput
|
impl WindowsInput {
|
||||||
{
|
pub fn new(context: Rc<Context>) -> WindowsInput {
|
||||||
pub fn new(context: Rc<Context>) -> WindowsInput
|
WindowsInput {
|
||||||
{
|
context,
|
||||||
WindowsInput { context, display_input: false }
|
display_input: false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalInput for WindowsInput
|
impl ITerminalInput for WindowsInput {
|
||||||
{
|
fn read_line(&self) -> io::Result<String> {
|
||||||
fn read_line(&self) -> io::Result<String>
|
|
||||||
{
|
|
||||||
let term = terminal(&self.context);
|
let term = terminal(&self.context);
|
||||||
let mut chars: Vec<char> = Vec::new();
|
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 0 or 0xe0 we need to listen again because the next key will be an special key
|
||||||
if pressed_char != 0 || pressed_char != 0xe0 {
|
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) => {
|
Some(c) => {
|
||||||
if is_line_end(c) { break; }
|
if is_line_end(c) {
|
||||||
else { chars.push(c); }
|
break;
|
||||||
|
} else {
|
||||||
if self.display_input
|
chars.push(c);
|
||||||
{
|
|
||||||
term.write(c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
if self.display_input {
|
||||||
None => { panic!("Some error needs to be returned") }
|
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());
|
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 term = terminal(&self.context);
|
||||||
|
|
||||||
let pressed_char = unsafe { _getwch() };
|
let pressed_char = unsafe { _getwch() };
|
||||||
|
|
||||||
// we could return error but maybe option to keep listening until valid character is inputted.
|
// we could return error but maybe option to keep listening until valid character is inputted.
|
||||||
if pressed_char == 0 || pressed_char == 0xe0 {
|
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) => {
|
Some(c) => {
|
||||||
if self.display_input
|
if self.display_input {
|
||||||
{
|
|
||||||
term.write(c);
|
term.write(c);
|
||||||
}
|
}
|
||||||
return Ok(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;
|
use Context;
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
||||||
let buf: [u8; 1024] = unsafe { ::std::mem::zeroed() };
|
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)
|
Ok(Key::Unknown)
|
||||||
// let pressed_char = unsafe { _getwch() };
|
// let pressed_char = unsafe { _getwch() };
|
||||||
//
|
//
|
||||||
// // if 0 or 0xe0 we need to listen again because the next key will be an special key
|
// // 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 {
|
// if pressed_char == 0 || pressed_char == 0xe0 {
|
||||||
// let special_key: i32 = unsafe { _getwch() };
|
// let special_key: i32 = unsafe { _getwch() };
|
||||||
// println!("spkey {}",special_key);
|
// println!("spkey {}",special_key);
|
||||||
// return Ok(key_from_key_code(0x26));
|
// return Ok(key_from_key_code(0x26));
|
||||||
// } else {
|
// } else {
|
||||||
// match char::from_u32(pressed_char as u32)
|
// match char::from_u32(pressed_char as u32)
|
||||||
// {
|
// {
|
||||||
// Some(c) => return Ok(Key::Char(c)),
|
// Some(c) => return Ok(Key::Char(c)),
|
||||||
// None => { panic!("Some error needs to be returned") }
|
// None => { panic!("Some error needs to be returned") }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_async(&self) -> AsyncReader
|
fn read_async(&self) -> AsyncReader {
|
||||||
{
|
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop
|
loop {
|
||||||
{
|
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
|
||||||
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
|
|
||||||
|
|
||||||
// we could return error but maybe option to keep listening until valid character is inputted.
|
// we could return error but maybe option to keep listening until valid character is inputted.
|
||||||
if pressed_char == 0 || pressed_char == 0xe0 {
|
if pressed_char == 0 || pressed_char == 0xe0 {
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
tx.send(Ok(pressed_char as u8));
|
|
||||||
|
|
||||||
if pressed_char == 13
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tx.send(Ok(pressed_char as u8));
|
||||||
|
|
||||||
|
if pressed_char == 13 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AsyncReader { recv: rx }
|
AsyncReader { recv: rx }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_until_async(&self, delimiter: u8) -> AsyncReader
|
fn read_until_async(&self, delimiter: u8) -> AsyncReader {
|
||||||
{
|
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop
|
loop {
|
||||||
{
|
|
||||||
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
|
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
|
||||||
|
|
||||||
let end_of_stream = (pressed_char == delimiter);
|
let end_of_stream = (pressed_char == delimiter);
|
||||||
@ -159,17 +153,14 @@ impl ITerminalInput for WindowsInput
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_line_end(key: char) -> bool
|
fn is_line_end(key: char) -> bool {
|
||||||
{
|
if key as u8 == 13 {
|
||||||
if key as u8 == 13
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//0 59 = F1
|
//0 59 = F1
|
||||||
//0 60 = F2
|
//0 60 = F2
|
||||||
//0 61 = F3
|
//0 61 = F3
|
||||||
@ -193,23 +184,21 @@ fn is_line_end(key: char) -> bool
|
|||||||
//224 133 = F11
|
//224 133 = F11
|
||||||
//224 134 = F12
|
//224 134 = F12
|
||||||
|
|
||||||
|
|
||||||
fn key_from_key_code(code: INT) -> Key {
|
fn key_from_key_code(code: INT) -> Key {
|
||||||
|
|
||||||
println!("code: {}", code);
|
println!("code: {}", code);
|
||||||
println!("up winapi: {}", winuser::VK_UP);
|
println!("up winapi: {}", winuser::VK_UP);
|
||||||
|
|
||||||
match code {
|
match code {
|
||||||
// 59 => Key::F1,
|
// 59 => Key::F1,
|
||||||
// 60 => Key::F2,
|
// 60 => Key::F2,
|
||||||
// 61 => Key::F3,
|
// 61 => Key::F3,
|
||||||
// 62 => Key::F4,
|
// 62 => Key::F4,
|
||||||
// 63 => Key::F5,
|
// 63 => Key::F5,
|
||||||
// 64 => Key::F6,
|
// 64 => Key::F6,
|
||||||
// 65 => Key::F7,
|
// 65 => Key::F7,
|
||||||
// 66 => Key::F8,
|
// 66 => Key::F8,
|
||||||
// 67 => Key::F9,
|
// 67 => Key::F9,
|
||||||
// 68 => Key::F10,
|
// 68 => Key::F10,
|
||||||
winuser::VK_LEFT => Key::ArrowLeft,
|
winuser::VK_LEFT => Key::ArrowLeft,
|
||||||
winuser::VK_RIGHT => Key::ArrowRight,
|
winuser::VK_RIGHT => Key::ArrowRight,
|
||||||
winuser::VK_UP => Key::ArrowUp,
|
winuser::VK_UP => Key::ArrowUp,
|
||||||
|
@ -5,11 +5,11 @@ use self::libc::{c_int, c_ushort, ioctl, STDOUT_FILENO, TIOCGWINSZ};
|
|||||||
use state::commands::{IStateCommand, NoncanonicalModeCommand};
|
use state::commands::{IStateCommand, NoncanonicalModeCommand};
|
||||||
use {libc, CommandManager, Context, StateManager};
|
use {libc, CommandManager, Context, StateManager};
|
||||||
|
|
||||||
use termios::{ Termios,cfmakeraw,tcsetattr,TCSADRAIN };
|
|
||||||
use std::io::Error;
|
use std::io::Error;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::{io, mem, fs};
|
|
||||||
use std::os::unix::io::AsRawFd;
|
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.
|
/// A representation of the size of the current terminal.
|
||||||
#[repr(C)]
|
#[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.
|
/// This allows for getting stdio representing _only_ the TTY, and not other streams.
|
||||||
pub fn get_tty() -> io::Result<fs::File> {
|
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];
|
let mut buf = [0u8; 20];
|
||||||
|
|
||||||
// get tty raw handle.
|
// get tty raw handle.
|
||||||
let tty_f;
|
let tty_f;
|
||||||
|
|
||||||
let fd = unsafe
|
let fd = unsafe {
|
||||||
{
|
if libc::isatty(libc::STDIN_FILENO) == 1 {
|
||||||
if libc::isatty(libc::STDIN_FILENO) == 1
|
libc::STDIN_FILENO
|
||||||
{
|
} else {
|
||||||
libc::STDIN_FILENO
|
tty_f = fs::File::open("/dev/tty")?;
|
||||||
} else {
|
tty_f.as_raw_fd()
|
||||||
tty_f = fs::File::open("/dev/tty")?;
|
}
|
||||||
tty_f.as_raw_fd()
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let mut termios = Termios::from_fd(fd)?;
|
let mut termios = Termios::from_fd(fd)?;
|
||||||
let original = termios.clone();
|
let original = termios.clone();
|
||||||
@ -174,31 +172,36 @@ pub fn read_char() -> io::Result<char>
|
|||||||
if read < 0 {
|
if read < 0 {
|
||||||
Err(io::Error::last_os_error())
|
Err(io::Error::last_os_error())
|
||||||
} else if buf[0] == b'\x03' {
|
} 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 {
|
} else {
|
||||||
let mut pressed_char = Ok(' ');
|
let mut pressed_char = Ok(' ');
|
||||||
|
|
||||||
if let Ok(s) = ::std::str::from_utf8(&buf[..read as usize])
|
if let Ok(s) = ::std::str::from_utf8(&buf[..read as usize]) {
|
||||||
{
|
if let Some(c) = s.chars().next() {
|
||||||
if let Some(c) = s.chars().next()
|
pressed_char = Ok(c);
|
||||||
{
|
}
|
||||||
pressed_char = Ok(c);
|
} else {
|
||||||
}
|
pressed_char = Err(io::Error::new(
|
||||||
}else {
|
io::ErrorKind::Interrupted,
|
||||||
pressed_char = Err(io::Error::new(io::ErrorKind::Interrupted, "Could not parse char to utf8 char"));
|
"Could not parse char to utf8 char",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
pressed_char
|
pressed_char
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
tcsetattr(fd, TCSADRAIN, &original)?;
|
tcsetattr(fd, TCSADRAIN, &original)?;
|
||||||
|
|
||||||
// if the user hit ^C we want to signal SIGINT to outselves.
|
// if the user hit ^C we want to signal SIGINT to outselves.
|
||||||
if let Err(ref err) = rv {
|
if let Err(ref err) = rv {
|
||||||
if err.kind() == io::ErrorKind::Interrupted {
|
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 std::sync::{Once, ONCE_INIT};
|
||||||
use IStateCommand;
|
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 IS_ANSI_ON_WINDOWS_ENABLED: Option<bool> = None;
|
||||||
static mut DOES_WINDOWS_SUPPORT_ANSI: 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.
|
/// Try enable `ANSI escape codes` and return the result.
|
||||||
pub fn try_enable_ansi_support() -> bool {
|
pub fn try_enable_ansi_support() -> bool {
|
||||||
START.call_once(|| {
|
ENABLE_ANSI.call_once(|| {
|
||||||
use state::commands::win_commands::EnableAnsiCommand;
|
use state::commands::win_commands::EnableAnsiCommand;
|
||||||
let mut command = EnableAnsiCommand::new();
|
let mut command = EnableAnsiCommand::new();
|
||||||
let success = command.execute();
|
let success = command.execute();
|
||||||
@ -35,7 +35,7 @@ pub fn windows_supportable() -> bool {
|
|||||||
/// Get whether ansi has been tried to enable before.
|
/// Get whether ansi has been tried to enable before.
|
||||||
pub fn has_been_tried_to_enable_ansi() -> bool {
|
pub fn has_been_tried_to_enable_ansi() -> bool {
|
||||||
unsafe {
|
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.
|
/// 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) {
|
fn has_been_tried_to_enable(has_been_tried: bool) {
|
||||||
unsafe {
|
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.
|
//! This module handles some logic for cursor interaction in the windows console.
|
||||||
|
|
||||||
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
|
use winapi::shared::minwindef::{FALSE, TRUE};
|
||||||
use super::kernel;
|
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::rc::Rc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
@ -12,7 +18,7 @@ static mut SAVED_CURSOR_POS: (u16, u16) = (0, 0);
|
|||||||
/// Reset to saved cursor position
|
/// Reset to saved cursor position
|
||||||
pub fn reset_to_saved_position(screen_manager: &Rc<Mutex<ScreenManager>>) {
|
pub fn reset_to_saved_position(screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
kernel::set_console_cursor_position(
|
set_console_cursor_position(
|
||||||
SAVED_CURSOR_POS.0 as i16,
|
SAVED_CURSOR_POS.0 as i16,
|
||||||
SAVED_CURSOR_POS.1 as i16,
|
SAVED_CURSOR_POS.1 as i16,
|
||||||
screen_manager,
|
screen_manager,
|
||||||
@ -31,9 +37,61 @@ pub fn save_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) {
|
|||||||
|
|
||||||
/// get the current cursor position.
|
/// get the current cursor position.
|
||||||
pub fn pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
|
pub fn pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
|
||||||
let csbi = kernel::get_console_screen_buffer_info(screen_manager);
|
if let Ok(csbi) = csbi::get_csbi(screen_manager) {
|
||||||
(
|
(
|
||||||
csbi.dwCursorPosition.X as u16,
|
csbi.dwCursorPosition.X as u16,
|
||||||
csbi.dwCursorPosition.Y 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::shared::ntdef::NULL;
|
||||||
use winapi::um::consoleapi::WriteConsoleW;
|
use winapi::um::consoleapi::WriteConsoleW;
|
||||||
use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode};
|
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;
|
||||||
use winapi::um::wincon::{
|
use winapi::um::wincon::{
|
||||||
CreateConsoleScreenBuffer, FillConsoleOutputAttribute, FillConsoleOutputCharacterA,
|
CreateConsoleScreenBuffer, FillConsoleOutputAttribute, FillConsoleOutputCharacterA,
|
||||||
@ -23,206 +21,39 @@ use winapi::um::wincon::{
|
|||||||
};
|
};
|
||||||
use winapi::um::winnt::HANDLE;
|
use winapi::um::winnt::HANDLE;
|
||||||
|
|
||||||
use super::Empty;
|
use super::{handle, Empty};
|
||||||
static mut CONSOLE_OUTPUT_HANDLE: Option<HANDLE> = None;
|
|
||||||
static mut CONSOLE_INPUT_HANDLE: Option<HANDLE> = None;
|
|
||||||
|
|
||||||
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
|
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
|
||||||
|
use std::io::{ErrorKind, Result};
|
||||||
use std::sync::Mutex;
|
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.
|
/// Get the largest console window size possible.
|
||||||
pub fn get_largest_console_window_size() -> COORD {
|
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) }
|
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.
|
/// Set the console mode to the given console mode.
|
||||||
pub fn set_console_mode(handle: &HANDLE, console_mode: u32) -> bool {
|
pub fn set_console_mode(handle: &HANDLE, console_mode: u32) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let success = SetConsoleMode(*handle, console_mode);
|
return is_true(SetConsoleMode(*handle, console_mode));
|
||||||
return is_true(success);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the console mode.
|
/// Get the console mode.
|
||||||
pub fn get_console_mode(handle: &HANDLE, current_mode: &mut u32) -> bool {
|
pub fn get_console_mode(handle: &HANDLE, current_mode: &mut u32) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
let success = GetConsoleMode(*handle, &mut *current_mode);
|
return is_true(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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change the console text attribute.
|
/// Change the console text attribute.
|
||||||
pub fn set_console_text_attribute(value: u16, screen_manager: &Rc<Mutex<ScreenManager>>) {
|
pub fn set_console_text_attribute(value: u16, screen_manager: &Rc<Mutex<ScreenManager>>) -> bool {
|
||||||
let handle = get_current_handle(screen_manager);
|
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
SetConsoleTextAttribute(handle, value);
|
return is_true(SetConsoleTextAttribute(handle, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,71 +63,17 @@ pub fn set_console_info(
|
|||||||
rect: &SMALL_RECT,
|
rect: &SMALL_RECT,
|
||||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let handle = get_current_handle(screen_manager);
|
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||||
|
|
||||||
let absolute = match absolute {
|
let absolute = match absolute {
|
||||||
true => 1,
|
true => 1,
|
||||||
false => 0,
|
false => 0,
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let success = SetConsoleWindowInfo(handle, absolute, rect);
|
return is_true(SetConsoleWindowInfo(handle, absolute, rect));
|
||||||
is_true(success)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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
|
/// Parse integer to an bool
|
||||||
pub fn is_true(value: i32) -> bool {
|
pub fn is_true(value: i32) -> bool {
|
||||||
if value == 0 {
|
if value == 0 {
|
||||||
@ -305,3 +82,9 @@ pub fn is_true(value: i32) -> bool {
|
|||||||
return true;
|
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 kernel;
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
pub mod writing;
|
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 self::winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
|
||||||
use shared::traits::Empty;
|
use shared::traits::Empty;
|
||||||
|
@ -1,84 +1,84 @@
|
|||||||
use { Context, ScreenManager };
|
//use { Context, ScreenManager };
|
||||||
use std::rc::Rc;
|
//use std::rc::Rc;
|
||||||
use std::sync::Mutex;
|
//use std::sync::Mutex;
|
||||||
|
//
|
||||||
use winapi::um::consoleapi::ReadConsoleW;
|
//use winapi::um::consoleapi::ReadConsoleW;
|
||||||
use winapi::um::winnt::HANDLE;
|
//use winapi::um::winnt::HANDLE;
|
||||||
use winapi::um::wincon::{ COORD, PSMALL_RECT, ReadConsoleOutputA, CHAR_INFO, };
|
//use winapi::um::wincon::{ COORD, PSMALL_RECT, ReadConsoleOutputA, CHAR_INFO, };
|
||||||
use winapi::shared::minwindef::{ DWORD, LPDWORD, LPVOID };
|
//use winapi::shared::minwindef::{ DWORD, LPDWORD, LPVOID };
|
||||||
use winapi::shared::ntdef::NULL;
|
//use winapi::shared::ntdef::NULL;
|
||||||
|
//
|
||||||
use super::kernel;
|
//use super::kernel;
|
||||||
use winapi::ctypes::c_void;
|
//use winapi::ctypes::c_void;
|
||||||
|
//
|
||||||
pub fn read(buf: &mut [u8], screen_manager: &Rc<Mutex<ScreenManager>>) {
|
//pub fn read(buf: &mut [u8], screen_manager: &Rc<Mutex<ScreenManager>>) {
|
||||||
// // Read more if the buffer is empty
|
//// // Read more if the buffer is empty
|
||||||
// let mut utf16: Vec<u16> = Vec::new();
|
//// let mut utf16: Vec<u16> = Vec::new();
|
||||||
// let mut num: DWORD = 0;
|
//// 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 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 {
|
// unsafe {
|
||||||
// ReadConsoleW(handle,
|
// if !kernel::is_true(
|
||||||
// utf16.as_mut_ptr() as LPVOID,
|
// ReadConsoleOutputA(
|
||||||
// utf16.len() as u32,
|
// *read_buffer, // screen buffer to read from
|
||||||
// &mut num as LPDWORD,
|
// copy_buffer.as_mut_ptr(), // buffer to copy into
|
||||||
// ptr::mut_null())
|
// buffer_size, // col-row size of chiBuffer
|
||||||
// };
|
// buffer_coord, // top left dest. cell in chiBuffer
|
||||||
//
|
// source_buffer,
|
||||||
// utf16.truncate(num as uint);
|
// ), // screen buffer source rectangle
|
||||||
// let utf8 = match from_utf16(utf16.as_slice()) {
|
// ) {
|
||||||
// Some(utf8) => utf8.into_bytes(),
|
// panic!("Cannot read console output");
|
||||||
// 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,13 +2,18 @@ use std::rc::Rc;
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use ScreenManager;
|
use ScreenManager;
|
||||||
|
|
||||||
|
use super::csbi;
|
||||||
|
|
||||||
/// Get the terminal size
|
/// Get the terminal size
|
||||||
pub fn terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
|
pub fn terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
|
||||||
let csbi = super::kernel::get_console_screen_buffer_info(screen_manager);
|
if let Ok(csbi) = csbi::get_csbi(screen_manager) {
|
||||||
(
|
(
|
||||||
(csbi.srWindow.Right - csbi.srWindow.Left) as u16,
|
(csbi.srWindow.Right - csbi.srWindow.Left) as u16,
|
||||||
(csbi.srWindow.Bottom - csbi.srWindow.Top) as u16,
|
(csbi.srWindow.Bottom - csbi.srWindow.Top) as u16,
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
return (0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Exit the current process.
|
/// Exit the current process.
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
use { Context, ScreenManager };
|
use winapi::ctypes::c_void;
|
||||||
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::shared::ntdef::NULL;
|
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.
|
/// Fill a certain block with characters.
|
||||||
pub fn fill_console_output_character(
|
pub fn fill_console_output_character(
|
||||||
@ -17,8 +22,7 @@ pub fn fill_console_output_character(
|
|||||||
cells_to_write: u32,
|
cells_to_write: u32,
|
||||||
screen_manager: &Rc<Mutex<ScreenManager>>,
|
screen_manager: &Rc<Mutex<ScreenManager>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let handle = handle::get_current_handle(screen_manager).unwrap();
|
||||||
let handle = kernel::get_current_handle(screen_manager);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// fill the cells in console with blanks
|
// fill the cells in console with blanks
|
||||||
@ -42,7 +46,7 @@ pub fn fill_console_output_attribute(
|
|||||||
) -> bool {
|
) -> bool {
|
||||||
// Get the position of the current console window
|
// 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;
|
let success;
|
||||||
|
|
||||||
@ -66,9 +70,7 @@ pub fn write_console_output(
|
|||||||
buffer_size: COORD,
|
buffer_size: COORD,
|
||||||
buffer_coord: COORD,
|
buffer_coord: COORD,
|
||||||
source_buffer: PSMALL_RECT,
|
source_buffer: PSMALL_RECT,
|
||||||
) {
|
) -> Result<()> {
|
||||||
use self::wincon::WriteConsoleOutputA;
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
if !kernel::is_true(
|
if !kernel::is_true(
|
||||||
WriteConsoleOutputA(
|
WriteConsoleOutputA(
|
||||||
@ -79,27 +81,34 @@ pub fn write_console_output(
|
|||||||
source_buffer,
|
source_buffer,
|
||||||
), // screen buffer source rectangle
|
), // 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;
|
Ok(())
|
||||||
use std::str;
|
}
|
||||||
|
|
||||||
/// Write utf8 buffer to console.
|
/// Write utf8 buffer to console.
|
||||||
pub fn write_char_buffer(handle: &HANDLE, buf: &[u8]) -> ::std::io::Result<usize> {
|
pub fn write_char_buffer(handle: &HANDLE, buf: &[u8]) -> ::std::io::Result<usize> {
|
||||||
// get string from u8[] and parse it to an c_str
|
// get string from u8[] and parse it to an c_str
|
||||||
let mut utf8 = match str::from_utf8(buf) {
|
let mut utf8 = match str::from_utf8(buf) {
|
||||||
Ok(string) => string,
|
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: Vec<u16> = utf8.encode_utf16().collect();
|
||||||
let utf16_ptr: *const c_void = utf16.as_ptr() as *const _ as *const c_void;
|
let utf16_ptr: *const c_void = utf16.as_ptr() as *const _ as *const c_void;
|
||||||
|
|
||||||
// get buffer info
|
// 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
|
// get current position
|
||||||
let current_pos = COORD {
|
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 cells_written: u32 = 0;
|
||||||
|
|
||||||
let mut success = false;
|
let mut success = false;
|
||||||
// write to console
|
// write to console
|
||||||
unsafe {
|
unsafe {
|
||||||
@ -121,10 +129,9 @@ pub fn write_char_buffer(handle: &HANDLE, buf: &[u8]) -> ::std::io::Result<usize
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
match success
|
match success {
|
||||||
{
|
// think this is wrong could be done better!
|
||||||
// think this is wrong could be done better!
|
true => Ok(utf8.as_bytes().len()),
|
||||||
true => Ok(utf8.as_bytes().len()),
|
false => Ok(0),
|
||||||
false => Ok(0)
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@ -9,15 +9,15 @@ mod kernel;
|
|||||||
mod state;
|
mod state;
|
||||||
|
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
|
pub mod input;
|
||||||
pub mod manager;
|
pub mod manager;
|
||||||
pub mod style;
|
pub mod style;
|
||||||
pub mod terminal;
|
pub mod terminal;
|
||||||
pub mod input;
|
|
||||||
|
|
||||||
pub use state::context::Context;
|
|
||||||
pub use shared::crossterm::Crossterm;
|
pub use shared::crossterm::Crossterm;
|
||||||
pub use shared::screen;
|
|
||||||
pub use shared::raw;
|
pub use shared::raw;
|
||||||
|
pub use shared::screen;
|
||||||
|
pub use state::context::Context;
|
||||||
|
|
||||||
use manager::ScreenManager;
|
use manager::ScreenManager;
|
||||||
use state::command_manager::CommandManager;
|
use state::command_manager::CommandManager;
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
//! This module uses the stdout to write to the console.
|
//! This module uses the stdout to write to the console.
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::io::{self, Write, Read };
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
use super::IScreenManager;
|
use super::IScreenManager;
|
||||||
|
|
||||||
pub struct AnsiScreenManager {
|
pub struct AnsiScreenManager {
|
||||||
pub is_alternate_screen: bool,
|
pub is_alternate_screen: bool,
|
||||||
output: Box<Write>,
|
output: Box<Write>,
|
||||||
input: Box<Read>
|
input: Box<Read>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IScreenManager for AnsiScreenManager {
|
impl IScreenManager for AnsiScreenManager {
|
||||||
@ -30,19 +30,19 @@ impl IScreenManager for AnsiScreenManager {
|
|||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn read_line(&mut self) -> io::Result<String>
|
// fn read_line(&mut self) -> io::Result<String>
|
||||||
// {
|
// {
|
||||||
// let mut rv = String::new();
|
// let mut rv = String::new();
|
||||||
// self.input.read_line(&mut rv)?;
|
// self.input.read_line(&mut rv)?;
|
||||||
// let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
// let len = rv.trim_right_matches(&['\r', '\n'][..]).len();
|
||||||
// rv.truncate(len);
|
// rv.truncate(len);
|
||||||
// Ok(rv)
|
// Ok(rv)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// fn read_char(&mut self) -> io::Result<String>
|
// fn read_char(&mut self) -> io::Result<String>
|
||||||
// {
|
// {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
self.output.write(buf)
|
self.output.write(buf)
|
||||||
|
@ -45,8 +45,7 @@ impl ScreenManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write an ANSI code as &str
|
/// 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)
|
self.screen_manager.write_str(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
use super::IScreenManager;
|
use super::IScreenManager;
|
||||||
|
use kernel::windows_kernel::{handle, kernel, writing};
|
||||||
use kernel::windows_kernel::kernel;
|
|
||||||
use kernel::windows_kernel::writing;
|
|
||||||
use winapi::um::wincon::ENABLE_PROCESSED_OUTPUT;
|
use winapi::um::wincon::ENABLE_PROCESSED_OUTPUT;
|
||||||
use winapi::um::winnt::HANDLE;
|
use winapi::um::winnt::HANDLE;
|
||||||
|
|
||||||
@ -20,13 +18,11 @@ impl IScreenManager for WinApiScreenManager {
|
|||||||
self.is_alternate_screen = is_alternate_screen;
|
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())
|
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())
|
self.write(string.as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,9 +47,9 @@ impl IScreenManager for WinApiScreenManager {
|
|||||||
impl WinApiScreenManager {
|
impl WinApiScreenManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
WinApiScreenManager {
|
WinApiScreenManager {
|
||||||
output: kernel::get_output_handle(),
|
output: handle::get_output_handle().unwrap(),
|
||||||
is_alternate_screen: false,
|
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 {
|
pub fn get_handle(&mut self) -> &HANDLE {
|
||||||
if self.is_alternate_screen {
|
if self.is_alternate_screen {
|
||||||
return &self.alternate_handle;
|
return &self.alternate_handle;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return &self.output;
|
return &self.output;
|
||||||
}
|
}
|
||||||
|
@ -22,20 +22,18 @@
|
|||||||
//! let cursor = crossterm.cursor();
|
//! let cursor = crossterm.cursor();
|
||||||
//! let terminal = crossterm.terminal();
|
//! let terminal = crossterm.terminal();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
use super::super::cursor;
|
use super::super::cursor;
|
||||||
|
use super::super::input::input;
|
||||||
use super::super::style;
|
use super::super::style;
|
||||||
use super::super::terminal::terminal;
|
use super::super::terminal::terminal;
|
||||||
use super::super::input::input;
|
|
||||||
|
|
||||||
use Context;
|
use Context;
|
||||||
|
|
||||||
|
use std::convert::From;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
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`.
|
/// 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.
|
/// You can better use `Crossterm` for accessing these modules.
|
||||||
@ -48,22 +46,21 @@ use std::convert::From;
|
|||||||
/// let cursor = crossterm.cursor();
|
/// let cursor = crossterm.cursor();
|
||||||
/// let terminal = crossterm.terminal();
|
/// let terminal = crossterm.terminal();
|
||||||
pub struct Crossterm {
|
pub struct Crossterm {
|
||||||
context: Rc<Context>
|
context: Rc<Context>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create `Crossterm` instance from `Context`
|
/// Create `Crossterm` instance from `Context`
|
||||||
impl From<Rc<Context>> for Crossterm
|
impl From<Rc<Context>> for Crossterm {
|
||||||
{
|
|
||||||
fn from(context: Rc<Context>) -> Self {
|
fn from(context: Rc<Context>) -> Self {
|
||||||
return Crossterm {
|
return Crossterm { context: context };
|
||||||
context: context
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crossterm {
|
impl Crossterm {
|
||||||
pub fn new() -> 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.
|
/// Get an Terminal implementation whereon terminal related actions can be performed.
|
||||||
@ -80,8 +77,7 @@ impl Crossterm {
|
|||||||
/// let mut terminal = crossterm.terminal();
|
/// let mut terminal = crossterm.terminal();
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn terminal(&self) -> terminal::Terminal
|
pub fn terminal(&self) -> terminal::Terminal {
|
||||||
{
|
|
||||||
return terminal::Terminal::new(self.context.clone());
|
return terminal::Terminal::new(self.context.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,9 +98,8 @@ impl Crossterm {
|
|||||||
/// cursor.goto(5,10);
|
/// cursor.goto(5,10);
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn cursor(&self) -> cursor::TerminalCursor
|
pub fn cursor(&self) -> cursor::TerminalCursor {
|
||||||
{
|
return cursor::TerminalCursor::new(self.context.clone());
|
||||||
return cursor::TerminalCursor::new(self.context.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get an Color implementation whereon color related actions can be performed.
|
/// Get an Color implementation whereon color related actions can be performed.
|
||||||
@ -123,13 +118,11 @@ impl Crossterm {
|
|||||||
/// let mut terminal_color = crossterm.color();
|
/// 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());
|
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());
|
return input::TerminalInput::new(self.context.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,8 +172,7 @@ impl Crossterm {
|
|||||||
/// crossterm.write("Some text \n Some text on new line.");
|
/// 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)
|
self.terminal().write(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +50,13 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
|
|||||||
let mut does_support = true;
|
let mut does_support = true;
|
||||||
|
|
||||||
if cfg!(target_os = "windows") {
|
if cfg!(target_os = "windows") {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
|
use kernel::windows_kernel::ansi_support::try_enable_ansi_support;
|
||||||
|
|
||||||
// Try to enable ansi on windows if not than use WINAPI.
|
// 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 {
|
if !does_support {
|
||||||
term = Some(winapi_impl);
|
term = Some(winapi_impl);
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,5 @@ pub mod crossterm;
|
|||||||
pub mod functions;
|
pub mod functions;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|
||||||
pub mod screen;
|
|
||||||
pub mod raw;
|
pub mod raw;
|
||||||
|
pub mod screen;
|
||||||
|
@ -29,6 +29,25 @@ pub struct RawTerminal {
|
|||||||
command_id: u16,
|
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.
|
/// Trait withs contains a method for switching into raw mode.
|
||||||
pub trait IntoRawMode: Write + Sized {
|
pub trait IntoRawMode: Write + Sized {
|
||||||
fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
|
fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
|
||||||
|
@ -87,9 +87,9 @@ use shared::functions;
|
|||||||
use state::commands::*;
|
use state::commands::*;
|
||||||
use Context;
|
use Context;
|
||||||
|
|
||||||
|
use std::convert::From;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::convert::From;
|
|
||||||
|
|
||||||
pub struct AlternateScreen {
|
pub struct AlternateScreen {
|
||||||
context: Rc<Context>,
|
context: Rc<Context>,
|
||||||
@ -167,8 +167,7 @@ impl Drop for AlternateScreen {
|
|||||||
|
|
||||||
use super::super::shared::crossterm::Crossterm;
|
use super::super::shared::crossterm::Crossterm;
|
||||||
|
|
||||||
impl From<Crossterm> for AlternateScreen
|
impl From<Crossterm> for AlternateScreen {
|
||||||
{
|
|
||||||
fn from(crossterm: Crossterm) -> Self {
|
fn from(crossterm: Crossterm) -> Self {
|
||||||
let command_id = get_to_alternate_screen_command(crossterm.context());
|
let command_id = get_to_alternate_screen_command(crossterm.context());
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use super::IStateCommand;
|
use super::IStateCommand;
|
||||||
use {Context, StateManager};
|
use {Context, StateManager};
|
||||||
|
|
||||||
use kernel::windows_kernel::{ansi_support, kernel};
|
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use winapi::shared::minwindef::DWORD;
|
use winapi::shared::minwindef::DWORD;
|
||||||
use winapi::um::wincon;
|
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() {
|
if ansi_support::has_been_tried_to_enable_ansi() && ansi_support::ansi_enabled() {
|
||||||
return ansi_support::windows_supportable();
|
return ansi_support::windows_supportable();
|
||||||
} else {
|
} else {
|
||||||
let output_handle = kernel::get_output_handle();
|
let output_handle = handle::get_output_handle().unwrap();
|
||||||
|
|
||||||
let mut dw_mode: DWORD = 0;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
||||||
@ -51,7 +51,7 @@ impl IStateCommand for EnableAnsiCommand {
|
|||||||
|
|
||||||
fn undo(&mut self) -> bool {
|
fn undo(&mut self) -> bool {
|
||||||
if ansi_support::ansi_enabled() {
|
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;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
||||||
@ -96,7 +96,7 @@ impl EnableRawModeCommand {
|
|||||||
|
|
||||||
impl IStateCommand for EnableRawModeCommand {
|
impl IStateCommand for EnableRawModeCommand {
|
||||||
fn execute(&mut self) -> bool {
|
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;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&input_handle, &mut dw_mode) {
|
if !kernel::get_console_mode(&input_handle, &mut dw_mode) {
|
||||||
@ -113,7 +113,7 @@ impl IStateCommand for EnableRawModeCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self) -> bool {
|
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;
|
let mut dw_mode: DWORD = 0;
|
||||||
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
|
||||||
@ -155,13 +155,13 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
|
|||||||
fn execute(&mut self) -> bool {
|
fn execute(&mut self) -> bool {
|
||||||
use super::super::super::manager::WinApiScreenManager;
|
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.
|
// 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.
|
// 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();
|
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
||||||
screen_manager.toggle_is_alternate_screen(true);
|
screen_manager.toggle_is_alternate_screen(true);
|
||||||
@ -180,8 +180,8 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn undo(&mut self) -> bool {
|
fn undo(&mut self) -> bool {
|
||||||
let handle = kernel::get_output_handle();
|
let handle = handle::get_output_handle().unwrap();
|
||||||
kernel::set_active_screen_buffer(handle);
|
csbi::set_active_screen_buffer(handle);
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
let mut screen_manager = self.context.screen_manager.lock().unwrap();
|
||||||
|
@ -48,16 +48,16 @@
|
|||||||
|
|
||||||
use {ScreenManager, StateManager};
|
use {ScreenManager, StateManager};
|
||||||
|
|
||||||
|
use std::marker::Sync;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Mutex;
|
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.
|
/// 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 struct Context {
|
||||||
pub screen_manager: Rc<Mutex<ScreenManager>>,
|
pub screen_manager: Rc<Mutex<ScreenManager>>,
|
||||||
pub state_manager: Mutex<StateManager>,
|
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
|
/// 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.
|
/// 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;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
/// This struct is an ansi implementation for color related actions.
|
/// This struct is an ansi implementation for color related actions.
|
||||||
pub struct AnsiColor
|
pub struct AnsiColor {
|
||||||
{
|
screen_manager: Rc<Mutex<ScreenManager>>,
|
||||||
screen_manager: Rc<Mutex<ScreenManager>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnsiColor {
|
impl AnsiColor {
|
||||||
@ -21,7 +20,7 @@ impl AnsiColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ITerminalColor for 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 mx_guard = &self.screen_manager;
|
||||||
let mut screen = mx_guard.lock().unwrap();
|
let mut screen = mx_guard.lock().unwrap();
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
use super::super::super::manager::WinApiScreenManager;
|
||||||
use super::super::{Color, ColorType};
|
use super::super::{Color, ColorType};
|
||||||
use super::ITerminalColor;
|
use super::ITerminalColor;
|
||||||
use kernel::windows_kernel::kernel;
|
use kernel::windows_kernel::{csbi, kernel};
|
||||||
use winapi::um::wincon;
|
use winapi::um::wincon;
|
||||||
use ScreenManager;
|
use ScreenManager;
|
||||||
use super::super::super::manager::WinApiScreenManager;
|
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
@ -25,7 +25,7 @@ impl ITerminalColor for WinApiColor {
|
|||||||
fn set_fg(&self, fg_color: Color) {
|
fn set_fg(&self, fg_color: Color) {
|
||||||
let color_value = &self.color_value(fg_color, ColorType::Foreground);
|
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.
|
// 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.
|
// 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) {
|
fn set_bg(&self, bg_color: Color) {
|
||||||
let color_value = &self.color_value(bg_color, ColorType::Background);
|
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.
|
// 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.
|
// 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 {
|
impl ObjectStyle {
|
||||||
/// Apply an `StyledObject` to the passed displayable object.
|
/// 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 {
|
StyledObject {
|
||||||
object_style: self.clone(),
|
object_style: self.clone(),
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use Context;
|
use Context;
|
||||||
|
|
||||||
use std::fmt::{self,Display};
|
use std::fmt::{self, Display};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ pub struct StyledObject<D: Display> {
|
|||||||
pub context: Rc<Context>,
|
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`
|
/// Set the foreground of the styled object to the passed `Color`
|
||||||
///
|
///
|
||||||
/// #Example
|
/// #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> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
|
||||||
let mut colored_terminal = super::super::color(&self.context);
|
let mut colored_terminal = super::super::color(&self.context);
|
||||||
let mut reset = true;
|
let mut reset = true;
|
||||||
|
|
||||||
@ -164,7 +162,7 @@ impl <D:Display> Display for StyledObject<D>
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[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 mutex = &self.context.screen_manager;
|
||||||
{
|
{
|
||||||
let mut screen = mutex.lock().unwrap();
|
let mut screen = mutex.lock().unwrap();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
//! This is an `ANSI escape code` specific implementation for terminal related action.
|
//! 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.
|
//! 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::super::cursor::cursor;
|
||||||
|
use super::{ClearType, ITerminal, Rc};
|
||||||
use shared::functions;
|
use shared::functions;
|
||||||
use Context;
|
use Context;
|
||||||
|
|
||||||
@ -48,7 +48,6 @@ impl ITerminal for AnsiTerminal {
|
|||||||
fn scroll_up(&self, count: i16) {
|
fn scroll_up(&self, count: i16) {
|
||||||
let mut screen = self.context.screen_manager.lock().unwrap();
|
let mut screen = self.context.screen_manager.lock().unwrap();
|
||||||
{
|
{
|
||||||
panic!();
|
|
||||||
screen.write_string(format!(csi!("{}S"), count));
|
screen.write_string(format!(csi!("{}S"), count));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ impl Terminal {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
pub fn terminal_size(&self) -> (u16, u16) {
|
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.
|
/// 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())
|
style::ObjectStyle::new().apply_to(val, self.context.clone())
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use super::super::shared::functions;
|
|||||||
use super::super::ScreenManager;
|
use super::super::ScreenManager;
|
||||||
use super::{ClearType, ITerminal, Rc};
|
use super::{ClearType, ITerminal, Rc};
|
||||||
use cursor::cursor;
|
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 winapi::um::wincon::{CONSOLE_SCREEN_BUFFER_INFO, COORD, SMALL_RECT};
|
||||||
use Context;
|
use Context;
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ impl WinApiTerminal {
|
|||||||
|
|
||||||
impl ITerminal for WinApiTerminal {
|
impl ITerminal for WinApiTerminal {
|
||||||
fn clear(&self, clear_type: ClearType) {
|
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();
|
let pos = cursor(&self.context).pos();
|
||||||
|
|
||||||
match clear_type {
|
match clear_type {
|
||||||
@ -41,18 +41,18 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_up(&self, count: i16) {
|
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.
|
// Set srctWindow to the current window size and location.
|
||||||
let mut srct_window = csbi.srWindow;
|
let mut srct_window = csbi.srWindow;
|
||||||
|
|
||||||
|
|
||||||
// Check whether the window is too close to the screen buffer top
|
// Check whether the window is too close to the screen buffer top
|
||||||
if srct_window.Top >= count {
|
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
|
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 {
|
if success {
|
||||||
panic!("Something went wrong when scrolling down");
|
panic!("Something went wrong when scrolling down");
|
||||||
}
|
}
|
||||||
@ -60,20 +60,22 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn scroll_down(&self, count: i16) {
|
fn scroll_down(&self, count: i16) {
|
||||||
|
let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();
|
||||||
let csbi = kernel::get_console_screen_buffer_info(&self.context.screen_manager);
|
|
||||||
// Set srctWindow to the current window size and location.
|
// Set srctWindow to the current window size and location.
|
||||||
let mut srct_window = csbi.srWindow;
|
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
|
// Check whether the window is too close to the screen buffer top
|
||||||
if srct_window.Bottom < csbi.dwSize.Y - count {
|
if srct_window.Bottom < csbi.dwSize.Y - count {
|
||||||
srct_window.Top += count; // move top down
|
srct_window.Top += count; // move top down
|
||||||
srct_window.Bottom += count; // move bottom 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 {
|
if success {
|
||||||
panic!("Something went wrong when scrolling down");
|
panic!("Something went wrong when scrolling down");
|
||||||
}
|
}
|
||||||
@ -91,7 +93,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the position of the current console window
|
// 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;
|
let mut success = false;
|
||||||
|
|
||||||
// If the buffer is smaller than this new window size, resize the
|
// If the buffer is smaller than this new window size, resize the
|
||||||
@ -120,7 +122,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resize_buffer {
|
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 {
|
if !success {
|
||||||
panic!("Something went wrong when setting screen buffer size.");
|
panic!("Something went wrong when setting screen buffer size.");
|
||||||
@ -137,7 +139,7 @@ impl ITerminal for WinApiTerminal {
|
|||||||
if success {
|
if success {
|
||||||
// If we resized the buffer, un-resize it.
|
// If we resized the buffer, un-resize it.
|
||||||
if resize_buffer {
|
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();
|
let bounds = kernel::get_largest_console_window_size();
|
||||||
|
Loading…
Reference in New Issue
Block a user