Refactored WinApi code

This commit is contained in:
TimonPost 2018-07-24 18:06:17 +02:00
parent 2cc40d5d28
commit d38f406dc7
23 changed files with 255 additions and 121 deletions

View File

@ -45,6 +45,12 @@ fn main() {
use crossterm::raw::RawTerminal; use crossterm::raw::RawTerminal;
use crossterm::Crossterm; use crossterm::Crossterm;
use crossterm::cursor::cursor::TerminalCursor;
use crossterm::terminal::terminal::Terminal;
use crossterm::terminal::ClearType;
use std::io::Read;
pub fn crossterm() { pub fn crossterm() {
let crossterm = Crossterm::new(); let crossterm = Crossterm::new();
let mut term = crossterm.terminal(); let mut term = crossterm.terminal();
@ -57,27 +63,30 @@ pub fn crossterm() {
let mut raw_screen = RawTerminal::new(&crossterm.context()); let mut raw_screen = RawTerminal::new(&crossterm.context());
raw_screen.enable(); raw_screen.enable();
let mut stdin = input.read_async().bytes(); let mut stdin = input.read_until_async().bytes();
let mut buf = String::new(); let mut buf = String::new();
let mut counter: u16 = 1; let (term_x, term_y) = term.terminal_size();
let mut command_bar_y = term_y;
let (curs_x, curs_y) = cursor.pos();
let mut counter: u16 = 0 + curs_y;
loop { loop {
cursor.goto(0, counter); cursor.goto(0, counter);
term.write("test data"); let (curs_x, curs_y) = cursor.pos();
term.write(format!("cursor pos {} term pos: {} command pos: {}", curs_y, term_y, command_bar_y));
cursor.goto(0, counter + 1);
let (term_width, term_height) = term.terminal_size(); if (curs_y >= term_y - 1 )
let (cursor_x, cursor_y) = cursor.pos(); {
cursor.goto(0, counter + 1);
if cursor_y >= term_height { term.clear(ClearType::CurrentLine);
cursor.goto(0, counter + 2);
term.write(format!("> {}", buf));
term.scroll_up(1); term.scroll_up(1);
} }
cursor.goto(0, term_height);
term.clear(ClearType::CurrentLine);
term.write(format!("> {}", buf));
while let Some(b) = stdin.next() { while let Some(b) = stdin.next() {
if let Ok(b) = b { if let Ok(b) = b {
if b == 3 { if b == 3 {
@ -93,18 +102,3 @@ pub fn crossterm() {
thread::sleep(time::Duration::from_millis(100)); 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

@ -29,6 +29,11 @@ impl ITerminalCursor for AnsiCursor {
functions::get_cursor_position(self.context.clone()) functions::get_cursor_position(self.context.clone())
} }
fn absolute_pos(&self) -> (u16, u16)
{
functions::get_absolute_cursor_pos(&self.context)
}
fn move_up(&self, count: u16) { fn move_up(&self, count: u16) {
let mut screen = self.context.screen_manager.lock().unwrap(); let mut screen = self.context.screen_manager.lock().unwrap();
{ {

View File

@ -82,10 +82,15 @@ impl TerminalCursor {
/// } /// }
/// ///
/// ``` /// ```
pub fn pos(&mut self) -> (u16, u16) { pub fn pos(&self) -> (u16, u16) {
self.terminal_cursor.pos() self.terminal_cursor.pos()
} }
pub fn absolute_pos(&self) -> (u16, u16)
{
self.terminal_cursor.absolute_pos()
}
/// Move the current cursor position `n` times up. /// Move the current cursor position `n` times up.
/// ///
/// #Example /// #Example

View File

@ -34,6 +34,9 @@ pub trait ITerminalCursor {
fn goto(&self, x: u16, y: u16); fn goto(&self, x: u16, y: u16);
/// Get the location (x,y) of the current cusror in the context /// Get the location (x,y) of the current cusror in the context
fn pos(&self) -> (u16, u16); fn pos(&self) -> (u16, u16);
fn absolute_pos(&self) -> (u16, u16);
/// Move cursor n times up /// Move cursor n times up
fn move_up(&self, count: u16); fn move_up(&self, count: u16);
/// Move the cursor `n` times to the right. /// Move the cursor `n` times to the right.

View File

@ -29,6 +29,11 @@ impl ITerminalCursor for WinApiCursor {
cursor::pos(&self.screen_manager) cursor::pos(&self.screen_manager)
} }
fn absolute_pos(&self) -> (u16, u16)
{
cursor::absolute_cursor_pos(&self.screen_manager)
}
fn move_up(&self, count: u16) { fn move_up(&self, count: u16) {
let (xpos, ypos) = self.pos(); let (xpos, ypos) = self.pos();
self.goto(xpos, ypos - count); self.goto(xpos, ypos - count);

View File

@ -33,7 +33,15 @@ impl ITerminalInput for WindowsInput {
let mut chars: Vec<char> = Vec::new(); let mut chars: Vec<char> = Vec::new();
loop { loop {
let pressed_char = unsafe { _getwch() }; let mut is_raw_screen = false;
{
let mutex = &self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
// _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } };
// 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 {
@ -45,9 +53,7 @@ impl ITerminalInput for WindowsInput {
chars.push(c); chars.push(c);
} }
if self.display_input {
term.write(c);
}
} }
None => panic!("Some error needs to be returned"), None => panic!("Some error needs to be returned"),
}; };
@ -60,7 +66,15 @@ impl ITerminalInput for WindowsInput {
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 mut is_raw_screen = false;
{
let mutex = &self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
// _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } };
// 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 {
@ -111,9 +125,19 @@ impl ITerminalInput for WindowsInput {
fn read_async(&self) -> AsyncReader { fn read_async(&self) -> AsyncReader {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let mut is_raw_screen = false;
{
let mutex = &self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
// panic!("is raw screen: {} ", is_raw_screen);
thread::spawn(move || { thread::spawn(move || {
loop { loop {
let pressed_char: u8 = (unsafe { _getwch() }) as u8;
// _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } };
// 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 {
@ -134,9 +158,17 @@ impl ITerminalInput for WindowsInput {
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();
let mut is_raw_screen = false;
{
let mutex =&self.context.screen_manager;
let screen = mutex.lock().unwrap();
is_raw_screen = screen.is_raw_screen();
}
thread::spawn(move || { thread::spawn(move || {
loop { loop {
let pressed_char: u8 = (unsafe { _getwch() }) as u8; // _getwch is without echo and _getwche is with echo
let pressed_char = unsafe { if is_raw_screen { _getwch() } else { _getwche() } } as u8;
let end_of_stream = (pressed_char == delimiter); let end_of_stream = (pressed_char == delimiter);
@ -153,6 +185,7 @@ 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;
@ -212,6 +245,6 @@ fn key_from_key_code(code: INT) -> Key {
} }
extern "C" { extern "C" {
fn _getwche() -> INT;
fn _getwch() -> INT; fn _getwch() -> INT;
fn _getwch_nolock() -> INT;
} }

View File

@ -37,16 +37,30 @@ 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) {
if let Ok(csbi) = csbi::get_csbi(screen_manager) {
( let handle = handle::get_output_handle().unwrap();
csbi.dwCursorPosition.X as u16,
csbi.dwCursorPosition.Y as u16, if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
) ( csbi.dwCursorPosition.X as u16, csbi.dwCursorPosition.Y as u16 )
} else { } else {
(0, 0) (0, 0)
} }
} }
pub fn absolute_cursor_pos(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
let handle = handle::get_output_handle().unwrap();
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
(
(csbi.dwMaximumWindowSize.X) as u16,
(csbi.dwMaximumWindowSize.Y) as u16,
)
} else {
return (0, 0);
}
}
/// Set the cursor position to the given x and y. Note that this is 0 based. /// 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>>) { pub fn set_console_cursor_position(x: i16, y: i16, screen_manager: &Rc<Mutex<ScreenManager>>) {
if x < 0 || x >= <i16>::max_value() { if x < 0 || x >= <i16>::max_value() {

View File

@ -1,31 +1,19 @@
//! This module is the core of all the `WINAPI` actions. All unsafe `WINAPI` function call are done here. //! This module is the core of all the `WINAPI` actions. All unsafe `WINAPI` function call are done here.
//! I am planing to refactor this a little since a lot of code could be handled safer. //! I am planing to refactor this a little since a lot of code could be handled safer.
use std::rc::Rc;
use Context;
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::consoleapi::{GetConsoleMode, SetConsoleMode};
use winapi::um::wincon;
use winapi::um::wincon::{
CreateConsoleScreenBuffer, FillConsoleOutputAttribute, FillConsoleOutputCharacterA,
GetConsoleScreenBufferInfo, GetLargestConsoleWindowSize, SetConsoleActiveScreenBuffer,
SetConsoleCursorInfo, SetConsoleCursorPosition, SetConsoleScreenBufferSize,
SetConsoleTextAttribute, SetConsoleWindowInfo, WriteConsoleOutputAttribute,
WriteConsoleOutputCharacterA, WriteConsoleOutputCharacterW, WriteConsoleOutputW, CHAR_INFO,
CONSOLE_CURSOR_INFO, CONSOLE_SCREEN_BUFFER_INFO, COORD, ENABLE_PROCESSED_INPUT, PSMALL_RECT,
SMALL_RECT,
};
use winapi::um::winnt::HANDLE; use winapi::um::winnt::HANDLE;
use winapi::um::wincon::{
SetConsoleTextAttribute, SetConsoleWindowInfo, GetLargestConsoleWindowSize,
COORD, SMALL_RECT
};
use super::{handle, Empty}; use super::{handle, Empty};
use super::super::super::manager::ScreenManager;
use super::super::super::manager::{ScreenManager, WinApiScreenManager};
use std::io::{ErrorKind, Result}; use std::io::{ErrorKind, Result};
use std::sync::Mutex; use std::sync::Mutex;
use std::rc::Rc;
/// 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 {

View File

@ -5,7 +5,6 @@ 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 csbi; pub mod csbi;
pub mod handle; pub mod handle;

View File

@ -2,11 +2,14 @@ use std::rc::Rc;
use std::sync::Mutex; use std::sync::Mutex;
use ScreenManager; use ScreenManager;
use super::csbi; use super::{csbi, handle};
/// 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) {
if let Ok(csbi) = csbi::get_csbi(screen_manager) {
let handle = handle::get_output_handle().unwrap();
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
( (
(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,
@ -16,6 +19,20 @@ pub fn terminal_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
} }
} }
pub fn buffer_size(screen_manager: &Rc<Mutex<ScreenManager>>) -> (u16, u16) {
let handle = handle::get_output_handle().unwrap();
if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) {
(
(csbi.dwSize.X) as u16,
(csbi.dwSize.Y) as u16,
)
} else {
return (0, 0);
}
}
/// Exit the current process. /// Exit the current process.
pub fn exit() { pub fn exit() {
::std::process::exit(256); ::std::process::exit(256);

View File

@ -8,14 +8,27 @@ use std::io::{self, Read, Write};
use super::IScreenManager; use super::IScreenManager;
pub struct AnsiScreenManager { pub struct AnsiScreenManager {
pub is_alternate_screen: bool, is_alternate_screen: bool,
is_raw_screen: bool,
output: Box<Write>, output: Box<Write>,
input: Box<Read>, input: Box<Read>,
} }
impl IScreenManager for AnsiScreenManager { impl IScreenManager for AnsiScreenManager {
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool) { fn set_is_raw_screen(&mut self, value: bool) {
self.is_alternate_screen = is_alternate_screen; self.is_raw_screen = value;
}
fn set_is_alternate_screen(&mut self, value: bool) {
self.is_alternate_screen = value;
}
fn is_raw_screen(&self) -> bool {
self.is_raw_screen
}
fn is_alternate_screen(&self) -> bool {
self.is_alternate_screen
} }
fn write_string(&mut self, string: String) -> io::Result<usize> { fn write_string(&mut self, string: String) -> io::Result<usize> {
@ -63,6 +76,7 @@ impl AnsiScreenManager {
input: (Box::from(io::stdin()) as Box<Read>), input: (Box::from(io::stdin()) as Box<Read>),
output: (Box::from(io::stdout()) as Box<Write>), output: (Box::from(io::stdout()) as Box<Write>),
is_alternate_screen: false, is_alternate_screen: false,
is_raw_screen: false,
} }
} }
} }

View File

@ -33,10 +33,22 @@ impl ScreenManager {
} }
} }
pub fn set_is_raw_screen(&mut self, value: bool) {
self.screen_manager.set_is_raw_screen(value);
}
/// Toggle a boolean to whether alternate screen is on or of. /// Toggle a boolean to whether alternate screen is on or of.
pub fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool) { pub fn set_is_alternate_screen(&mut self, value: bool) {
self.screen_manager self.screen_manager.set_is_alternate_screen(value);
.toggle_is_alternate_screen(is_alternate_screen); }
pub fn is_raw_screen(&self) -> bool {
self.screen_manager.is_raw_screen()
}
/// Toggle a boolean to whether alternate screen is on or of.
pub fn is_alternate_screen(&self) -> bool {
self.screen_manager.is_alternate_screen()
} }
/// Write an ANSI code as String. /// Write an ANSI code as String.

View File

@ -33,8 +33,12 @@ use std::any::Any;
use std::io; use std::io;
pub trait IScreenManager { pub trait IScreenManager {
/// Toggle the value if alternatescreen is on. fn set_is_raw_screen(&mut self, value: bool);
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool); fn set_is_alternate_screen(&mut self, value: bool);
fn is_raw_screen(&self) -> bool;
fn is_alternate_screen(&self) -> bool;
/// Write ansi code as String to the current stdout. /// Write ansi code as String to the current stdout.
fn write_string(&mut self, string: String) -> io::Result<usize>; fn write_string(&mut self, string: String) -> io::Result<usize>;
/// Write a &str to the current stdout. /// Write a &str to the current stdout.

View File

@ -8,15 +8,29 @@ use std::io::{self, Write};
use std::rc::Rc; use std::rc::Rc;
pub struct WinApiScreenManager { pub struct WinApiScreenManager {
pub is_alternate_screen: bool, is_alternate_screen: bool,
is_raw_screen: bool,
output: HANDLE, output: HANDLE,
alternate_handle: HANDLE, alternate_handle: HANDLE,
} }
impl IScreenManager for WinApiScreenManager { impl IScreenManager for WinApiScreenManager {
fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool) {
self.is_alternate_screen = is_alternate_screen; fn set_is_raw_screen(&mut self, value: bool) {
self.is_raw_screen = value;
} }
fn set_is_alternate_screen(&mut self, value: bool) {
self.is_alternate_screen = value;
}
fn is_raw_screen(&self) -> bool {
self.is_raw_screen
}
fn is_alternate_screen(&self) -> bool {
self.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())
@ -49,6 +63,7 @@ impl WinApiScreenManager {
WinApiScreenManager { WinApiScreenManager {
output: handle::get_output_handle().unwrap(), output: handle::get_output_handle().unwrap(),
is_alternate_screen: false, is_alternate_screen: false,
is_raw_screen: false,
alternate_handle: handle::get_output_handle().unwrap(), alternate_handle: handle::get_output_handle().unwrap(),
} }
} }
@ -56,7 +71,6 @@ impl WinApiScreenManager {
/// Set the alternate handle to the given handle. /// Set the alternate handle to the given handle.
pub fn set_alternate_handle(&mut self, alternate_handle: HANDLE) { pub fn set_alternate_handle(&mut self, alternate_handle: HANDLE) {
self.alternate_handle = alternate_handle; self.alternate_handle = alternate_handle;
// needs to be turned on so that escape characters like \n and \t will be processed. // needs to be turned on so that escape characters like \n and \t will be processed.
kernel::set_console_mode(&self.alternate_handle, ENABLE_PROCESSED_OUTPUT as u32); kernel::set_console_mode(&self.alternate_handle, ENABLE_PROCESSED_OUTPUT as u32);
} }

View File

@ -6,10 +6,10 @@ use Context;
use ScreenManager; use ScreenManager;
#[cfg(windows)] #[cfg(windows)]
use kernel::windows_kernel::terminal::{exit, terminal_size}; use kernel::windows_kernel::terminal::{exit, terminal_size, buffer_size};
#[cfg(windows)] #[cfg(windows)]
use kernel::windows_kernel::cursor::pos; use kernel::windows_kernel::cursor::{pos, absolute_cursor_pos};
#[cfg(unix)] #[cfg(unix)]
use kernel::unix_kernel::terminal::{exit, pos, terminal_size}; use kernel::unix_kernel::terminal::{exit, pos, terminal_size};
@ -32,6 +32,16 @@ pub fn get_cursor_position(context: Rc<Context>) -> (u16, u16) {
return pos(&context.screen_manager); return pos(&context.screen_manager);
} }
pub fn get_buffer_size(context: &Rc<Context>) -> (u16, u16)
{
return buffer_size(&context.screen_manager);
}
pub fn get_absolute_cursor_pos(context: &Rc<Context>) -> (u16, u16)
{
return absolute_cursor_pos(&context.screen_manager);
}
/// exit the current terminal. /// exit the current terminal.
pub fn exit_terminal() { pub fn exit_terminal() {
#[cfg(unix)] #[cfg(unix)]

View File

@ -40,10 +40,22 @@ impl RawTerminal {
} }
pub fn enable(&self) -> bool { pub fn enable(&self) -> bool {
{
let mutex = &self.context.screen_manager;
let mut screen = mutex.lock().unwrap();
screen.set_is_raw_screen(true);
}
CommandManager::execute(self.context.clone(), self.command_id) CommandManager::execute(self.context.clone(), self.command_id)
} }
pub fn disable(&self) -> bool { pub fn disable(&self) -> bool {
{
let mutex = &self.context.screen_manager;
let mut screen = mutex.lock().unwrap();
screen.set_is_raw_screen(false);
}
CommandManager::undo(self.context.clone(), self.command_id) CommandManager::undo(self.context.clone(), self.command_id)
} }
} }
@ -60,16 +72,22 @@ impl<W: Write> IntoRawMode for W {
fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal> { fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal> {
let command_id = EnableRawModeCommand::new(&context.state_manager); let command_id = EnableRawModeCommand::new(&context.state_manager);
let success = CommandManager::execute(context.clone(), command_id); {
let mutex = &context.screen_manager;
if success { let mut screen = mutex.lock().unwrap();
Ok(RawTerminal { screen.set_is_raw_screen(true);
context: context.clone(),
command_id: command_id,
})
} else {
panic!("cannot move into raw mode")
} }
let raw_terminal = RawTerminal {
context: context.clone(),
command_id: command_id,
};
if raw_terminal.enable()
{
return Ok(raw_terminal);
}
return Err(io::Error::new(io::ErrorKind::Other, "Could not enter raw mode."))
} }
} }

View File

@ -85,7 +85,7 @@
use shared::functions; use shared::functions;
use state::commands::*; use state::commands::*;
use Context; use {CommandManager, Context};
use std::convert::From; use std::convert::From;
use std::io::{self, Write}; use std::io::{self, Write};
@ -109,36 +109,29 @@ impl AlternateScreen {
}; };
screen.to_alternate(); screen.to_alternate();
return screen; return screen;
} }
/// Change the current screen to the mainscreen. /// Change the current screen to the mainscreen.
pub fn to_main(&self) { pub fn to_main(&self) {
let mut mutex = &self.context.state_manager;
{ {
let mut state_manager = mutex.lock().unwrap(); let mutex = &self.context.screen_manager;
let mut screen = mutex.lock().unwrap();
let mut mx = &state_manager.get(self.command_id); screen.set_is_alternate_screen(false);
{
let mut command = mx.lock().unwrap();
command.undo();
}
} }
CommandManager::undo(self.context.clone(), self.command_id);
} }
/// Change the current screen to alternate screen. /// Change the current screen to alternate screen.
pub fn to_alternate(&self) { pub fn to_alternate(&self) {
let mut mutex = &self.context.state_manager;
{ {
let mut state_manager = mutex.lock().unwrap(); let mutex = &self.context.screen_manager;
let mut screen = mutex.lock().unwrap();
let mut mx = &state_manager.get(self.command_id); screen.set_is_alternate_screen(true);
{
let mut command = mx.lock().unwrap();
command.execute();
}
} }
CommandManager::execute(self.context.clone(), self.command_id);
} }
} }

View File

@ -41,7 +41,6 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
let mut screen = self.context.screen_manager.lock().unwrap(); let mut screen = self.context.screen_manager.lock().unwrap();
{ {
screen.write_str(csi!("?1049h")); screen.write_str(csi!("?1049h"));
screen.toggle_is_alternate_screen(true);
return true; return true;
} }
} }
@ -50,7 +49,6 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
let mut screen = self.context.screen_manager.lock().unwrap(); let mut screen = self.context.screen_manager.lock().unwrap();
{ {
screen.write_str(csi!("?1049l")); screen.write_str(csi!("?1049l"));
screen.toggle_is_alternate_screen(false);
return true; return true;
} }
} }

View File

@ -163,19 +163,20 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
// Make the new screen buffer the active screen buffer. // Make the new screen buffer the active screen buffer.
csbi::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);
let b: &mut WinApiScreenManager = match screen_manager
.as_any()
.downcast_mut::<WinApiScreenManager>()
{ {
Some(b) => b, let mutex = &self.context.screen_manager;
None => panic!(""), let mut screen = mutex.lock().unwrap();
};
b.set_alternate_handle(new_handle); let b: &mut WinApiScreenManager = match screen
.as_any()
.downcast_mut::<WinApiScreenManager>()
{
Some(b) => b,
None => panic!(""),
};
b.set_alternate_handle(new_handle);
}
true true
} }
@ -183,11 +184,6 @@ impl IStateCommand for ToAlternateScreenBufferCommand {
let handle = handle::get_output_handle().unwrap(); let handle = handle::get_output_handle().unwrap();
csbi::set_active_screen_buffer(handle); csbi::set_active_screen_buffer(handle);
{ true
let mut screen_manager = self.context.screen_manager.lock().unwrap();
screen_manager.toggle_is_alternate_screen(false);
}
true
} }
} }

View File

@ -45,6 +45,8 @@ impl ITerminal for AnsiTerminal {
functions::get_terminal_size(&self.context.screen_manager) functions::get_terminal_size(&self.context.screen_manager)
} }
fn buffer_size(&self) -> (u16, u16) { functions::get_buffer_size(&self.context) }
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();
{ {

View File

@ -42,6 +42,10 @@ pub trait ITerminal {
fn clear(&self, clear_type: ClearType); fn clear(&self, clear_type: ClearType);
/// Get the terminal size (x,y) /// Get the terminal size (x,y)
fn terminal_size(&self) -> (u16, u16); fn terminal_size(&self) -> (u16, u16);
// get the size of the current buffer
fn buffer_size(&self) -> (u16, u16);
/// Scroll `n` lines up in the current terminal. /// Scroll `n` lines up in the current terminal.
fn scroll_up(&self, count: i16); fn scroll_up(&self, count: i16);
/// Scroll `n` lines down in the current terminal. /// Scroll `n` lines down in the current terminal.

View File

@ -85,6 +85,10 @@ impl Terminal {
return self.terminal.terminal_size(); return self.terminal.terminal_size();
} }
pub fn buffer_size(&self) -> (u16, u16) {
return self.terminal.buffer_size();
}
/// Scroll `n` lines up in the current terminal. /// Scroll `n` lines up in the current terminal.
/// ///
/// #Example /// #Example

View File

@ -40,6 +40,8 @@ impl ITerminal for WinApiTerminal {
terminal::terminal_size(&self.context.screen_manager) terminal::terminal_size(&self.context.screen_manager)
} }
fn buffer_size(&self) -> (u16, u16) {terminal::buffer_size(&self.context.screen_manager)}
fn scroll_up(&self, count: i16) { fn scroll_up(&self, count: i16) {
let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap(); let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();