This commit is contained in:
TimonPost 2018-07-27 18:44:38 +02:00
parent 1499763054
commit d7387ed227
13 changed files with 266 additions and 379 deletions

View File

@ -12,86 +12,17 @@
//! - Run program with: `cargo run`
extern crate crossterm;
use crossterm::Context;
use crossterm::Terminal;
// mod terminal;
// mod color;
// mod cursor;
// mod crossterm_type;
mod input;
// mod input;
use input::keyboard::{async_input, input as stdin};
use crossterm::raw::IntoRawMode;
//use input::keyboard::{async_input, input as stdin};
use std::{thread, time};
fn main() {
async_input::read_async_until();
}
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();
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 (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;
loop {
// cursor.goto(0, counter);
//
// 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);
//
// 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);
// }
//
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));
}
}

View File

@ -6,20 +6,20 @@
use super::super::shared::functions;
use super::*;
use std::io::Write;
use Context;
use {Context, ScreenManager};
use std::fmt::Display;
use std::rc::Rc;
/// Struct that stores an specific platform implementation for cursor related actions.
pub struct TerminalCursor {
context: Rc<Context>,
pub struct TerminalCursor<'cursor> {
context: &'cursor ScreenManager,
terminal_cursor: Box<ITerminalCursor>,
}
impl TerminalCursor {
impl<'cursor> TerminalCursor<'cursor> {
/// Create new cursor instance whereon cursor related actions can be performed.
pub fn new(context: Rc<Context>) -> TerminalCursor {
pub fn new(context: &'cursor ScreenManager) -> TerminalCursor<'cursor> {
#[cfg(target_os = "windows")]
let cursor = functions::get_module::<Box<ITerminalCursor>>(
WinApiCursor::new(context.screen_manager.clone()),

View File

@ -31,25 +31,25 @@ use std::rc::Rc;
///! so that cursor related actions can be preformed on both unix and windows systems.
pub trait ITerminalCursor {
/// Goto some location (x,y) in the context.
fn goto(&self, x: u16, y: u16);
fn goto(&self, x: u16, y: u16, screen_manager: &ScreenManager);
/// Get the location (x,y) of the current cusror in the context
fn pos(&self) -> (u16, u16);
fn pos(&self, screen_manager: &ScreenManager) -> (u16, u16);
/// Move cursor n times up
fn move_up(&self, count: u16);
fn move_up(&self, count: u16, screen_manager: &ScreenManager);
/// Move the cursor `n` times to the right.
fn move_right(&self, count: u16);
fn move_right(&self, count: u16, screen_manager: &ScreenManager);
/// Move the cursor `n` times down.
fn move_down(&self, count: u16);
fn move_down(&self, count: u16, screen_manager: &ScreenManager);
/// Move the cursor `n` times left.
fn move_left(&self, count: u16);
fn move_left(&self, count: u16, screen_manager: &ScreenManager);
/// Save cursor position so that its saved position can be recalled later. Note that this position is stored program based not per instance of the cursor struct.
fn save_position(&self);
fn save_position(&self, screen_manager: &ScreenManager);
/// Return to saved cursor position
fn reset_position(&self);
fn reset_position(&self, screen_manager: &ScreenManager);
/// Hide the terminal cursor.
fn hide(&self);
fn hide(&self, screen_manager: &ScreenManager);
/// Show the terminal cursor
fn show(&self);
fn show(&self, screen_manager: &ScreenManager);
/// enable or disable the blinking of the cursor.
fn blink(&self, blink: bool);
fn blink(&self, blink: bool, screen_manager: &ScreenManager);
}

View File

@ -10,60 +10,58 @@ use std::rc::Rc;
use std::sync::Mutex;
/// This struct is an windows implementation for cursor related actions.
pub struct WinApiCursor {
screen_manager: Rc<Mutex<ScreenManager>>,
}
pub struct WinApiCursor;
impl WinApiCursor {
pub fn new(screen_manager: Rc<Mutex<ScreenManager>>) -> Box<WinApiCursor> {
Box::from(WinApiCursor { screen_manager })
pub fn new() -> Box<WinApiCursor> {
Box::from(WinApiCursor { })
}
}
impl ITerminalCursor for WinApiCursor {
fn goto(&self, x: u16, y: u16) {
fn goto(&self, x: u16, y: u16, screen_manager: &ScreenManager) {
cursor::set_console_cursor_position(x as i16, y as i16, &self.screen_manager);
}
fn pos(&self) -> (u16, u16) {
fn pos(&self, screen_manager: &ScreenManager) -> (u16, u16) {
cursor::pos(&self.screen_manager)
}
fn move_up(&self, count: u16) {
fn move_up(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos();
self.goto(xpos, ypos - count);
}
fn move_right(&self, count: u16) {
fn move_right(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos();
self.goto(xpos + count, ypos);
}
fn move_down(&self, count: u16) {
fn move_down(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos();
self.goto(xpos, ypos + count);
}
fn move_left(&self, count: u16) {
fn move_left(&self, count: u16, screen_manager: &ScreenManager) {
let (xpos, ypos) = self.pos();
self.goto(xpos - count, ypos);
}
fn save_position(&self) {
fn save_position(&self, screen_manager: &ScreenManager) {
cursor::save_cursor_pos(&self.screen_manager);
}
fn reset_position(&self) {
fn reset_position(&self, screen_manager: &ScreenManager) {
cursor::reset_to_saved_position(&self.screen_manager);
}
fn hide(&self) {
fn hide(&self, screen_manager: &ScreenManager) {
cursor::cursor_visibility(false, &self.screen_manager);
}
fn show(&self) {
fn show(&self, screen_manager: &ScreenManager) {
cursor::cursor_visibility(true, &self.screen_manager);
}
fn blink(&self, blink: bool) {}
fn blink(&self, blink: bool, screen_manager: &ScreenManager) {}
}

View File

@ -14,6 +14,7 @@ pub mod manager;
pub mod style;
pub mod terminal;
pub use shared::Terminal::Terminal;
pub use shared::crossterm::Crossterm;
pub use shared::raw;
pub use shared::screen;

110
src/shared/Terminal.rs Normal file
View File

@ -0,0 +1,110 @@
use {StateManager, ScreenManager};
use super::super::state::commands::*;
use super::raw::RawTerminal;
use super::screen::AlternateScreen;
use std::collections::HashMap;
use std::io::Result;
pub struct Terminal{
raw_mode: bool,
alternate_mode: bool,
active_screen: ScreenManager,
raw_terminal: Option<Box<IRawScreenCommand>>,
alternate_screen: Option<Box<IAlternateScreenCommand>>
}
impl Terminal{
pub fn new() -> Terminal
{
Terminal
{
raw_mode: false,
alternate_mode: false,
active_screen: ScreenManager::new(),
raw_terminal: None,
alternate_screen: None,
}
}
pub fn enable_raw_mode(&mut self) -> Result<()> {
match self.raw_terminal
{
None => {
self.raw_terminal = Some(RawTerminal::new());
return self.enable_raw_mode();
},
Some(ref mut raw_terminal) => {
raw_terminal.enable()?;
self.raw_mode = true;
},
}
return Ok(())
}
pub fn disable_raw_mode(&mut self) -> Result<()>
{
match self.raw_terminal
{
None => {
self.raw_terminal = Some(RawTerminal::new());
return self.disable_raw_mode();
},
Some(ref mut raw_terminal) => {
raw_terminal.disable()?;
self.raw_mode = false;
},
}
return Ok(())
}
pub fn enable_alternate_screen(&mut self) -> Result<()>
{
match self.alternate_screen
{
None => {
self.alternate_screen = Some(AlternateScreen::new());
return self.enable_alternate_screen();
},
Some(ref mut alternate_screen) => {
alternate_screen.to_alternate_screen(&mut self.active_screen)?;
self.alternate_mode = true;
},
}
return Ok(())
}
pub fn disable_alternate_screen(&mut self) -> Result<()>
{
match self.alternate_screen
{
None => {
self.alternate_screen = Some(AlternateScreen::new());
return self.disable_alternate_screen();
},
Some(ref mut alternate_screen) => {
alternate_screen.to_main_screen(&mut self.active_screen)?;
self.alternate_mode = false;
},
}
return Ok(())
}
}
impl Drop for Terminal
{
fn drop(&mut self) {
if let Some(ref mut screen) = self.alternate_screen
{
screen.to_main_screen(&mut self.active_screen);
}
if let Some(ref mut raw_terminal) = self.raw_terminal
{
raw_terminal.disable();
}
}
}

View File

@ -8,3 +8,4 @@ pub mod traits;
pub mod raw;
pub mod screen;
pub mod Terminal;

View File

@ -17,99 +17,39 @@ use super::super::state::commands::unix_command::EnableRawModeCommand;
#[cfg(windows)]
use state::commands::win_commands::EnableRawModeCommand;
use state::commands::IStateCommand;
use {CommandManager, Context};
use state::commands::IRawScreenCommand;
use {CommandManager, Context, ScreenManager };
use std::io::{self, Write};
use std::rc::Rc;
/// A wrapper for the raw terminal state. Which can be used to write to.
pub struct RawTerminal {
context: Rc<Context>,
command_id: u16,
}
pub struct RawTerminal;
impl RawTerminal {
pub fn new(context: &Rc<Context>) -> RawTerminal {
let command_id = EnableRawModeCommand::new(&context.state_manager);
RawTerminal {
context: context.clone(),
command_id: command_id,
}
}
pub fn enable(&self) -> bool {
{
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)
pub fn new() -> Box<IRawScreenCommand> {
Box::from(EnableRawModeCommand::new())
}
}
//
///// Trait withs contains a method for switching into raw mode.
//pub trait IntoRawMode: Write + Sized {
// fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
//}
//
//impl<W: Write> IntoRawMode for W {
// /// Raw mode means that input (stdin) won't be printed it will instead have to be written manually by
// /// the program. The input isn't canonicalised or line buffered (that is, you can
// /// read from input(stdin) one byte of a time).
// fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal> {
// let raw_terminal = RawTerminal::new();
//
// if raw_terminal.enable()
// {
// return Ok(raw_terminal);
// }
//
// return Err(io::Error::new(io::ErrorKind::Other, "Could not enter raw mode."))
// }
//}
/// Trait withs contains a method for switching into raw mode.
pub trait IntoRawMode: Write + Sized {
fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal>;
}
impl<W: Write> IntoRawMode for W {
/// Raw mode means that input (stdin) won't be printed it will instead have to be written manually by
/// the program. The input isn't canonicalised or line buffered (that is, you can
/// read from input(stdin) one byte of a time).
fn into_raw_mode(&self, context: Rc<Context>) -> io::Result<RawTerminal> {
let command_id = EnableRawModeCommand::new(&context.state_manager);
{
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."))
}
}
impl Write for RawTerminal {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write(buf)
}
}
fn flush(&mut self) -> io::Result<()> {
let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.flush()
}
}
}
/// If an instance of `RawTerminal` will be dropped all terminal changes that are made will be undone.
impl Drop for RawTerminal {
fn drop(&mut self) {
let success = CommandManager::undo(self.context.clone(), self.command_id);
}
}

View File

@ -85,104 +85,43 @@
use shared::functions;
use state::commands::*;
use {CommandManager, Context};
use {CommandManager, Context,ScreenManager};
use std::convert::From;
use std::io::{self, Write};
use std::rc::Rc;
pub struct AlternateScreen {
context: Rc<Context>,
command_id: u16,
}
pub struct AlternateScreen;
impl AlternateScreen {
/// Get the alternate screen from the context.
/// By calling this method the current screen will be changed to the alternate screen.
/// And you get back an handle for that screen.
pub fn from(context: Rc<Context>) -> Self {
let command_id = get_to_alternate_screen_command(context.clone());
pub fn new() -> Box<IAlternateScreenCommand> {
let command = functions::get_module::<Box<IAlternateScreenCommand>>(
win_commands::ToAlternateScreenBufferCommand::new(),
shared_commands::ToAlternateScreenBufferCommand::new(),
).unwrap();
let screen = AlternateScreen {
context: context.clone(),
command_id: command_id,
};
#[cfg(not(target_os = "windows"))]
let command = shared_commands::ToAlternateScreenBufferCommand::new();
screen.to_alternate();
return screen;
}
/// Change the current screen to the mainscreen.
pub fn to_main(&self) {
{
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 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);
}
}
impl Write for AlternateScreen {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write(buf)
}
}
fn flush(&mut self) -> io::Result<()> {
let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.flush()
}
}
}
impl Drop for AlternateScreen {
fn drop(&mut self) {
use CommandManager;
CommandManager::undo(self.context.clone(), self.command_id);
command
}
}
use super::super::shared::crossterm::Crossterm;
impl From<Crossterm> for AlternateScreen {
fn from(crossterm: Crossterm) -> Self {
let command_id = get_to_alternate_screen_command(crossterm.context());
//impl From<Crossterm> for AlternateScreen {
// fn from(crossterm: Crossterm) -> Self {
// let command_id = get_to_alternate_screen_command(crossterm.context());
//
// let screen = AlternateScreen {
// context: crossterm.context(),
// command_id: command_id,
// };
// screen.to_alternate();
// return screen;
// }
//}
let screen = AlternateScreen {
context: crossterm.context(),
command_id: command_id,
};
screen.to_alternate();
return screen;
}
}
// Get the alternate screen command to enable and disable alternate screen based on the current platform
fn get_to_alternate_screen_command(context: Rc<Context>) -> u16 {
#[cfg(target_os = "windows")]
let command_id = functions::get_module::<u16>(
win_commands::ToAlternateScreenBufferCommand::new(context.clone()),
shared_commands::ToAlternateScreenBufferCommand::new(context.clone()),
).unwrap();
#[cfg(not(target_os = "windows"))]
let command_id = shared_commands::ToAlternateScreenBufferCommand::new(context.clone());
return command_id;
}

View File

@ -31,3 +31,18 @@ pub trait IStateCommand {
fn execute(&mut self) -> bool;
fn undo(&mut self) -> bool;
}
use ScreenManager;
use std::io::Result;
pub trait IAlternateScreenCommand
{
fn to_alternate_screen(&self,screen_manager: &mut ScreenManager) -> Result<()>;
fn to_main_screen(&self, screen_manager: &mut ScreenManager) -> Result<()>;
}
pub trait IRawScreenCommand
{
fn enable(&mut self) -> Result<()>;
fn disable(&mut self) -> Result<()>;
}

View File

@ -1,11 +1,13 @@
//! This module contains the commands that can be used for both unix and windows systems. Or else said terminals that support ansi codes.
use super::IStateCommand;
use super::{IStateCommand, IAlternateScreenCommand};
use Context;
use ScreenManager;
use std::rc::Rc;
use std::io::Result;
pub struct EmptyCommand;
impl IStateCommand for EmptyCommand {
fn execute(&mut self) -> bool {
return false;
@ -17,39 +19,22 @@ impl IStateCommand for EmptyCommand {
}
/// This command is used for switching to alternate screen and back to main screen.
pub struct ToAlternateScreenBufferCommand {
context: Rc<Context>,
}
pub struct ToAlternateScreenBufferCommand;
impl ToAlternateScreenBufferCommand {
pub fn new(context: Rc<Context>) -> u16 {
let mut state = context.state_manager.lock().unwrap();
{
let key = state.get_changes_count();
let command = ToAlternateScreenBufferCommand {
context: context.clone(),
};
state.register_change(Box::from(command), key);
key
}
impl ToAlternateScreenBufferCommand {
pub fn new() -> Box<ToAlternateScreenBufferCommand> {
return Box::new(ToAlternateScreenBufferCommand {});
}
}
impl IStateCommand for ToAlternateScreenBufferCommand {
fn execute(&mut self) -> bool {
let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_str(csi!("?1049h"));
return true;
}
impl IAlternateScreenCommand for ToAlternateScreenBufferCommand {
fn to_alternate_screen(&self, screen_manager: &mut ScreenManager) -> Result<()> {
screen_manager.write_str(csi!("?1049h"));
Ok(())
}
fn undo(&mut self) -> bool {
let mut screen = self.context.screen_manager.lock().unwrap();
{
screen.write_str(csi!("?1049l"));
return true;
}
fn to_main_screen(&self, screen_manager: &mut ScreenManager) -> Result<()> {
screen_manager.write_str(csi!("?1049l"));
Ok(())
}
}

View File

@ -7,6 +7,7 @@ use {CommandManager, Context, StateManager};
const FD_STDIN: ::std::os::unix::io::RawFd = 1;
use std::io::Result;
use std::rc::Rc;
use std::sync::Mutex;
@ -66,32 +67,18 @@ impl IStateCommand for NoncanonicalModeCommand {
/// This command is used for enabling and disabling raw mode for the terminal.
pub struct EnableRawModeCommand {
original_mode: Option<Box<Termios>>,
command_id: u16,
original_mode: Result<Termios>,
}
impl EnableRawModeCommand {
pub fn new(state_manager: &Mutex<StateManager>) -> u16 {
let mut state = state_manager.lock().unwrap();
{
let key = state.get_changes_count();
let command = EnableRawModeCommand {
original_mode: None,
command_id: key,
};
state.register_change(Box::from(command), key);
key
}
pub fn new() -> EnableRawModeCommand {
return EnableRawModeCommand { original_mode: terminal::get_terminal_mode(), }
}
}
impl IStateCommand for EnableRawModeCommand {
impl EnableRawModeCommand {
fn execute(&mut self) -> bool {
let original_mode = terminal::get_terminal_mode();
if let Ok(original_mode) = original_mode {
self.original_mode = Some(Box::from(original_mode));
if let Ok(original_mode) = self.original_mode {
let mut new_mode = original_mode;
terminal::make_raw(&mut new_mode);
terminal::set_terminal_mode(&new_mode);

View File

@ -1,6 +1,6 @@
//! This module contains the commands that can be used for windows systems.
use super::IStateCommand;
use super::{ IStateCommand, IAlternateScreenCommand, IRawScreenCommand};
use {Context, StateManager};
use kernel::windows_kernel::{ansi_support, csbi, handle, kernel};
@ -11,6 +11,7 @@ use winapi::um::wincon::{CHAR_INFO, COORD, ENABLE_VIRTUAL_TERMINAL_PROCESSING, S
use std::rc::Rc;
use std::sync::Mutex;
use std::io::{Result, ErrorKind, Error };
/// This command is used for enabling and disabling ANSI code support for windows systems,
/// For more info check: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences.
@ -74,116 +75,95 @@ impl IStateCommand for EnableAnsiCommand {
#[derive(Clone, Copy)]
pub struct EnableRawModeCommand {
mask: DWORD,
key: u16,
}
impl EnableRawModeCommand {
pub fn new(state_manager: &Mutex<StateManager>) -> u16 {
pub fn new() -> EnableRawModeCommand {
use self::wincon::{ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT, ENABLE_PROCESSED_INPUT};
let mut state = state_manager.lock().unwrap();
{
let key = state.get_changes_count();
let command = EnableRawModeCommand {
mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT,
key: key,
};
state.register_change(Box::from(command), key);
key
EnableRawModeCommand {
mask: ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT,
}
}
}
impl IStateCommand for EnableRawModeCommand {
fn execute(&mut self) -> bool {
let input_handle = handle::get_input_handle().unwrap();
impl IRawScreenCommand for EnableRawModeCommand {
fn enable(&mut self) -> Result<()> {
let input_handle = handle::get_input_handle()?;
let mut dw_mode: DWORD = 0;
if !kernel::get_console_mode(&input_handle, &mut dw_mode) {
return false;
return Err(Error::new(ErrorKind::Other,"Could not get console mode when enabling raw mode"))
}
let new_mode = dw_mode & !self.mask;
if !kernel::set_console_mode(&input_handle, new_mode) {
return false;
return Err(Error::new(ErrorKind::Other,"Could not set console mode when enabling raw mode"))
}
true
return Ok(())
}
fn undo(&mut self) -> bool {
let output_handle = handle::get_output_handle().unwrap();
fn disable(&mut self) -> Result<()> {
let output_handle = handle::get_input_handle()?;
let mut dw_mode: DWORD = 0;
if !kernel::get_console_mode(&output_handle, &mut dw_mode) {
return false;
return Err(Error::new(ErrorKind::Other,"Could not get console mode when disabling raw mode"))
}
let new_mode = dw_mode | self.mask;
if !kernel::set_console_mode(&output_handle, new_mode) {
return false;
return Err(Error::new(ErrorKind::Other,"Could not set console mode when disabling raw mode"))
}
true
return Ok(())
}
}
use ScreenManager;
/// This command is used for switching to alternate screen and back to main screen.
/// check https://docs.microsoft.com/en-us/windows/console/reading-and-writing-blocks-of-characters-and-attributes for more info
pub struct ToAlternateScreenBufferCommand {
context: Rc<Context>,
}
pub struct ToAlternateScreenBufferCommand;
impl ToAlternateScreenBufferCommand {
pub fn new(context: Rc<Context>) -> u16 {
let mut state = context.state_manager.lock().unwrap();
{
let key = state.get_changes_count();
let command = ToAlternateScreenBufferCommand {
context: context.clone(),
};
state.register_change(Box::from(command), key);
key
}
pub fn new() -> Box<ToAlternateScreenBufferCommand>{
return Box::from(ToAlternateScreenBufferCommand {});
}
}
impl IStateCommand for ToAlternateScreenBufferCommand {
fn execute(&mut self) -> bool {
impl IAlternateScreenCommand for ToAlternateScreenBufferCommand {
fn to_alternate_screen(&self, screen_manager: &mut ScreenManager) -> Result<()>{
use super::super::super::manager::WinApiScreenManager;
let handle = handle::get_output_handle().unwrap();
let handle = handle::get_output_handle()?;
// create a new screen buffer to copy to.
let new_handle = csbi::create_console_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 mutex = &self.context.screen_manager;
let mut screen = mutex.lock().unwrap();
let b: &mut WinApiScreenManager = match screen_manager
.as_any()
.downcast_mut::<WinApiScreenManager>()
{
Some(b) => b,
None => return Err(Error::new(ErrorKind::Other,"Invalid cast exception")),
};
let b: &mut WinApiScreenManager = match screen
.as_any()
.downcast_mut::<WinApiScreenManager>()
{
Some(b) => b,
None => panic!(""),
};
b.set_alternate_handle(new_handle);
b.set_alternate_handle(new_handle);
}
true
Ok(())
}
fn undo(&mut self) -> bool {
let handle = handle::get_output_handle().unwrap();
fn to_main_screen(&self, screen_manager: &mut ScreenManager) -> Result<()>{
let handle = handle::get_output_handle()?;
csbi::set_active_screen_buffer(handle);
true
Ok(())
}
}