From c848beb72186698a43b30cf30c41d349933a8831 Mon Sep 17 00:00:00 2001 From: TimonPost Date: Tue, 21 Aug 2018 21:17:53 +0200 Subject: [PATCH] Added Sync markers --- Cargo.toml | 2 +- examples/examples.rs | 22 ++++++---- src/common/commands/mod.rs | 4 +- src/common/commands/win_commands.rs | 5 +-- src/common/functions.rs | 4 +- src/common/screen/alternate.rs | 6 +-- src/kernel/windows_kernel/handle.rs | 67 +++++++++++++++++++++++++---- src/modules/cursor/cursor.rs | 6 +-- src/modules/cursor/mod.rs | 2 +- src/modules/input/input.rs | 2 +- src/modules/style/color.rs | 6 +-- src/modules/terminal/terminal.rs | 6 +-- 12 files changed, 92 insertions(+), 40 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c83d705..9df65b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ readme = "README.md" [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] libc = "0.2.37" diff --git a/examples/examples.rs b/examples/examples.rs index da9c605..8341d98 100644 --- a/examples/examples.rs +++ b/examples/examples.rs @@ -16,18 +16,22 @@ mod some_types; mod input; use std::io::Write; - +use std::{thread,time}; fn main() { -// use crossterm::screen::RawScreen; -// use crossterm::Screen; -// -// let mut screen = Screen::new(true); -// + use crossterm::screen::RawScreen; + use crossterm::Screen; + + let mut screen = Screen::new(true); + + cursor::goto(); + // 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"); - - } diff --git a/src/common/commands/mod.rs b/src/common/commands/mod.rs index 20567cd..f900f9a 100644 --- a/src/common/commands/mod.rs +++ b/src/common/commands/mod.rs @@ -23,13 +23,13 @@ pub trait IEnableAnsiCommand { } // 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 disable(&self, stdout: &TerminalOutput) -> io::Result<()>; } // 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 disable(&self) -> io::Result<()>; } diff --git a/src/common/commands/win_commands.rs b/src/common/commands/win_commands.rs index 34bbf84..5177463 100644 --- a/src/common/commands/win_commands.rs +++ b/src/common/commands/win_commands.rs @@ -87,9 +87,8 @@ impl RawModeCommand impl RawModeCommand { /// Enables raw mode. pub fn enable(&mut self) -> Result<()> { - 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) { return Err(Error::new( @@ -112,7 +111,7 @@ impl RawModeCommand { /// Disables raw mode. 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; if !kernel::get_console_mode(&stdout, &mut dw_mode) { diff --git a/src/common/functions.rs b/src/common/functions.rs index aa93ae8..adc56d7 100644 --- a/src/common/functions.rs +++ b/src/common/functions.rs @@ -41,10 +41,10 @@ pub fn get_module(winapi_impl: T, unix_impl: T) -> Option { if !windows_supportable() { // 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. - does_support = true; + does_support = false; if !does_support { term = Some(winapi_impl); } diff --git a/src/common/screen/alternate.rs b/src/common/screen/alternate.rs index e7388f9..463d43b 100644 --- a/src/common/screen/alternate.rs +++ b/src/common/screen/alternate.rs @@ -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. pub struct AlternateScreen { - command: Box, + command: Box, pub screen: Screen, } impl AlternateScreen { /// Create new instance of alternate screen. - pub fn new(command: Box, screen: Screen) -> Self + pub fn new(command: Box, screen: Screen) -> Self { return AlternateScreen { command, screen } } @@ -37,7 +37,7 @@ impl AlternateScreen { pub fn to_alternate_screen(stdout: TerminalOutput, raw_mode: bool) -> io::Result { #[cfg(target_os = "windows")] - let command = functions::get_module::>( + let command = functions::get_module::>( Box::from(commands::win_commands::ToAlternateScreenCommand::new()), Box::from(commands::shared_commands::ToAlternateScreenCommand::new()), ).unwrap(); diff --git a/src/kernel/windows_kernel/handle.rs b/src/kernel/windows_kernel/handle.rs index a0fc6d9..984a57a 100644 --- a/src/kernel/windows_kernel/handle.rs +++ b/src/kernel/windows_kernel/handle.rs @@ -3,27 +3,76 @@ 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::{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 std::sync::Arc; 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. pub fn get_current_handle(stdout: &Arc) -> Result { +// let handle: Result; +// +// let winapi_stdout: &WinApiOutput = match stdout +// .as_any() +// .downcast_ref::() +// { +// 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 dw: DWORD = 0; + unsafe { + + let utf16: Vec = "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 + { + let error = GetLastError(); + return Err(io::Error::new( + io::ErrorKind::Other, + format!("Could not get output handle current handle!, error code: {}", error).as_ref(), + )); + } + } + + Ok(handle) + } +} + +pub fn get_current_handle_1() -> Result +{ let handle: Result; + use std::str; + unsafe + { + let dw: DWORD = 0; - let winapi_stdout: &WinApiOutput = match stdout - .as_any() - .downcast_ref::() - { - 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 utf16: Vec = "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()); - handle = Ok(winapi_stdout.get_handle()); + if !is_valid_handle(&handle) { + return Err(io::Error::new( + io::ErrorKind::Other, + "Could not get output handle 1 !", + )); + } - return handle; + Ok(handle) + } } /// Get the std_output_handle of the console diff --git a/src/modules/cursor/cursor.rs b/src/modules/cursor/cursor.rs index 423d39e..67588dd 100644 --- a/src/modules/cursor/cursor.rs +++ b/src/modules/cursor/cursor.rs @@ -28,7 +28,7 @@ use Screen; /// ``` pub struct TerminalCursor<'stdout> { screen: &'stdout Arc, - terminal_cursor: Box, + terminal_cursor: Box, } impl<'stdout> TerminalCursor<'stdout> { @@ -36,11 +36,11 @@ impl<'stdout> TerminalCursor<'stdout> { pub fn new(screen: &'stdout Arc) -> TerminalCursor<'stdout> { #[cfg(target_os = "windows")] let cursor = - functions::get_module::>(WinApiCursor::new(), AnsiCursor::new()) + functions::get_module::>(WinApiCursor::new(), AnsiCursor::new()) .unwrap(); #[cfg(not(target_os = "windows"))] - let cursor = AnsiCursor::new() as Box; + let cursor = AnsiCursor::new() as Box; TerminalCursor { terminal_cursor: cursor, diff --git a/src/modules/cursor/mod.rs b/src/modules/cursor/mod.rs index 647d7a2..99f0ca7 100644 --- a/src/modules/cursor/mod.rs +++ b/src/modules/cursor/mod.rs @@ -25,7 +25,7 @@ use std::sync::Arc; ///! ///! 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. -trait ITerminalCursor { +trait ITerminalCursor : Sync + Send { /// Goto some location (x,y) in the context. fn goto(&self, x: u16, y: u16, stdout: &Arc); /// Get the location (x,y) of the current cusror in the context diff --git a/src/modules/input/input.rs b/src/modules/input/input.rs index 3bd699d..2aff617 100644 --- a/src/modules/input/input.rs +++ b/src/modules/input/input.rs @@ -20,7 +20,7 @@ use Screen; /// /// ``` pub struct TerminalInput<'stdout> { - terminal_input: Box, + terminal_input: Box, stdout: &'stdout Arc, } diff --git a/src/modules/style/color.rs b/src/modules/style/color.rs index 86517e2..505c07f 100644 --- a/src/modules/style/color.rs +++ b/src/modules/style/color.rs @@ -27,7 +27,7 @@ use Screen; /// colored_terminal.reset(); /// ``` pub struct TerminalColor<'stdout> { - color: Box, + color: Box, stdout: &'stdout Arc, } @@ -35,13 +35,13 @@ impl<'stdout> TerminalColor<'stdout> { /// Create new instance whereon color related actions can be performed. pub fn new(stdout: &'stdout Arc) -> TerminalColor<'stdout> { #[cfg(target_os = "windows")] - let color = functions::get_module::>( + let color = functions::get_module::>( Box::from(WinApiColor::new()), Box::from(AnsiColor::new()), ).unwrap(); #[cfg(not(target_os = "windows"))] - let color = Box::from(AnsiColor::new()) as Box; + let color = Box::from(AnsiColor::new()) as Box; TerminalColor { color, diff --git a/src/modules/terminal/terminal.rs b/src/modules/terminal/terminal.rs index 841d0a1..0f49ea6 100644 --- a/src/modules/terminal/terminal.rs +++ b/src/modules/terminal/terminal.rs @@ -21,7 +21,7 @@ use std::fmt; /// /// ``` pub struct Terminal<'stdout> { - terminal: Box, + terminal: Box, screen: &'stdout Arc, } @@ -29,13 +29,13 @@ impl<'stdout> Terminal<'stdout> { /// Create new terminal instance whereon terminal related actions can be performed. pub fn new(screen: &'stdout Arc) -> Terminal<'stdout> { #[cfg(target_os = "windows")] - let terminal = functions::get_module::>( + let terminal = functions::get_module::>( Box::new(WinApiTerminal::new()), Box::new(AnsiTerminal::new()), ).unwrap(); #[cfg(not(target_os = "windows"))] - let terminal = Box::from(AnsiTerminal::new()) as Box; + let terminal = Box::from(AnsiTerminal::new()) as Box; Terminal { terminal,