refactored winapi code

This commit is contained in:
TimonPost 2018-07-22 14:55:14 +02:00
parent 9df976ed29
commit 2cc40d5d28
40 changed files with 777 additions and 703 deletions

View File

@ -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);
//
//
//
//
//}

View File

@ -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 {

View File

@ -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),
} }
} }

View File

@ -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;

View File

@ -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) {}

View File

@ -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()));
} }

View File

@ -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 {

View File

@ -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 || {
for i in get_tty().unwrap().bytes() {
if send.send(i).is_err() { if send.send(i).is_err() {
return; 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 { match i {
Ok(byte) => { Ok(byte) => {
let end_of_stream = &byte == &delimiter; let end_of_stream = &byte == &delimiter;
let send_error = send.send(Ok(byte)).is_err(); let send_error = send.send(Ok(byte)).is_err();
if end_of_stream || send_error { return; } if end_of_stream || send_error {
}, return;
Err(_) => { return; } }
}
Err(_) => {
return;
}
}
} }
}); });
AsyncReader { recv: recv } AsyncReader { recv: recv }
} }
} }

View File

@ -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,62 +57,62 @@ 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.
@ -125,8 +122,7 @@ impl ITerminalInput for WindowsInput
tx.send(Ok(pressed_char as u8)); tx.send(Ok(pressed_char as u8));
if pressed_char == 13 if pressed_char == 13 {
{
return; return;
} }
} }
@ -135,13 +131,11 @@ impl ITerminalInput for WindowsInput
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,

View File

@ -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,21 +138,20 @@ 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 libc::STDIN_FILENO
} else { } else {
tty_f = fs::File::open("/dev/tty")?; tty_f = fs::File::open("/dev/tty")?;
@ -160,7 +159,6 @@ pub fn read_char() -> io::Result<char>
} }
}; };
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 { } else {
pressed_char = Err(io::Error::new(io::ErrorKind::Interrupted, "Could not parse char to utf8 char")); pressed_char = Err(io::Error::new(
io::ErrorKind::Interrupted,
"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);
}
} }
} }

View File

@ -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;
} }
} }

View 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(())
}

View File

@ -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(())
} }

View 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
}
}

View File

@ -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
//}

View File

@ -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;

View File

@ -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");
}
}
}

View File

@ -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.

View File

@ -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),
} }
} }

View File

@ -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;

View File

@ -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)

View File

@ -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)
} }

View File

@ -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;
} }

View File

@ -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)
} }

View File

@ -54,9 +54,9 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
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);
} }

View File

@ -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;

View File

@ -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>;

View File

@ -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());

View File

@ -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();

View File

@ -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.

View File

@ -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();

View File

@ -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.

View File

@ -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,

View File

@ -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;

View File

@ -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));
} }
} }

View File

@ -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())
} }

View File

@ -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();