diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 4cfcb34..a416570 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -3,8 +3,21 @@ + + + + + + - + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - + + + + + + + + + + @@ -51,38 +73,47 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + @@ -120,7 +151,6 @@ &context cursor context - data Mutex WriteConsoleOutputW CONSOLE_CURSOR_INFO @@ -128,6 +158,7 @@ Borrow fmt STD_OUTPUT_HANDLE + data crossterm_cursor @@ -170,38 +201,38 @@ @@ -215,7 +246,7 @@ - - - + @@ -602,14 +634,14 @@ - + - + @@ -635,14 +667,6 @@ - - - - - - - - @@ -710,13 +734,6 @@ - - - - - - - @@ -724,34 +741,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -759,17 +748,14 @@ - - - - - - - + + + + @@ -787,13 +773,6 @@ - - - - - - - @@ -801,20 +780,6 @@ - - - - - - - - - - - - - - @@ -826,13 +791,6 @@ - - - - - - - @@ -840,20 +798,6 @@ - - - - - - - - - - - - - - @@ -868,6 +812,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -875,6 +882,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -888,116 +962,45 @@ - + - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -1008,6 +1011,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs index ba25251..cf3732b 100644 --- a/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs +++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/bin.rs @@ -30,10 +30,15 @@ use std::io::Write; use std::{time, thread}; fn main() { -// alternate_screen::switch_between_main_and_alternate_screen(); +//// alternate_screen::switch_between_main_and_alternate_screen(); let context = Context::new(); - let mut scre = screen::AlternateScreen::from(context.clone()); - write!(scre, "asdf"); - scre.flush(); - thread::sleep(time::Duration::from_secs(3)); +// let mut scre = screen::AlternateScreen::from(context.clone()); +// write!(scre, "asdf"); +// scre.flush(); +// thread::sleep(time::Duration::from_secs(3)); + + use crossterm::terminal::terminal; + + let curs = terminal(context.clone()); + curs.set_title(String::from("Test")); } \ No newline at end of file diff --git a/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs b/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs index 6671060..92b3d43 100644 --- a/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs +++ b/examples/Crossterm 0.2.2 - New Version (Not finished)/cursor/mod.rs @@ -122,6 +122,24 @@ pub fn safe_and_reset_position() println!() } +/// Hide cursor display | demonstration. +pub fn hide_cursor() +{ + let context = Context::new(); + + let cursor = cursor(context.clone()); + cursor.hide(); +} + +/// Show cursor display | demonstration. +pub fn show_cursor() +{ + let context = Context::new(); + + let cursor = cursor(context.clone()); + cursor.show(); +} + diff --git a/src/cursor/ansi_cursor.rs b/src/cursor/ansi_cursor.rs index fcf4e84..d880abe 100644 --- a/src/cursor/ansi_cursor.rs +++ b/src/cursor/ansi_cursor.rs @@ -19,12 +19,11 @@ impl AnsiCursor { } impl ITerminalCursor for AnsiCursor { - fn goto(&self, x: u16, y: u16) { let mut screen = self.context.screen_manager.lock().unwrap(); { - screen.write_ansi(format!(csi!("{};{}H"), y + 1, x +1)); + screen.write_ansi(format!(csi!("{};{}H"), y + 1, x + 1)); } } @@ -91,4 +90,18 @@ impl ITerminalCursor for AnsiCursor { screen.write_ansi_str(csi!("?25h")); } } + + fn blink(&self, blink: bool) + { + let mut screen = self.context.screen_manager.lock().unwrap(); + { + if blink + { + screen.write_ansi_str(csi!("?12h")); + } + else { + screen.write_ansi_str(csi!("?12l")); + } + } + } } diff --git a/src/cursor/cursor.rs b/src/cursor/cursor.rs index 604b8c5..938edc4 100644 --- a/src/cursor/cursor.rs +++ b/src/cursor/cursor.rs @@ -26,7 +26,7 @@ impl TerminalCursor #[cfg(not(target_os = "windows"))] let cursor = Some(AnsiCursor::new(context.clone()) as Box); - TerminalCursor { terminal_cursor: cursor , context} + TerminalCursor { terminal_cursor: Some(WinApiCursor::new()), context} } /// Goto some position (x,y) in the terminal. @@ -105,7 +105,7 @@ impl TerminalCursor /// // Move the cursor to position 3 times to the up in the terminal /// cursor.move_up(3); /// } - /// + /// /// ``` pub fn move_up(&mut self, count: u16) -> &mut TerminalCursor { if let Some(ref terminal_cursor) = self.terminal_cursor { @@ -293,6 +293,73 @@ impl TerminalCursor terminal_cursor.reset_position(); } } + + /// Hide de cursor in the console. + /// + /// #Example + /// + /// ```rust + /// + /// extern crate crossterm; + /// use self::crossterm::cursor::cursor; + /// use self::crossterm::Context; + /// + /// let context = Context::new(); + /// cursor(&context).hide(); + /// + /// ``` + pub fn hide(&self) + { + if let Some(ref terminal_cursor) = self.terminal_cursor { + terminal_cursor.hide(); + } + } + + /// Show the cursor in the console. + /// + /// #Example + /// + /// ```rust + /// + /// extern crate crossterm; + /// use self::crossterm::cursor::cursor; + /// use self::crossterm::Context; + /// + /// let context = Context::new(); + /// cursor(&context).show(); + /// + /// ``` + pub fn show(&self) + { + if let Some(ref terminal_cursor) = self.terminal_cursor { + terminal_cursor.show(); + } + } + + /// Enable or disable blinking of the terminal. + /// + /// Note that this only works on windows 10 and unix systems. If you are working on windows 10 or lower this won't work. + /// + /// #Example + /// + /// ```rust + /// + /// extern crate crossterm; + /// use self::crossterm::cursor::cursor; + /// use self::crossterm::Context; + /// + /// let context = Context::new(); + /// let cursor = cursor(&context); + /// cursor.blink(true); + /// cursor.blink(false); + /// + /// ``` + pub fn blink(&self, blink: bool) + { + if let Some(ref terminal_cursor) = self.terminal_cursor { + terminal_cursor.blink(blink); + } + } } /// Get an TerminalCursor implementation whereon cursor related actions can be performed. @@ -312,7 +379,12 @@ impl TerminalCursor /// // Get cursor and goto pos X: 5, Y: 10 /// let mut cursor = cursor::cursor(&context); /// cursor.goto(5,10); -/// +/// +/// cursor.show(); +/// cursor.hide(); +/// cursor.blink(); +/// cursor.move_left(2); +/// /// //Or you can do it in one line. /// cursor::cursor(&context).goto(5,10); /// diff --git a/src/cursor/mod.rs b/src/cursor/mod.rs index e01898f..1f662d0 100644 --- a/src/cursor/mod.rs +++ b/src/cursor/mod.rs @@ -51,4 +51,6 @@ pub trait ITerminalCursor { fn hide(&self); /// Show the terminal cursor fn show(&self); + /// enable or disable the blinking of the cursor. + fn blink(&self, blink: bool); } \ No newline at end of file diff --git a/src/cursor/winapi_cursor.rs b/src/cursor/winapi_cursor.rs index 4326804..0476595 100644 --- a/src/cursor/winapi_cursor.rs +++ b/src/cursor/winapi_cursor.rs @@ -62,4 +62,9 @@ impl ITerminalCursor for WinApiCursor { { kernel::cursor_visibility(true); } + + fn blink(&self, blink: bool) + { + + } } diff --git a/src/kernel/windows_kernel/kernel.rs b/src/kernel/windows_kernel/kernel.rs index 3a9f781..855643f 100644 --- a/src/kernel/windows_kernel/kernel.rs +++ b/src/kernel/windows_kernel/kernel.rs @@ -134,11 +134,11 @@ pub fn set_console_cursor_position(x: i16, y: i16) pub fn cursor_visibility(visable: bool) { let handle = get_output_handle(); - let cursor_info = CONSOLE_CURSOR_INFO { - dwSize: 100, - bVisible: if visable { FALSE } else {TRUE} + + dwSize: 1, + bVisible: if visable { TRUE } else {FALSE} }; unsafe @@ -299,17 +299,37 @@ pub fn write_console_output(write_buffer: &HANDLE, copy_buffer: &mut [CHAR_INFO; pub fn write_char_buffer(handle: HANDLE, buf: &[u8]) { - use std::ffi::CString; + use std::ffi::{ NulError, CString }; use std::str; + // get string from u8[] and parse it to an c_str + let mut utf8 = match str::from_utf8(buf) + { + Ok(string) => string, + Err(_) => "", + }; + + let utf16_bytes: Vec = utf8.encode_utf16().collect(); + + let utf16 = match String::from_utf16(&utf16_bytes) + { + Ok(string) => string, + Err(_) => String::new() + }; + + let str_length = utf16.len() as u32; + + let c_str = match CString::new(utf16) + { + Ok(c) => c, + Err(_) => CString::new("").unwrap() + }; + + let ptr: *const i8 = c_str.as_ptr() as *const i8; + // get buffer info let csbi = get_console_screen_buffer_info(); - // get string from u8[] and parse it to an c_str - let mut data = str::from_utf8(buf).unwrap(); - let c_str = CString::new(data).unwrap(); - let ptr: *const u16 = c_str.as_ptr() as *const u16; - panic!("{:?}", ptr); // get current position let current_pos = COORD {X: csbi.dwCursorPosition.X, Y: csbi.dwCursorPosition.Y}; @@ -318,9 +338,16 @@ pub fn write_char_buffer(handle: HANDLE, buf: &[u8]) // write to console unsafe { - - WriteConsoleOutputAttribute(handle, ptr, data.len() as u32, current_pos, &mut cells_written); + WriteConsoleOutputCharacterA(handle, ptr, str_length, current_pos, &mut cells_written); } + + // get buffer info + let csbi = get_console_screen_buffer_info(); + + // get current position + let new_pos = COORD {X: csbi.dwCursorPosition.X, Y: csbi.dwCursorPosition.Y}; + + set_console_cursor_position(new_pos.X, new_pos.Y + 1); } /// Parse integer to an bool diff --git a/src/manager/ansi_manager.rs b/src/manager/ansi_manager.rs index 5f83fa5..31f2219 100644 --- a/src/manager/ansi_manager.rs +++ b/src/manager/ansi_manager.rs @@ -15,12 +15,6 @@ pub struct AnsiScreenManager impl IScreenManager for AnsiScreenManager { - -// fn stdout(&mut self) -> &mut Self::Output -// { -// return &mut self.output -// } - fn toggle_is_alternate_screen(&mut self, is_alternate_screen: bool) { self.is_alternate_screen = is_alternate_screen; diff --git a/src/manager/manager.rs b/src/manager/manager.rs index 2a8d1e5..dafa94d 100644 --- a/src/manager/manager.rs +++ b/src/manager/manager.rs @@ -20,15 +20,15 @@ impl ScreenManager { /// Create new screen manager instance whereon screen related actions can be performed. pub fn new() -> ScreenManager { -// #[cfg(target_os = "windows")] -// let screen_manager = functions::get_module::>(Box::from(WinApiScreenManager::new()), Box::from(AnsiScreenManager::new())).unwrap(); -// -// #[cfg(not(target_os = "windows"))] -// let screen_manager = Box::new(AnsiScreenManager::new()); + #[cfg(target_os = "windows")] + let screen_manager = functions::get_module::>(Box::from(WinApiScreenManager::new()), Box::from(AnsiScreenManager::new())).unwrap(); + + #[cfg(not(target_os = "windows"))] + let screen_manager = Box::new(AnsiScreenManager::new()); ScreenManager { - screen_manager: Box::from(WinApiScreenManager::new()), + screen_manager: Box::from(WinApiScreenManager::new()) } } diff --git a/src/shared/screen.rs b/src/shared/screen.rs index b15e9fd..f40f2a8 100644 --- a/src/shared/screen.rs +++ b/src/shared/screen.rs @@ -1,4 +1,9 @@ //! This module contains all the logic for switching between alternate screen and main screen. +//! +//! *Nix style applications often utilize an alternate screen buffer, so that they can modify the entire contents of the buffer, without affecting the application that started them. +//! The alternate buffer is exactly the dimensions of the window, without any scrollback region. +//! For an example of this behavior, consider when vim is launched from bash. +//! Vim uses the entirety of the screen to edit the file, then returning to bash leaves the original buffer unchanged. use Context; use state::commands::*; diff --git a/src/state/commands/win_commands.rs b/src/state/commands/win_commands.rs index f731306..e95c523 100644 --- a/src/state/commands/win_commands.rs +++ b/src/state/commands/win_commands.rs @@ -174,14 +174,8 @@ impl IStateCommand for ToAlternateScreenBufferCommand { fn execute(&mut self) -> bool { - use super::super::super::kernel::windows_kernel::ansi_support; use super::super::super::manager::WinApiScreenManager; - let does_support = ansi_support::try_enable_ansi_support(); - let mut screen_manager = self.context.screen_manager.lock().unwrap(); - - screen_manager.toggle_is_alternate_screen(true); - let mut chi_buffer: [CHAR_INFO;160] = unsafe {mem::zeroed() }; let handle = kernel::get_output_handle(); @@ -192,6 +186,9 @@ impl IStateCommand for ToAlternateScreenBufferCommand // Make the new screen buffer the active screen buffer. kernel::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!("&a isn't a B!") diff --git a/src/terminal/ansi_terminal.rs b/src/terminal/ansi_terminal.rs index 2c2c04a..378a4e4 100644 --- a/src/terminal/ansi_terminal.rs +++ b/src/terminal/ansi_terminal.rs @@ -66,4 +66,12 @@ impl ITerminal for AnsiTerminal { screen.write_ansi(format!(csi!("8;{};{}t"), width, height)); } } + + fn set_title(&self, title: String) + { + let mut screen = self.context.screen_manager.lock().unwrap(); + { + screen.write_ansi_str("\x1b]2;New terminal titleBEL"); + } + } } diff --git a/src/terminal/mod.rs b/src/terminal/mod.rs index cca8135..1d0d23e 100644 --- a/src/terminal/mod.rs +++ b/src/terminal/mod.rs @@ -48,4 +48,6 @@ pub trait ITerminal { fn scroll_down(&self, count: i16); /// Resize terminal to the given width and height. fn set_size(&self,width: i16, height: i16); + /// Set the terminal title. + fn set_title(&self, title: String); } diff --git a/src/terminal/terminal.rs b/src/terminal/terminal.rs index f99f528..faab9d4 100644 --- a/src/terminal/terminal.rs +++ b/src/terminal/terminal.rs @@ -186,6 +186,13 @@ impl Terminal { { style::ObjectStyle::new().apply_to(val, self.context.clone()) } + + pub fn set_title(&self, title: String) + { + if let Some (ref terminal) = self.terminal { + terminal.set_title(title ); + } + } } /// Get an Terminal implementation whereon terminal related actions can be performed. diff --git a/src/terminal/winapi_terminal.rs b/src/terminal/winapi_terminal.rs index 53b8132..866c6c7 100644 --- a/src/terminal/winapi_terminal.rs +++ b/src/terminal/winapi_terminal.rs @@ -137,6 +137,11 @@ impl ITerminal for WinApiTerminal { } } } + + fn set_title(&self, title: String) + { + + } } pub fn clear_after_cursor(pos: (u16,u16), csbi: CONSOLE_SCREEN_BUFFER_INFO, context: Rc) {