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