From d38f406dc7e2704b5eed5f1e3625c9da78e0834d Mon Sep 17 00:00:00 2001 From: TimonPost Date: Tue, 24 Jul 2018 18:06:17 +0200 Subject: [PATCH] Refactored WinApi code --- examples/Crossterm 0.3.1/bin.rs | 48 ++++++++++++-------------- src/cursor/ansi_cursor.rs | 5 +++ src/cursor/cursor.rs | 7 +++- src/cursor/mod.rs | 3 ++ src/cursor/winapi_cursor.rs | 5 +++ src/input/windows_input.rs | 49 ++++++++++++++++++++++----- src/kernel/windows_kernel/cursor.rs | 24 ++++++++++--- src/kernel/windows_kernel/kernel.rs | 24 ++++--------- src/kernel/windows_kernel/mod.rs | 1 - src/kernel/windows_kernel/terminal.rs | 21 ++++++++++-- src/manager/ansi_manager.rs | 20 +++++++++-- src/manager/manager.rs | 18 ++++++++-- src/manager/mod.rs | 8 +++-- src/manager/win_manager.rs | 22 +++++++++--- src/shared/functions.rs | 14 ++++++-- src/shared/raw.rs | 36 +++++++++++++++----- src/shared/screen.rs | 29 ++++++---------- src/state/commands/shared_commands.rs | 2 -- src/state/commands/win_commands.rs | 28 +++++++-------- src/terminal/ansi_terminal.rs | 2 ++ src/terminal/mod.rs | 4 +++ src/terminal/terminal.rs | 4 +++ src/terminal/winapi_terminal.rs | 2 ++ 23 files changed, 255 insertions(+), 121 deletions(-) diff --git a/examples/Crossterm 0.3.1/bin.rs b/examples/Crossterm 0.3.1/bin.rs index 8932d32..a66119e 100644 --- a/examples/Crossterm 0.3.1/bin.rs +++ b/examples/Crossterm 0.3.1/bin.rs @@ -45,6 +45,12 @@ fn main() { use crossterm::raw::RawTerminal; use crossterm::Crossterm; + +use crossterm::cursor::cursor::TerminalCursor; +use crossterm::terminal::terminal::Terminal; +use crossterm::terminal::ClearType; +use std::io::Read; + pub fn crossterm() { let crossterm = Crossterm::new(); let mut term = crossterm.terminal(); @@ -57,27 +63,30 @@ pub fn crossterm() { let mut raw_screen = RawTerminal::new(&crossterm.context()); 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 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 { 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(); - let (cursor_x, cursor_y) = cursor.pos(); - - if cursor_y >= term_height { + if (curs_y >= term_y - 1 ) + { + cursor.goto(0, counter + 1); + term.clear(ClearType::CurrentLine); + cursor.goto(0, counter + 2); + term.write(format!("> {}", buf)); 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 { @@ -92,19 +101,4 @@ pub fn crossterm() { 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); -// -// -// -// -//} +} \ No newline at end of file diff --git a/src/cursor/ansi_cursor.rs b/src/cursor/ansi_cursor.rs index 79c6284..7f50a06 100644 --- a/src/cursor/ansi_cursor.rs +++ b/src/cursor/ansi_cursor.rs @@ -29,6 +29,11 @@ impl ITerminalCursor for AnsiCursor { 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) { let mut screen = self.context.screen_manager.lock().unwrap(); { diff --git a/src/cursor/cursor.rs b/src/cursor/cursor.rs index 8f501e0..963c6e6 100644 --- a/src/cursor/cursor.rs +++ b/src/cursor/cursor.rs @@ -82,10 +82,15 @@ impl TerminalCursor { /// } /// /// ``` - pub fn pos(&mut self) -> (u16, u16) { + pub fn pos(&self) -> (u16, u16) { self.terminal_cursor.pos() } + pub fn absolute_pos(&self) -> (u16, u16) + { + self.terminal_cursor.absolute_pos() + } + /// Move the current cursor position `n` times up. /// /// #Example diff --git a/src/cursor/mod.rs b/src/cursor/mod.rs index 6285902..941799d 100644 --- a/src/cursor/mod.rs +++ b/src/cursor/mod.rs @@ -34,6 +34,9 @@ pub trait ITerminalCursor { fn goto(&self, x: u16, y: u16); /// Get the location (x,y) of the current cusror in the context fn pos(&self) -> (u16, u16); + + fn absolute_pos(&self) -> (u16, u16); + /// Move cursor n times up fn move_up(&self, count: u16); /// Move the cursor `n` times to the right. diff --git a/src/cursor/winapi_cursor.rs b/src/cursor/winapi_cursor.rs index 0488306..689d72e 100644 --- a/src/cursor/winapi_cursor.rs +++ b/src/cursor/winapi_cursor.rs @@ -29,6 +29,11 @@ impl ITerminalCursor for WinApiCursor { cursor::pos(&self.screen_manager) } + fn absolute_pos(&self) -> (u16, u16) + { + cursor::absolute_cursor_pos(&self.screen_manager) + } + fn move_up(&self, count: u16) { let (xpos, ypos) = self.pos(); self.goto(xpos, ypos - count); diff --git a/src/input/windows_input.rs b/src/input/windows_input.rs index 392ae50..ba983ba 100644 --- a/src/input/windows_input.rs +++ b/src/input/windows_input.rs @@ -33,7 +33,15 @@ impl ITerminalInput for WindowsInput { let mut chars: Vec = Vec::new(); 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 pressed_char != 0 || pressed_char != 0xe0 { @@ -45,9 +53,7 @@ impl ITerminalInput for WindowsInput { chars.push(c); } - if self.display_input { - term.write(c); - } + } None => panic!("Some error needs to be returned"), }; @@ -60,7 +66,15 @@ impl ITerminalInput for WindowsInput { fn read_char(&self) -> io::Result { 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. if pressed_char == 0 || pressed_char == 0xe0 { @@ -111,9 +125,19 @@ impl ITerminalInput for WindowsInput { fn read_async(&self) -> AsyncReader { 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 || { 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. if pressed_char == 0 || pressed_char == 0xe0 { @@ -134,9 +158,17 @@ impl ITerminalInput for WindowsInput { fn read_until_async(&self, delimiter: u8) -> AsyncReader { 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 || { 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); @@ -153,6 +185,7 @@ impl ITerminalInput for WindowsInput { } } + fn is_line_end(key: char) -> bool { if key as u8 == 13 { return true; @@ -212,6 +245,6 @@ fn key_from_key_code(code: INT) -> Key { } extern "C" { + fn _getwche() -> INT; fn _getwch() -> INT; - fn _getwch_nolock() -> INT; } diff --git a/src/kernel/windows_kernel/cursor.rs b/src/kernel/windows_kernel/cursor.rs index 5a5014d..2cc7e92 100644 --- a/src/kernel/windows_kernel/cursor.rs +++ b/src/kernel/windows_kernel/cursor.rs @@ -37,16 +37,30 @@ pub fn save_cursor_pos(screen_manager: &Rc>) { /// get the current cursor position. pub fn pos(screen_manager: &Rc>) -> (u16, u16) { - if let Ok(csbi) = csbi::get_csbi(screen_manager) { - ( - csbi.dwCursorPosition.X as u16, - csbi.dwCursorPosition.Y as u16, - ) + + let handle = handle::get_output_handle().unwrap(); + + if let Ok(csbi) = csbi::get_csbi_by_handle(&handle) { + ( csbi.dwCursorPosition.X as u16, csbi.dwCursorPosition.Y as u16 ) } else { (0, 0) } } +pub fn absolute_cursor_pos(screen_manager: &Rc>) -> (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. pub fn set_console_cursor_position(x: i16, y: i16, screen_manager: &Rc>) { if x < 0 || x >= ::max_value() { diff --git a/src/kernel/windows_kernel/kernel.rs b/src/kernel/windows_kernel/kernel.rs index 343925d..fb8257f 100644 --- a/src/kernel/windows_kernel/kernel.rs +++ b/src/kernel/windows_kernel/kernel.rs @@ -1,31 +1,19 @@ //! 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. -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::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::wincon::{ + SetConsoleTextAttribute, SetConsoleWindowInfo, GetLargestConsoleWindowSize, + COORD, SMALL_RECT +}; use super::{handle, Empty}; +use super::super::super::manager::ScreenManager; -use super::super::super::manager::{ScreenManager, WinApiScreenManager}; use std::io::{ErrorKind, Result}; use std::sync::Mutex; +use std::rc::Rc; /// Get the largest console window size possible. pub fn get_largest_console_window_size() -> COORD { diff --git a/src/kernel/windows_kernel/mod.rs b/src/kernel/windows_kernel/mod.rs index 4ca20fd..a54d772 100644 --- a/src/kernel/windows_kernel/mod.rs +++ b/src/kernel/windows_kernel/mod.rs @@ -5,7 +5,6 @@ pub mod cursor; pub mod kernel; pub mod terminal; pub mod writing; -//pub mod reading; pub mod csbi; pub mod handle; diff --git a/src/kernel/windows_kernel/terminal.rs b/src/kernel/windows_kernel/terminal.rs index c534750..8f100a2 100644 --- a/src/kernel/windows_kernel/terminal.rs +++ b/src/kernel/windows_kernel/terminal.rs @@ -2,11 +2,14 @@ use std::rc::Rc; use std::sync::Mutex; use ScreenManager; -use super::csbi; +use super::{csbi, handle}; /// Get the terminal size pub fn terminal_size(screen_manager: &Rc>) -> (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.Bottom - csbi.srWindow.Top) as u16, @@ -16,6 +19,20 @@ pub fn terminal_size(screen_manager: &Rc>) -> (u16, u16) { } } +pub fn buffer_size(screen_manager: &Rc>) -> (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. pub fn exit() { ::std::process::exit(256); diff --git a/src/manager/ansi_manager.rs b/src/manager/ansi_manager.rs index 1e63bed..4ea1265 100644 --- a/src/manager/ansi_manager.rs +++ b/src/manager/ansi_manager.rs @@ -8,14 +8,27 @@ use std::io::{self, Read, Write}; use super::IScreenManager; pub struct AnsiScreenManager { - pub is_alternate_screen: bool, + is_alternate_screen: bool, + is_raw_screen: bool, output: Box, input: Box, } impl IScreenManager for AnsiScreenManager { - 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 { @@ -63,6 +76,7 @@ impl AnsiScreenManager { input: (Box::from(io::stdin()) as Box), output: (Box::from(io::stdout()) as Box), is_alternate_screen: false, + is_raw_screen: false, } } } diff --git a/src/manager/manager.rs b/src/manager/manager.rs index 76650d9..29de940 100644 --- a/src/manager/manager.rs +++ b/src/manager/manager.rs @@ -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. - pub fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool) { - self.screen_manager - .toggle_is_alternate_screen(is_alternate_screen); + pub fn set_is_alternate_screen(&mut self, value: bool) { + self.screen_manager.set_is_alternate_screen(value); + } + + 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. diff --git a/src/manager/mod.rs b/src/manager/mod.rs index 76f4014..d52aa91 100644 --- a/src/manager/mod.rs +++ b/src/manager/mod.rs @@ -33,8 +33,12 @@ use std::any::Any; use std::io; pub trait IScreenManager { - /// Toggle the value if alternatescreen is on. - fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool); + fn set_is_raw_screen(&mut self, value: 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. fn write_string(&mut self, string: String) -> io::Result; /// Write a &str to the current stdout. diff --git a/src/manager/win_manager.rs b/src/manager/win_manager.rs index c1014d0..f24d311 100644 --- a/src/manager/win_manager.rs +++ b/src/manager/win_manager.rs @@ -8,15 +8,29 @@ use std::io::{self, Write}; use std::rc::Rc; pub struct WinApiScreenManager { - pub is_alternate_screen: bool, + is_alternate_screen: bool, + is_raw_screen: bool, output: HANDLE, alternate_handle: HANDLE, } 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 { self.write(string.as_bytes()) @@ -49,6 +63,7 @@ impl WinApiScreenManager { WinApiScreenManager { output: handle::get_output_handle().unwrap(), is_alternate_screen: false, + is_raw_screen: false, alternate_handle: handle::get_output_handle().unwrap(), } } @@ -56,7 +71,6 @@ impl WinApiScreenManager { /// Set the alternate handle to the given handle. pub fn set_alternate_handle(&mut self, alternate_handle: HANDLE) { self.alternate_handle = alternate_handle; - // 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); } diff --git a/src/shared/functions.rs b/src/shared/functions.rs index c4f945f..f7d2034 100644 --- a/src/shared/functions.rs +++ b/src/shared/functions.rs @@ -6,10 +6,10 @@ use Context; use ScreenManager; #[cfg(windows)] -use kernel::windows_kernel::terminal::{exit, terminal_size}; +use kernel::windows_kernel::terminal::{exit, terminal_size, buffer_size}; #[cfg(windows)] -use kernel::windows_kernel::cursor::pos; +use kernel::windows_kernel::cursor::{pos, absolute_cursor_pos}; #[cfg(unix)] use kernel::unix_kernel::terminal::{exit, pos, terminal_size}; @@ -32,6 +32,16 @@ pub fn get_cursor_position(context: Rc) -> (u16, u16) { return pos(&context.screen_manager); } +pub fn get_buffer_size(context: &Rc) -> (u16, u16) +{ + return buffer_size(&context.screen_manager); +} + +pub fn get_absolute_cursor_pos(context: &Rc) -> (u16, u16) +{ + return absolute_cursor_pos(&context.screen_manager); +} + /// exit the current terminal. pub fn exit_terminal() { #[cfg(unix)] diff --git a/src/shared/raw.rs b/src/shared/raw.rs index 13365cf..54acd08 100644 --- a/src/shared/raw.rs +++ b/src/shared/raw.rs @@ -40,10 +40,22 @@ impl RawTerminal { } 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) } 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) } } @@ -60,16 +72,22 @@ impl IntoRawMode for W { fn into_raw_mode(&self, context: Rc) -> io::Result { let command_id = EnableRawModeCommand::new(&context.state_manager); - let success = CommandManager::execute(context.clone(), command_id); - - if success { - Ok(RawTerminal { - context: context.clone(), - command_id: command_id, - }) - } else { - panic!("cannot move into raw mode") + { + let mutex = &context.screen_manager; + let mut screen = mutex.lock().unwrap(); + screen.set_is_raw_screen(true); } + + 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.")) } } diff --git a/src/shared/screen.rs b/src/shared/screen.rs index ee8d61d..edd1617 100644 --- a/src/shared/screen.rs +++ b/src/shared/screen.rs @@ -85,7 +85,7 @@ use shared::functions; use state::commands::*; -use Context; +use {CommandManager, Context}; use std::convert::From; use std::io::{self, Write}; @@ -109,36 +109,29 @@ impl AlternateScreen { }; screen.to_alternate(); + return screen; } /// Change the current screen to the mainscreen. pub fn to_main(&self) { - let mut mutex = &self.context.state_manager; { - let mut state_manager = mutex.lock().unwrap(); - - let mut mx = &state_manager.get(self.command_id); - { - let mut command = mx.lock().unwrap(); - command.undo(); - } + let mutex = &self.context.screen_manager; + let mut screen = mutex.lock().unwrap(); + screen.set_is_alternate_screen(false); } + + CommandManager::undo(self.context.clone(), self.command_id); } /// Change the current screen to alternate screen. pub fn to_alternate(&self) { - let mut mutex = &self.context.state_manager; { - let mut state_manager = mutex.lock().unwrap(); - - let mut mx = &state_manager.get(self.command_id); - { - let mut command = mx.lock().unwrap(); - - command.execute(); - } + let mutex = &self.context.screen_manager; + let mut screen = mutex.lock().unwrap(); + screen.set_is_alternate_screen(true); } + CommandManager::execute(self.context.clone(), self.command_id); } } diff --git a/src/state/commands/shared_commands.rs b/src/state/commands/shared_commands.rs index f7ed7ae..924f8bd 100644 --- a/src/state/commands/shared_commands.rs +++ b/src/state/commands/shared_commands.rs @@ -41,7 +41,6 @@ impl IStateCommand for ToAlternateScreenBufferCommand { let mut screen = self.context.screen_manager.lock().unwrap(); { screen.write_str(csi!("?1049h")); - screen.toggle_is_alternate_screen(true); return true; } } @@ -50,7 +49,6 @@ impl IStateCommand for ToAlternateScreenBufferCommand { let mut screen = self.context.screen_manager.lock().unwrap(); { screen.write_str(csi!("?1049l")); - screen.toggle_is_alternate_screen(false); return true; } } diff --git a/src/state/commands/win_commands.rs b/src/state/commands/win_commands.rs index acef0e7..7cb4e14 100644 --- a/src/state/commands/win_commands.rs +++ b/src/state/commands/win_commands.rs @@ -163,19 +163,20 @@ impl IStateCommand for ToAlternateScreenBufferCommand { // Make the new screen buffer the active screen buffer. 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::() { - Some(b) => b, - None => panic!(""), - }; + let mutex = &self.context.screen_manager; + let mut screen = mutex.lock().unwrap(); - b.set_alternate_handle(new_handle); + let b: &mut WinApiScreenManager = match screen + .as_any() + .downcast_mut::() + { + Some(b) => b, + None => panic!(""), + }; + b.set_alternate_handle(new_handle); + } true } @@ -183,11 +184,6 @@ impl IStateCommand for ToAlternateScreenBufferCommand { let handle = handle::get_output_handle().unwrap(); csbi::set_active_screen_buffer(handle); - { - let mut screen_manager = self.context.screen_manager.lock().unwrap(); - screen_manager.toggle_is_alternate_screen(false); - } - - true + true } } diff --git a/src/terminal/ansi_terminal.rs b/src/terminal/ansi_terminal.rs index ff6dc41..1063ad9 100644 --- a/src/terminal/ansi_terminal.rs +++ b/src/terminal/ansi_terminal.rs @@ -45,6 +45,8 @@ impl ITerminal for AnsiTerminal { 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) { let mut screen = self.context.screen_manager.lock().unwrap(); { diff --git a/src/terminal/mod.rs b/src/terminal/mod.rs index 47ee25b..0662b95 100644 --- a/src/terminal/mod.rs +++ b/src/terminal/mod.rs @@ -42,6 +42,10 @@ pub trait ITerminal { fn clear(&self, clear_type: ClearType); /// Get the terminal size (x,y) 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. fn scroll_up(&self, count: i16); /// Scroll `n` lines down in the current terminal. diff --git a/src/terminal/terminal.rs b/src/terminal/terminal.rs index 240659f..33c6248 100644 --- a/src/terminal/terminal.rs +++ b/src/terminal/terminal.rs @@ -85,6 +85,10 @@ impl Terminal { 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. /// /// #Example diff --git a/src/terminal/winapi_terminal.rs b/src/terminal/winapi_terminal.rs index 77171f0..aae70fb 100644 --- a/src/terminal/winapi_terminal.rs +++ b/src/terminal/winapi_terminal.rs @@ -40,6 +40,8 @@ impl ITerminal for WinApiTerminal { 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) { let csbi = csbi::get_csbi(&self.context.screen_manager).unwrap();