Added Sync markers

This commit is contained in:
TimonPost 2018-08-21 21:17:53 +02:00
parent b98f549a73
commit c848beb721
12 changed files with 92 additions and 40 deletions

View File

@ -12,7 +12,7 @@ readme = "README.md"
[dependencies] [dependencies]
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.5", features = ["winbase","winuser","consoleapi","processenv","wincon", "handleapi"] } winapi = { version = "0.3.5", features = ["winbase","winuser","consoleapi","processenv","wincon", "handleapi","errhandlingapi"] }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
libc = "0.2.37" libc = "0.2.37"

View File

@ -16,18 +16,22 @@ mod some_types;
mod input; mod input;
use std::io::Write; use std::io::Write;
use std::{thread,time};
fn main() fn main()
{ {
// use crossterm::screen::RawScreen; use crossterm::screen::RawScreen;
// use crossterm::Screen; use crossterm::Screen;
//
// let mut screen = Screen::new(true); let mut screen = Screen::new(true);
//
cursor::goto();
// write!(screen, "text \n\r"); // write!(screen, "text \n\r");
// let a = screen.enable_alternate_modes(true).unwrap(); let a = screen.enable_alternate_modes(true).unwrap();
// cursor::goto();
thread::sleep(time::Duration::from_millis(2000));
drop(a);
cursor::goto();
// //
// write!(a, "text \n\r"); // write!(a, "text \n\r");
} }

View File

@ -23,13 +23,13 @@ pub trait IEnableAnsiCommand {
} }
// This trait provides an interface for switching to alternate screen and back. // This trait provides an interface for switching to alternate screen and back.
pub trait IAlternateScreenCommand: Send { pub trait IAlternateScreenCommand: Sync + Send {
fn enable(&self, stdout: &mut TerminalOutput) -> io::Result<()>; fn enable(&self, stdout: &mut TerminalOutput) -> io::Result<()>;
fn disable(&self, stdout: &TerminalOutput) -> io::Result<()>; fn disable(&self, stdout: &TerminalOutput) -> io::Result<()>;
} }
// This trait provides an interface for switching to raw mode and back. // This trait provides an interface for switching to raw mode and back.
pub trait IRawScreenCommand: Send{ pub trait IRawScreenCommand: Sync + Send{
fn enable(&mut self) -> io::Result<()>; fn enable(&mut self) -> io::Result<()>;
fn disable(&self) -> io::Result<()>; fn disable(&self) -> io::Result<()>;
} }

View File

@ -87,9 +87,8 @@ impl RawModeCommand
impl RawModeCommand { impl RawModeCommand {
/// Enables raw mode. /// Enables raw mode.
pub fn enable(&mut self) -> Result<()> { pub fn enable(&mut self) -> Result<()> {
let mut dw_mode: DWORD = 0; let mut dw_mode: DWORD = 0;
let stdout = handle::get_output_handle().unwrap(); let stdout = handle::get_current_handle_1().unwrap();
if !kernel::get_console_mode(&stdout, &mut dw_mode) { if !kernel::get_console_mode(&stdout, &mut dw_mode) {
return Err(Error::new( return Err(Error::new(
@ -112,7 +111,7 @@ impl RawModeCommand {
/// Disables raw mode. /// Disables raw mode.
pub fn disable(&self) -> Result<()> { pub fn disable(&self) -> Result<()> {
let stdout = handle::get_output_handle().unwrap(); let stdout = handle::get_current_handle_1().unwrap();
let mut dw_mode: DWORD = 0; let mut dw_mode: DWORD = 0;
if !kernel::get_console_mode(&stdout, &mut dw_mode) { if !kernel::get_console_mode(&stdout, &mut dw_mode) {

View File

@ -41,10 +41,10 @@ pub fn get_module<T>(winapi_impl: T, unix_impl: T) -> Option<T> {
if !windows_supportable() if !windows_supportable()
{ {
// Try to enable ansi on windows if not than use WINAPI. // Try to enable ansi on windows if not than use WINAPI.
does_support = try_enable_ansi_support(); // does_support = try_enable_ansi_support();
// uncomment this line when you want to use the winapi implementation. // uncomment this line when you want to use the winapi implementation.
does_support = true; does_support = false;
if !does_support { if !does_support {
term = Some(winapi_impl); term = Some(winapi_impl);
} }

View File

@ -15,14 +15,14 @@ use std::convert::From;
/// With this type you will be able to switch to alternate screen and back to main screen. /// With this type you will be able to switch to alternate screen and back to main screen.
pub struct AlternateScreen pub struct AlternateScreen
{ {
command: Box<IAlternateScreenCommand + Send>, command: Box<IAlternateScreenCommand + Sync + Send>,
pub screen: Screen, pub screen: Screen,
} }
impl AlternateScreen { impl AlternateScreen {
/// Create new instance of alternate screen. /// Create new instance of alternate screen.
pub fn new(command: Box<IAlternateScreenCommand + Send>, screen: Screen) -> Self pub fn new(command: Box<IAlternateScreenCommand + Sync + Send>, screen: Screen) -> Self
{ {
return AlternateScreen { command, screen } return AlternateScreen { command, screen }
} }
@ -37,7 +37,7 @@ impl AlternateScreen {
pub fn to_alternate_screen(stdout: TerminalOutput, raw_mode: bool) -> io::Result<AlternateScreen> { pub fn to_alternate_screen(stdout: TerminalOutput, raw_mode: bool) -> io::Result<AlternateScreen> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Send>>( let command = functions::get_module::<Box<commands::IAlternateScreenCommand + Sync + Send>>(
Box::from(commands::win_commands::ToAlternateScreenCommand::new()), Box::from(commands::win_commands::ToAlternateScreenCommand::new()),
Box::from(commands::shared_commands::ToAlternateScreenCommand::new()), Box::from(commands::shared_commands::ToAlternateScreenCommand::new()),
).unwrap(); ).unwrap();

View File

@ -3,27 +3,76 @@
use winapi::um::handleapi::INVALID_HANDLE_VALUE; use winapi::um::handleapi::INVALID_HANDLE_VALUE;
use winapi::um::processenv::GetStdHandle; use winapi::um::processenv::GetStdHandle;
use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE}; use winapi::um::winbase::{STD_INPUT_HANDLE, STD_OUTPUT_HANDLE};
use winapi::um::winnt::{GENERIC_READ, GENERIC_WRITE, GENERIC_ALL, FILE_SHARE_WRITE};
use winapi::um::fileapi::{OPEN_EXISTING, CreateFileW};
use winapi::shared::minwindef::DWORD;
use winapi::um::errhandlingapi::GetLastError;
use super::*; use super::*;
use std::sync::Arc; use std::sync::Arc;
use std::io::{self, Result}; use std::io::{self, Result};
use std::ptr::null_mut;
use winapi::ctypes::c_void;
/// Get the global stored handle whits provides access to the current screen. /// Get the global stored handle whits provides access to the current screen.
pub fn get_current_handle(stdout: &Arc<TerminalOutput>) -> Result<HANDLE> { pub fn get_current_handle(stdout: &Arc<TerminalOutput>) -> Result<HANDLE> {
let handle: Result<HANDLE>; // let handle: Result<HANDLE>;
//
// let winapi_stdout: &WinApiOutput = match stdout
// .as_any()
// .downcast_ref::<WinApiOutput>()
// {
// Some(win_api) => win_api,
// None => return Err(io::Error::new(io::ErrorKind::Other,"Could not convert to winapi screen write, this could happen when the user has an ANSI screen write and is calling the platform specific operations 'get_cursor_pos' or 'get_terminal_size'"))
// };
let winapi_stdout: &WinApiOutput = match stdout let dw: DWORD = 0;
.as_any() unsafe {
.downcast_ref::<WinApiOutput>()
let utf16: Vec<u16> = "CONOUT$".encode_utf16().collect();
let utf16_ptr: *const u16 = utf16.as_ptr();
let handle = CreateFileW(utf16_ptr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, null_mut(), OPEN_EXISTING, dw, null_mut());
if !is_valid_handle(&handle) {
unsafe
{ {
Some(win_api) => win_api, let error = GetLastError();
None => return Err(io::Error::new(io::ErrorKind::Other,"Could not convert to winapi screen write, this could happen when the user has an ANSI screen write and is calling the platform specific operations 'get_cursor_pos' or 'get_terminal_size'")) return Err(io::Error::new(
}; io::ErrorKind::Other,
format!("Could not get output handle current handle!, error code: {}", error).as_ref(),
));
}
}
Ok(handle)
}
}
handle = Ok(winapi_stdout.get_handle()); pub fn get_current_handle_1() -> Result<HANDLE>
{
let handle: Result<HANDLE>;
use std::str;
unsafe
{
let dw: DWORD = 0;
return handle; let utf16: Vec<u16> = "CONOUT$".encode_utf16().collect();
let utf16_ptr: *const u16 = utf16.as_ptr();
let handle = CreateFileW(utf16_ptr, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, null_mut(), OPEN_EXISTING,dw, null_mut());
if !is_valid_handle(&handle) {
return Err(io::Error::new(
io::ErrorKind::Other,
"Could not get output handle 1 !",
));
}
Ok(handle)
}
} }
/// Get the std_output_handle of the console /// Get the std_output_handle of the console

View File

@ -28,7 +28,7 @@ use Screen;
/// ``` /// ```
pub struct TerminalCursor<'stdout> { pub struct TerminalCursor<'stdout> {
screen: &'stdout Arc<TerminalOutput>, screen: &'stdout Arc<TerminalOutput>,
terminal_cursor: Box<ITerminalCursor>, terminal_cursor: Box<ITerminalCursor + Sync + Send>,
} }
impl<'stdout> TerminalCursor<'stdout> { impl<'stdout> TerminalCursor<'stdout> {
@ -36,11 +36,11 @@ impl<'stdout> TerminalCursor<'stdout> {
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> { pub fn new(screen: &'stdout Arc<TerminalOutput>) -> TerminalCursor<'stdout> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let cursor = let cursor =
functions::get_module::<Box<ITerminalCursor>>(WinApiCursor::new(), AnsiCursor::new()) functions::get_module::<Box<ITerminalCursor + Sync + Send>>(WinApiCursor::new(), AnsiCursor::new())
.unwrap(); .unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let cursor = AnsiCursor::new() as Box<ITerminalCursor>; let cursor = AnsiCursor::new() as Box<ITerminalCursor + Sync + Send>;
TerminalCursor { TerminalCursor {
terminal_cursor: cursor, terminal_cursor: cursor,

View File

@ -25,7 +25,7 @@ use std::sync::Arc;
///! ///!
///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific), ///! This trait is implemented for `WINAPI` (Windows specific) and `ANSI` (Unix specific),
///! so that cursor related actions can be preformed on both unix and windows systems. ///! so that cursor related actions can be preformed on both unix and windows systems.
trait ITerminalCursor { trait ITerminalCursor : Sync + Send {
/// Goto some location (x,y) in the context. /// Goto some location (x,y) in the context.
fn goto(&self, x: u16, y: u16, stdout: &Arc<TerminalOutput>); fn goto(&self, x: u16, y: u16, stdout: &Arc<TerminalOutput>);
/// Get the location (x,y) of the current cusror in the context /// Get the location (x,y) of the current cusror in the context

View File

@ -20,7 +20,7 @@ use Screen;
/// ///
/// ``` /// ```
pub struct TerminalInput<'stdout> { pub struct TerminalInput<'stdout> {
terminal_input: Box<ITerminalInput>, terminal_input: Box<ITerminalInput + Sync + Send>,
stdout: &'stdout Arc<TerminalOutput>, stdout: &'stdout Arc<TerminalOutput>,
} }

View File

@ -27,7 +27,7 @@ use Screen;
/// colored_terminal.reset(); /// colored_terminal.reset();
/// ``` /// ```
pub struct TerminalColor<'stdout> { pub struct TerminalColor<'stdout> {
color: Box<ITerminalColor>, color: Box<ITerminalColor + Sync + Send>,
stdout: &'stdout Arc<TerminalOutput>, stdout: &'stdout Arc<TerminalOutput>,
} }
@ -35,13 +35,13 @@ impl<'stdout> TerminalColor<'stdout> {
/// Create new instance whereon color related actions can be performed. /// Create new instance whereon color related actions can be performed.
pub fn new(stdout: &'stdout Arc<TerminalOutput>) -> TerminalColor<'stdout> { pub fn new(stdout: &'stdout Arc<TerminalOutput>) -> TerminalColor<'stdout> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let color = functions::get_module::<Box<ITerminalColor>>( let color = functions::get_module::<Box<ITerminalColor + Sync + Send>>(
Box::from(WinApiColor::new()), Box::from(WinApiColor::new()),
Box::from(AnsiColor::new()), Box::from(AnsiColor::new()),
).unwrap(); ).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let color = Box::from(AnsiColor::new()) as Box<ITerminalColor>; let color = Box::from(AnsiColor::new()) as Box<ITerminalColor + Sync + Send>;
TerminalColor { TerminalColor {
color, color,

View File

@ -21,7 +21,7 @@ use std::fmt;
/// ///
/// ``` /// ```
pub struct Terminal<'stdout> { pub struct Terminal<'stdout> {
terminal: Box<ITerminal>, terminal: Box<ITerminal + Sync + Send>,
screen: &'stdout Arc<TerminalOutput>, screen: &'stdout Arc<TerminalOutput>,
} }
@ -29,13 +29,13 @@ impl<'stdout> Terminal<'stdout> {
/// Create new terminal instance whereon terminal related actions can be performed. /// Create new terminal instance whereon terminal related actions can be performed.
pub fn new(screen: &'stdout Arc<TerminalOutput>) -> Terminal<'stdout> { pub fn new(screen: &'stdout Arc<TerminalOutput>) -> Terminal<'stdout> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let terminal = functions::get_module::<Box<ITerminal>>( let terminal = functions::get_module::<Box<ITerminal + Sync + Send>>(
Box::new(WinApiTerminal::new()), Box::new(WinApiTerminal::new()),
Box::new(AnsiTerminal::new()), Box::new(AnsiTerminal::new()),
).unwrap(); ).unwrap();
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal>; let terminal = Box::from(AnsiTerminal::new()) as Box<ITerminal + Sync + Send>;
Terminal { Terminal {
terminal, terminal,