diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 7bf73c3..08fdd67 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -3,25 +3,11 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
@@ -32,49 +18,16 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -85,10 +38,27 @@
winapi
kernel32
HANDLE
- CONSOLE_SCREEN_BUFFER_INFO
handleapi
terminal_cursor
terminal
+ r
+ short
+ console_mode
+ set
+ fsr_window
+ resizeBuffer
+ set_console_text_attribute
+ set(
+ kern
+ pos
+ csbi
+ kernel
+ success
+ count
+ xpos
+ handle::
+ wincon
+ CONSOLE_SCREEN_BUFFER_INFO
crossterm_cursor
@@ -105,25 +75,40 @@
@@ -134,10 +119,10 @@
DEFINITION_ORDER
-
+
-
-
+
+
@@ -154,6 +139,7 @@
+
@@ -164,23 +150,22 @@
-
+
-
-
+
-
+
@@ -292,16 +277,24 @@
1513618274599
-
+
+
+
+
+
+
+
+
+
+
-
+
-
@@ -316,9 +309,8 @@
-
+
-
@@ -330,6 +322,7 @@
+
@@ -343,89 +336,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -439,15 +349,6 @@
-
-
-
-
-
-
-
-
-
@@ -455,91 +356,15 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
@@ -547,7 +372,6 @@
-
@@ -555,7 +379,6 @@
-
@@ -563,7 +386,6 @@
-
@@ -571,7 +393,6 @@
-
@@ -579,55 +400,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -635,15 +407,6 @@
-
-
-
-
-
-
-
-
-
@@ -651,55 +414,23 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -707,37 +438,260 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Cargo.toml b/Cargo.toml
index ad673d0..3b9080e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,5 +16,8 @@ winapi = { version = "0.3", features = ["winbase","winuser","consoleapi","proces
[target.'cfg(unix)'.dependencies]
libc = "0.2"
+[[bin]]
+name = "example_bin"
+path = "./examples/bin.rs"
diff --git a/examples/bin.rs b/examples/bin.rs
index 5861c68..d648f4b 100644
--- a/examples/bin.rs
+++ b/examples/bin.rs
@@ -1,15 +1,29 @@
+//! This bin folder can be used to try the examples out located in the examples directory.
+//!
+//! All you need to do is:
+//!
+//! - Download the crossterm source code.
+//! - Add this in the Cargo.toml file:
+//! ``` [[bin]]
+//! name = "example_bin"
+//! path = "./examples/bin.rs"
+//! ```
+//!
+//! - Run program with: `cargo run`
+
+// Import crossterm crate.
extern crate crossterm;
-use self::crossterm::crossterm_style::*;
+// Add the usings for the crossterms modules to play with crossterm
+use self::crossterm::crossterm_style;
use self::crossterm::crossterm_cursor;
-use self::crossterm::crossterm_terminal::*;
-
-use std::io::{stdin, stdout, Write};
+use self::crossterm::crossterm_terminal;
+// Import the example modules.
pub mod color;
pub mod cursor;
pub mod terminal;
fn main() {
-
+
}
diff --git a/examples/color/mod.rs b/examples/color/mod.rs
index 103b678..b5c525d 100644
--- a/examples/color/mod.rs
+++ b/examples/color/mod.rs
@@ -28,7 +28,7 @@ pub fn paint_background()
// This will give you an object back wits can be styled and displayed.
let mut styledobject = paint("Red background color");
// Call the method `on()` on the object given by `paint()` and pass in an Color from the Color enum.
- styledobject = styledobject.on(Color::Blue);
+ styledobject = styledobject.on(Color::Red);
// Print the object to the console and check see the result
println!("{}", styledobject);
@@ -97,4 +97,33 @@ pub fn print_all_background_colors()
println!("Dark Cyan : \t {}", paint(" ").on(Color::DarkCyan));
println!("Grey : \t\t {}", paint(" ").on(Color::Grey));
println!("White : \t {}", paint(" ").on(Color::White));
+}
+
+/// Print font with all available attributes. Note that this can only be used at unix systems and that some are not supported widely.
+#[cfg(unix)]
+pub fn print_font_with_attributes()
+{
+ println!("{}", paint("Normal text"));
+ println!("{}", paint("Bold text").bold());
+ println!("{}", paint("Italic text").italic());
+ println!("{}", paint("Slow blinking text").slow_blink());
+ println!("{}", paint("Rapid blinking text").rapid_blink());
+ println!("{}", paint("Hidden text").hidden());
+ println!("{}", paint("Underlined text").underlined());
+ println!("{}", paint("Reversed color").reverse());
+ println!("{}", paint("Dim text color").dim());
+ println!("{}", paint("Crossed out font").crossed_out());
+}
+
+/// Print all supported rgb colors
+#[cfg(unix)]#[cfg(unix)]
+pub fn print_supported_colors()
+{
+ let count = crossterm::crossterm_style::get().get_available_color_count().unwrap();
+
+ for i in 0..count
+ {
+ println!("{}", paint(format!("Color: {}",i)).with(Color::AnsiValue(i as u8)));
+
+ }
}
\ No newline at end of file
diff --git a/examples/cursor/mod.rs b/examples/cursor/mod.rs
index 3366039..73d67df 100644
--- a/examples/cursor/mod.rs
+++ b/examples/cursor/mod.rs
@@ -76,6 +76,27 @@ pub fn print()
get().goto(10,5).print("@");
}
+/// Save and reset cursor position.
+pub fn safe_and_reset_position()
+{
+ let mut cursor = get();
+
+ // Goto X: 5 Y: 5
+ cursor.goto(5,5);
+ // Safe cursor position: X: 5 Y: 5
+ cursor.safe_position();
+ // Goto X: 5 Y: 20
+ cursor.goto(5,20);
+ // Print at X: 5 Y: 20.
+ print!("Yea!");
+ // Reset back to X: 5 Y: 5.
+ cursor.reset_position();
+ // Print Back at X: 5 Y: 5.
+ print!("Back");
+
+ println!()
+}
+
diff --git a/examples/terminal/mod.rs b/examples/terminal/mod.rs
index d35998b..961bf3b 100644
--- a/examples/terminal/mod.rs
+++ b/examples/terminal/mod.rs
@@ -80,7 +80,7 @@ pub fn clear_until_new_line()
print_test_data();
// Set terminal cursor position (see example for more info).
- crossterm_cursor::get().goto(4,4);
+ crossterm_cursor::get().goto(4,7);
// Clear all the cells until next line.
terminal.clear(ClearType::UntilNewLine);
@@ -96,6 +96,14 @@ pub fn print_terminal_size()
print!("X: {}, y: {}", terminal_size.0, terminal_size.1);
}
+/// Set the terminal size to width 10, height: 10.
+pub fn set_terminal_size()
+{
+ let mut terminal = get();
+
+ terminal.set_size(10,10);
+}
+
// scroll down 10 lines
pub fn scroll_down()
{
@@ -103,7 +111,7 @@ pub fn scroll_down()
// Get terminal
let mut terminal = get();
// Scroll down 10 lines.
- let terminal_size = terminal.scroll_down(10);
+ terminal.scroll_down(10);
}
// scroll down 10 lines
@@ -114,5 +122,14 @@ pub fn scroll_up()
// Get terminal
let mut terminal = get();
// Scroll up 10 lines.
- let terminal_size = terminal.scroll_up(10);
+ terminal.scroll_up(10);
+}
+
+// Resize the terminal to X: 10, Y: 10
+pub fn resize_terminal()
+{
+ // Get terminal
+ let mut terminal = get();
+ // Get terminal size
+ terminal.set_size(1,1);
}
diff --git a/src/crossterm_cursor/ansi_cursor.rs b/src/crossterm_cursor/ansi_cursor.rs
index 2ddb5e1..a2021b7 100644
--- a/src/crossterm_cursor/ansi_cursor.rs
+++ b/src/crossterm_cursor/ansi_cursor.rs
@@ -44,4 +44,16 @@ impl ITerminalCursor for AnsiCursor {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}D"), count);
}
+
+ fn safe_position(&mut self)
+ {
+ let mut some_writer = io::stdout();
+ write!(&mut some_writer, csi!("s"));
+ }
+
+ fn reset_position(&self)
+ {
+ let mut some_writer = io::stdout();
+ write!(&mut some_writer, csi!("u"));
+ }
}
diff --git a/src/crossterm_cursor/base_cursor.rs b/src/crossterm_cursor/base_cursor.rs
index cac14ab..c91f749 100644
--- a/src/crossterm_cursor/base_cursor.rs
+++ b/src/crossterm_cursor/base_cursor.rs
@@ -20,4 +20,8 @@ pub trait ITerminalCursor {
fn move_down(&self, count: u16);
/// Move the cursor `n` times left.
fn move_left(&self, count: u16);
+ /// Save cursor position for recall later. Note that this position is stored program based not per instance of the cursor struct.
+ fn safe_position(&mut self);
+ /// Return to saved cursor position
+ fn reset_position(&self);
}
diff --git a/src/crossterm_cursor/cursor.rs b/src/crossterm_cursor/cursor.rs
index 2d0a35a..702f477 100644
--- a/src/crossterm_cursor/cursor.rs
+++ b/src/crossterm_cursor/cursor.rs
@@ -209,6 +209,52 @@ impl TerminalCursor {
std::io::stdout().flush();
self
}
+
+ /// Save cursor position for recall later.
+ ///
+ /// Note that this position is stored program based not per instance of the `Cursor` struct.
+ ///
+ /// #Example
+ ///
+ /// ```rust
+ ///
+ /// extern crate crossterm;
+ ///
+ /// use self::crossterm::crossterm_cursor::get;
+ ///
+ /// get().safe_position();
+ ///
+ /// ```
+ pub fn safe_position(&mut self)
+ {
+ &self.init();
+ if let Some(ref mut terminal_cursor) = self.terminal_cursor {
+ terminal_cursor.safe_position();
+ }
+ }
+
+ /// Return to saved cursor position
+ ///
+ /// Note that this method reset to the position set by `safe_position()` and that this position is stored program based not per instance of the `Cursor` struct.
+ ///
+ /// #Example
+ ///
+ /// ```rust
+ ///
+ /// extern crate crossterm;
+ ///
+ /// use self::crossterm::crossterm_cursor::get;
+ ///
+ /// get().reset_position();
+ ///
+ /// ```
+ pub fn reset_position(&mut self)
+ {
+ &self.init();
+ if let Some(ref terminal_cursor) = self.terminal_cursor {
+ terminal_cursor.reset_position();
+ }
+ }
}
/// Get the concrete ITerminalCursor implementation based on the current operating system.
diff --git a/src/crossterm_cursor/winapi_cursor.rs b/src/crossterm_cursor/winapi_cursor.rs
index c2733dc..328dd71 100644
--- a/src/crossterm_cursor/winapi_cursor.rs
+++ b/src/crossterm_cursor/winapi_cursor.rs
@@ -17,34 +17,40 @@ impl ITerminalCursor for WinApiCursor {
}
fn pos(&self) -> (i16, i16) {
- (cursor::xpos(), cursor::ypos())
+ cursor::pos()
}
fn move_up(&self, count: u16) {
- let xpos = cursor::xpos();
- let ypos = cursor::ypos();
-
+ let (xpos,ypos) = cursor::pos();
cursor::set(xpos, ypos - count as i16);
}
fn move_right(&self, count: u16) {
- let xpos = cursor::xpos();
- let ypos = cursor::ypos();
+ let (xpos,ypos) = cursor::pos();
cursor::set(xpos + count as i16, ypos);
}
fn move_down(&self, count: u16) {
- let xpos = cursor::xpos();
- let ypos = cursor::ypos();
+ let (xpos,ypos) = cursor::pos();
cursor::set(xpos, ypos + count as i16);
}
fn move_left(&self, count: u16) {
- let xpos = cursor::xpos();
- let ypos = cursor::ypos();
+ let (xpos,ypos) = cursor::pos();
cursor::set(xpos - count as i16, ypos);
}
+
+
+ fn safe_position(&mut self)
+ {
+ cursor::save_cursor_pos();
+ }
+
+ fn reset_position(&self)
+ {
+ cursor::reset_to_saved_position();
+ }
}
diff --git a/src/crossterm_mouse/mod.rs b/src/crossterm_mouse/mod.rs
new file mode 100644
index 0000000..e69de29
diff --git a/src/crossterm_style/color/ansi_color.rs b/src/crossterm_style/color/ansi_color.rs
index dc95cdc..bd1419f 100644
--- a/src/crossterm_style/color/ansi_color.rs
+++ b/src/crossterm_style/color/ansi_color.rs
@@ -3,7 +3,7 @@ use std::io::Write;
use std::string::String;
use Construct;
-use super::color::{Color, ColorType};
+use super::super::{Color, ColorType};
use super::base_color::ITerminalColor;
@@ -19,14 +19,13 @@ impl Construct for ANSIColor {
impl ITerminalColor for ANSIColor {
fn set_fg(&self, fg_color: Color) {
-
- let mut some_writer = io::stdout();
- write!(&mut some_writer, csi!("38;5;{}m"), self.color_value(fg_color, ColorType::Foreground));
+ let mut some_writer = io::stdout();
+ write!(&mut some_writer, csi!("{}m"), self.color_value(fg_color, ColorType::Foreground));
}
fn set_bg(&self, bg_color: Color) {
- let mut some_writer = io::stdout();
- write!(&mut some_writer, csi!("48;5;{}m"), self.color_value(bg_color, ColorType::Background));
+ let mut some_writer = io::stdout();
+ write!(&mut some_writer, csi!("{}m"), self.color_value(bg_color, ColorType::Background));
}
fn reset(&self) {
@@ -36,23 +35,41 @@ impl ITerminalColor for ANSIColor {
fn color_value(&self, color: Color, color_type: ColorType) -> String {
- // Construct ANSI escape color code string. ;1 is for the brightness
- match color {
- Color::Black => "0",
- Color::Red => "9",
- Color::DarkRed =>"1",
- Color::Green => "10",
- Color::DarkGreen => "2",
- Color::Yellow => "11",
- Color::DarkYellow => "3",
- Color::Blue => "12",
- Color::DarkBlue => "4",
- Color::Magenta => "13",
- Color::DarkMagenta => "5",
- Color::Cyan => "14",
- Color::DarkCyan => "6",
- Color::Grey => "15",
- Color::White => "7",
- }.to_string()
+ let mut ansi_value = String::new();
+
+ match color_type
+ {
+ ColorType::Foreground => {
+ ansi_value.push_str("38;")
+ },
+ ColorType::Background => {
+ ansi_value.push_str("48;")
+ },
+ }
+
+ let rgb_val;
+
+ let color_val = match color {
+ Color::Black => "5;0",
+ Color::Red => "5;9",
+ Color::DarkRed =>"5;1",
+ Color::Green => "5;10",
+ Color::DarkGreen => "5;2",
+ Color::Yellow => "5;11",
+ Color::DarkYellow => "5;3",
+ Color::Blue => "5;12",
+ Color::DarkBlue => "5;4",
+ Color::Magenta => "5;13",
+ Color::DarkMagenta => "5;5",
+ Color::Cyan => "5;14",
+ Color::DarkCyan => "5;6",
+ Color::Grey => "5;15",
+ Color::White => "5;7",
+ Color::Rgb{r,g,b} => { rgb_val = format!("2;{};{};{}", r,g,b); rgb_val.as_str()},
+ Color::AnsiValue(val) => { rgb_val = format!("5;{}",val); rgb_val.as_str() }
+ };
+
+ ansi_value.push_str(color_val);
+ ansi_value
}
-}
+}
\ No newline at end of file
diff --git a/src/crossterm_style/color/base_color.rs b/src/crossterm_style/color/base_color.rs
index 467c7b3..43d3efe 100644
--- a/src/crossterm_style/color/base_color.rs
+++ b/src/crossterm_style/color/base_color.rs
@@ -9,7 +9,7 @@
///! so that the color related actions can be preformed on both unix and windows systems.
///!
-use super::color::{Color, ColorType};
+use super::super::{Color, ColorType};
pub trait ITerminalColor {
/// Set the forground color to the given color.
diff --git a/src/crossterm_style/color/color.rs b/src/crossterm_style/color/color.rs
index 433162c..dd1b766 100644
--- a/src/crossterm_style/color/color.rs
+++ b/src/crossterm_style/color/color.rs
@@ -2,91 +2,18 @@
//! Like styling the font, foreground color and background color.
use std::fmt;
-use std::convert::From;
-use std::str::FromStr;
+use std::io;
use Construct;
use crossterm_style::{ObjectStyle, StyledObject};
use super::base_color::ITerminalColor;
+use super::super::Color;
#[cfg(unix)]
use super::ANSIColor;
#[cfg(windows)]
use super::WinApiColor;
-/// Colors that are available for coloring the termainal font.
-#[derive(Debug, Copy, Clone)]
-pub enum Color {
- Black,
-
- Red,
- DarkRed,
-
- Green,
- DarkGreen,
-
- Yellow,
- DarkYellow,
-
- Blue,
- DarkBlue,
-
- Magenta,
- DarkMagenta,
-
- Cyan,
- DarkCyan,
-
- Grey,
- White,
-}
-
-/// Color types that can be used to determine if the Color enum is an Fore- or Background Color
-#[derive(Debug, Copy, Clone)]
-pub enum ColorType {
- Background,
- Foreground,
-}
-
-impl<'a> From<&'a str> for Color {
- fn from(src: &str) -> Self {
- src.parse().unwrap_or(Color::White)
- }
-}
-
-impl From for Color {
- fn from(src: String) -> Self {
- src.parse().unwrap_or(Color::White)
- }
-}
-
-impl FromStr for Color {
- type Err = ();
-
- fn from_str(src: &str) -> Result {
- let src = src.to_lowercase();
-
- match src.as_ref() {
- "black" => Ok(Color::Black),
- "red" => Ok(Color::Red),
- "dark_red" => Ok(Color::DarkRed),
- "green" => Ok(Color::Green),
- "dark_green" => Ok(Color::DarkGreen),
- "yellow" => Ok(Color::Yellow),
- "dark_yellow" => Ok(Color::DarkYellow),
- "blue" => Ok(Color::Blue),
- "dark_blue" => Ok(Color::DarkBlue),
- "magenta" => Ok(Color::Magenta),
- "dark_magenta" => Ok(Color::DarkMagenta),
- "cyan" => Ok(Color::Cyan),
- "dark_cyan" => Ok(Color::DarkCyan),
- "grey" => Ok(Color::Grey),
- "white" => Ok(Color::White),
- _ => Ok(Color::White),
- }
- }
-}
-
/// Struct that stores an specific platform implementation for color related actions.
pub struct TerminalColor {
terminal_color: Option>,
@@ -171,6 +98,23 @@ impl TerminalColor {
terminal_color.reset();
}
}
+
+ /// Get available color count.
+ pub fn get_available_color_count(&self) -> io::Result
+ {
+ use std::env;
+
+ Ok(match env::var_os("TERM") {
+ Some(val) => {
+ if val.to_str().unwrap_or("").contains("256color") {
+ 256
+ } else {
+ 8
+ }
+ }
+ None => 8,
+ })
+ }
}
/// Get an concrete ITerminalColor implementation based on the current operating system.
@@ -237,3 +181,5 @@ where
{
ObjectStyle::new().apply_to(val)
}
+
+
diff --git a/src/crossterm_style/color/winapi_color.rs b/src/crossterm_style/color/winapi_color.rs
index 2e6bca9..42b9717 100644
--- a/src/crossterm_style/color/winapi_color.rs
+++ b/src/crossterm_style/color/winapi_color.rs
@@ -1,5 +1,5 @@
use Construct;
-use super::color::{ColorType, Color};
+use super::super::{ColorType, Color};
use super::base_color::ITerminalColor;
use kernel::windows_kernel;
diff --git a/src/crossterm_style/mod.rs b/src/crossterm_style/mod.rs
index fe8c2a6..b526f9d 100644
--- a/src/crossterm_style/mod.rs
+++ b/src/crossterm_style/mod.rs
@@ -5,3 +5,97 @@ pub use self::color::color::*;
pub use self::styles::objectstyle::ObjectStyle;
pub use self::styles::styledobject::StyledObject;
+
+use std::convert::From;
+use std::str::FromStr;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
+pub enum Attribute {
+ Bold = 1,
+ Dim = 2,
+ Italic = 3,
+ Underlined = 4,
+ SlowBlink = 5,
+ RapidBlink = 6,
+ Reverse = 7,
+ Hidden = 8,
+ CrossedOut = 9
+}
+
+/// Colors that are available for coloring the termainal font.
+#[derive(Debug, Copy, Clone)]
+pub enum Color {
+ Black,
+
+ Red,
+ DarkRed,
+
+ Green,
+ DarkGreen,
+
+ Yellow,
+ DarkYellow,
+
+ Blue,
+ DarkBlue,
+
+ Magenta,
+ DarkMagenta,
+
+ Cyan,
+ DarkCyan,
+
+ Grey,
+ White,
+
+ #[cfg(unix)]
+ Rgb { r: u8, g: u8, b:u8 },
+ #[cfg(unix)]
+ AnsiValue(u8)
+}
+
+/// Color types that can be used to determine if the Color enum is an Fore- or Background Color
+#[derive(Debug, Copy, Clone)]
+pub enum ColorType {
+ Background,
+ Foreground,
+}
+
+impl<'a> From<&'a str> for Color {
+ fn from(src: &str) -> Self {
+ src.parse().unwrap_or(Color::White)
+ }
+}
+
+impl From for Color {
+ fn from(src: String) -> Self {
+ src.parse().unwrap_or(Color::White)
+ }
+}
+
+impl FromStr for Color {
+ type Err = ();
+
+ fn from_str(src: &str) -> Result {
+ let src = src.to_lowercase();
+
+ match src.as_ref() {
+ "black" => Ok(Color::Black),
+ "red" => Ok(Color::Red),
+ "dark_red" => Ok(Color::DarkRed),
+ "green" => Ok(Color::Green),
+ "dark_green" => Ok(Color::DarkGreen),
+ "yellow" => Ok(Color::Yellow),
+ "dark_yellow" => Ok(Color::DarkYellow),
+ "blue" => Ok(Color::Blue),
+ "dark_blue" => Ok(Color::DarkBlue),
+ "magenta" => Ok(Color::Magenta),
+ "dark_magenta" => Ok(Color::DarkMagenta),
+ "cyan" => Ok(Color::Cyan),
+ "dark_cyan" => Ok(Color::DarkCyan),
+ "grey" => Ok(Color::Grey),
+ "white" => Ok(Color::White),
+ _ => Ok(Color::White),
+ }
+ }
+}
diff --git a/src/crossterm_style/styles/objectstyle.rs b/src/crossterm_style/styles/objectstyle.rs
index 7d031b8..e43d82b 100644
--- a/src/crossterm_style/styles/objectstyle.rs
+++ b/src/crossterm_style/styles/objectstyle.rs
@@ -1,11 +1,16 @@
use crossterm_style::{Color, StyledObject};
use std::fmt::Display;
+use super::super::Attribute;
+
/// Struct that contains the style properties that can be applied to an displayable object.
#[derive(Clone)]
pub struct ObjectStyle {
pub fg_color: Option,
pub bg_color: Option,
+
+ #[cfg(unix)]
+ pub attrs: Vec
}
impl Default for ObjectStyle {
@@ -13,6 +18,8 @@ impl Default for ObjectStyle {
ObjectStyle {
fg_color: Some(Color::White),
bg_color: Some(Color::Black),
+ #[cfg(unix)]
+ attrs: Vec::new()
}
}
}
@@ -34,6 +41,8 @@ impl ObjectStyle {
return ObjectStyle {
fg_color: None,
bg_color: None,
+ #[cfg(unix)]
+ attrs: Vec::new()
};
}
@@ -48,4 +57,10 @@ impl ObjectStyle {
self.fg_color = Some(color);
self
}
+
+ #[cfg(unix)]
+ pub fn add_attr(&mut self, attr: Attribute)
+ {
+ self.attrs.push(attr);
+ }
}
diff --git a/src/crossterm_style/styles/styledobject.rs b/src/crossterm_style/styles/styledobject.rs
index 4415e00..4f239bf 100644
--- a/src/crossterm_style/styles/styledobject.rs
+++ b/src/crossterm_style/styles/styledobject.rs
@@ -2,6 +2,8 @@ use std;
use std::fmt;
use std::io::Write;
+use super::super::Attribute;
+
use crossterm_style::{Color, ObjectStyle};
/// Struct that contains both the style and the content wits will be styled.
@@ -11,21 +13,24 @@ pub struct StyledObject {
}
impl StyledObject {
- /// Sets the foreground of the styled object to the passed `Color`
+ /// Set the foreground of the styled object to the passed `Color`
///
/// #Example
///
/// ```rust
- /// // create an styled object with the foreground color red.
- /// let styledobject = paint("I am colored red").with(Color::Red);
- /// // create an styled object with the foreground color blue.
- /// let styledobject1 = paint("I am colored blue").with(Color::Blue);
+ /// extern crate crossterm;
+ /// use self::crossterm::crossterm_style::{paint,Color};
///
- /// // print the styledobject to see the result
- /// println!("{}", styledobject);
- /// println!("{}", styledobject1);
- /// // print an styled object directly.
- /// println!("{}", paint("I am colored green").with(Color::Green));
+ /// // create an styled object with the foreground color red.
+ /// let styledobject = paint("I am colored red").with(Color::Red);
+ /// // create an styled object with the foreground color blue.
+ /// let styledobject1 = paint("I am colored blue").with(Color::Blue);
+ ///
+ /// // print the styledobject to see the result
+ /// println!("{}", styledobject);
+ /// println!("{}", styledobject1);
+ /// // print an styled object directly.
+ /// println!("{}", paint("I am colored green").with(Color::Green));
///
/// ```
pub fn with(mut self, foreground_color: Color) -> StyledObject {
@@ -33,28 +38,68 @@ impl StyledObject {
self
}
- /// Sets the background of the styled object to the passed `Color`
+ /// Set the background of the styled object to the passed `Color`
///
/// #Example
///
- /// ```rust
- ///
- /// // create an styled object with the background color red.
- /// let styledobject = paint("I am colored red").on(Color::Red);
- /// // create an styled object with the background color blue.
- /// let styledobject1 = paint("I am colored blue").on(Color::Blue);
+ /// ```rust
+ /// extern crate crossterm;
+ /// use self::crossterm::crossterm_style::{paint,Color};
///
- /// // print the styledobjects
- /// println!("{}", styledobject);
- /// println!("{}", styledobject1);
- /// // print an styled object directly.
- /// println!("{}", paint("I am colored green").on(Color::Green))
+ /// // create an styled object with the background color red.
+ /// let styledobject = paint("I am colored red").on(Color::Red);
+ /// // create an styled object with the background color blue.
+ /// let styledobject1 = paint("I am colored blue").on(Color::Blue);
+ ///
+ /// // print the styledobjects
+ /// println!("{}", styledobject);
+ /// println!("{}", styledobject1);
+ /// // print an styled object directly.
+ /// println!("{}", paint("I am colored green").on(Color::Green))
///
/// ```
pub fn on(mut self, background_color: Color) -> StyledObject {
self.object_style = self.object_style.bg(background_color);
self
}
+
+ /// Set the attribute of an styled object to the passed `Attribute`
+ ///
+ /// #Example
+ ///
+ /// ```rust
+ ///
+ /// extern crate crossterm;
+ /// use self::crossterm::crossterm_style::{paint,Attribute};
+ ///
+ /// println!("{}", paint("Bold").attr(Attribute::Bold));
+ ///
+ /// ```
+ #[cfg(unix)]
+ pub fn attr(mut self, attr: Attribute) -> StyledObject
+ {
+ &self.object_style.add_attr(attr);
+ self
+ }
+
+ /// Increase the font intensity.
+ #[cfg(unix)]#[inline(always)] pub fn bold(self) -> StyledObject { self.attr(Attribute::Bold) }
+ /// Faint (decreased intensity) (Not widely supported).
+ #[cfg(unix)]#[inline(always)] pub fn dim(self) -> StyledObject { self.attr(Attribute::Dim) }
+ /// Make the font italic (Not widely supported; Sometimes treated as inverse).
+ #[cfg(unix)]#[inline(always)] pub fn italic(self) -> StyledObject { self.attr(Attribute::Italic) }
+ /// Underline font.
+ #[cfg(unix)]#[inline(always)] pub fn underlined(self) -> StyledObject { self.attr(Attribute::Underlined) }
+ /// Slow Blink (less than 150 per minute; not widely supported).
+ #[cfg(unix)]#[inline(always)] pub fn slow_blink(self) -> StyledObject { self.attr(Attribute::SlowBlink) }
+ /// Rapid Blink (MS-DOS ANSI.SYS; 150+ per minute; not widely supported).
+ #[cfg(unix)]#[inline(always)] pub fn rapid_blink(self) -> StyledObject { self.attr(Attribute::RapidBlink) }
+ /// Swap foreground and background colors.
+ #[cfg(unix)]#[inline(always)] pub fn reverse(self) -> StyledObject { self.attr(Attribute::Reverse) }
+ /// Hide text (Not widely supported).
+ #[cfg(unix)]#[inline(always)] pub fn hidden(self) -> StyledObject { self.attr(Attribute::Hidden) }
+ /// Characters legible, but marked for deletion. Not widely supported.
+ #[cfg(unix)]#[inline(always)] pub fn crossed_out(self) -> StyledObject { self.attr(Attribute::CrossedOut) }
}
/// This is used to make StyledObject able to be displayed.
@@ -78,6 +123,13 @@ macro_rules! impl_fmt
colored_terminal.set_fg(fg);
reset = true;
}
+
+ #[cfg(unix)]
+ for attr in self.object_style.attrs.iter() {
+ write!(f, csi!("{}m"), *attr as i16);
+ reset = true;
+ }
+
fmt::$name::fmt(&self.content, f)?;
std::io::stdout().flush().expect("Flush stdout failed");
diff --git a/src/crossterm_terminal/ansi_terminal.rs b/src/crossterm_terminal/ansi_terminal.rs
index db1774d..332bb42 100644
--- a/src/crossterm_terminal/ansi_terminal.rs
+++ b/src/crossterm_terminal/ansi_terminal.rs
@@ -50,4 +50,9 @@ impl ITerminal for UnixTerminal {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}T"), count);
}
+
+ fn set_size(&self, width: i16, height: i16) {
+ let mut some_writer = io::stdout();
+ write!(&mut some_writer, csi!("8;{};{}t"), width, height);
+ }
}
diff --git a/src/crossterm_terminal/base_terminal.rs b/src/crossterm_terminal/base_terminal.rs
index e82409d..b2b0716 100644
--- a/src/crossterm_terminal/base_terminal.rs
+++ b/src/crossterm_terminal/base_terminal.rs
@@ -16,4 +16,6 @@ pub trait ITerminal {
fn scroll_up(&self, count: i16);
/// Scroll `n` lines down in the current terminal.
fn scroll_down(&self, count: i16);
+ /// Resize terminal to the given width and height.
+ fn set_size(&self,width: i16, height: i16);
}
diff --git a/src/crossterm_terminal/terminal.rs b/src/crossterm_terminal/terminal.rs
index 70c298a..80c890e 100644
--- a/src/crossterm_terminal/terminal.rs
+++ b/src/crossterm_terminal/terminal.rs
@@ -120,6 +120,31 @@ impl Terminal {
terminal.scroll_down(count);
}
}
+
+ /// Set the terminal size. Note that not all terminals can be set to a very small scale.
+ ///
+ /// #Example
+ ///
+ /// ```rust
+ ///
+ /// extern crate crossterm;
+ /// use crossterm::crossterm_terminal;
+ ///
+ /// let mut term = crossterm_terminal::get();
+ ///
+ /// // Set of the size to X: 10 and Y: 10
+ /// let size = term.set_size(10,10);
+ ///
+ /// ```
+ pub fn set_size(&mut self, width: i16, height: i16)
+ {
+ &self.init();
+
+ if let Some (ref terminal) = self.terminal
+ {
+ terminal.set_size(width,height);
+ }
+ }
}
/// Get the concrete ITerminal implementation based on the current operating system.
diff --git a/src/crossterm_terminal/winapi_terminal.rs b/src/crossterm_terminal/winapi_terminal.rs
index 3f19a7a..72032c4 100644
--- a/src/crossterm_terminal/winapi_terminal.rs
+++ b/src/crossterm_terminal/winapi_terminal.rs
@@ -35,4 +35,6 @@ impl ITerminal for WinApiTerminal {
fn scroll_down(&self, count: i16) {
terminal::scroll_down(count as i16);
}
+
+ fn set_size(&self, width: i16, height: i16) { terminal::resize_terminal(width,height); }
}
diff --git a/src/kernel/windows_kernel/ansi_support.rs b/src/kernel/windows_kernel/ansi_support.rs
index 0074d13..fb87a58 100644
--- a/src/kernel/windows_kernel/ansi_support.rs
+++ b/src/kernel/windows_kernel/ansi_support.rs
@@ -1,18 +1,7 @@
-use winapi::shared::ntdef::HANDLE;
-use winapi::um::consoleapi::SetConsoleMode;
-
-use super::handle;
+use super::kernel;
/// Enables ansi for windows terminals.
pub fn enable_ansi_support() {
let enable_ansi_code: u32 = 7;
- let output_handle = handle::get_output_handle();
- set_console_mode(output_handle, enable_ansi_code)
-}
-
-/// Set the console mode of the windows terminal.
-fn set_console_mode(handle: HANDLE, console_mode: u32) {
- unsafe {
- SetConsoleMode(handle, console_mode);
- }
-}
+ kernel::set_console_mode(enable_ansi_code);
+}
\ No newline at end of file
diff --git a/src/kernel/windows_kernel/color.rs b/src/kernel/windows_kernel/color.rs
index d2e78bd..018b7ad 100644
--- a/src/kernel/windows_kernel/color.rs
+++ b/src/kernel/windows_kernel/color.rs
@@ -1,10 +1,9 @@
use winapi::um::wincon;
-use super::{handle, kernel};
+
+use super::{kernel};
use crossterm_style as style;
-use winapi::um::wincon::{SetConsoleTextAttribute};
-
-/// This will set the forground color by the given winapi color value parsed to u16.
+/// This will set the foreground color by the given winapi color.
pub fn set_fg_color(fg_color: u16) {
let csbi = kernel::get_console_screen_buffer_info();
@@ -21,10 +20,10 @@ pub fn set_fg_color(fg_color: u16) {
color = color | wincon::BACKGROUND_INTENSITY as u16;
}
- set_console_text_attribute(color);
+ kernel::set_console_text_attribute(color);
}
-/// This will set the forground color by the given winapi color value parsed to u16.
+/// This will set the background color by the given winapi color value.
pub fn set_bg_color(bg_color: u16) {
let csbi = kernel::get_console_screen_buffer_info();
// Notice that the color values are stored in wAttribute.
@@ -34,21 +33,21 @@ pub fn set_bg_color(bg_color: u16) {
let fg_color = attrs & 0x0007;
color = fg_color | bg_color;
- // foreground intensity is a seperate value in attrs,
+ // foreground intensity is a separate value in attrs,
// wee need to check if this was applied to the current fg color.
if (attrs & wincon::FOREGROUND_INTENSITY as u16) != 0 {
color = color | wincon::FOREGROUND_INTENSITY as u16;
}
- set_console_text_attribute(color);
+ kernel::set_console_text_attribute(color);
}
-/// This will reset the colors to the value given in u16.
+/// This will reset the colors to the given winapi color value.
pub fn reset(original_color: u16) {
- set_console_text_attribute(original_color);
+ kernel::set_console_text_attribute(original_color);
}
-/// This will get the winapi color value from the Color struct
+/// This will get the winapi color value from the Color and ColorType struct
pub fn winapi_color_val(color: style::Color, color_type: style::ColorType) -> u16 {
use crossterm_style::{Color, ColorType};
@@ -107,12 +106,3 @@ pub fn winapi_color_val(color: style::Color, color_type: style::ColorType) -> u1
winapi_color as u16
}
-
-/// This will set the console attributes by the given value
-fn set_console_text_attribute(value: u16) {
- let output_handle = handle::get_output_handle();
-
- unsafe {
- SetConsoleTextAttribute(output_handle, value);
- }
-}
diff --git a/src/kernel/windows_kernel/cursor.rs b/src/kernel/windows_kernel/cursor.rs
index 7e231eb..e719b9c 100644
--- a/src/kernel/windows_kernel/cursor.rs
+++ b/src/kernel/windows_kernel/cursor.rs
@@ -1,53 +1,35 @@
-use winapi::um::wincon::COORD;
-use super::{handle, kernel};
-use shared::functions;
+use super::kernel;
-use winapi::um::wincon::{SetConsoleCursorPosition};
+/// This stores the cursor pos, at program level. So it can be recalled later.
+static mut SAVED_CURSOR_POS:(i16,i16) = (0,0);
-
-/// Set the cursor position to an coordinate (x,y).
-pub fn set(x: i16, y: i16) {
- set_cursor_pos(x as i16, y as i16);
+/// Set the current cursor position to X and Y
+pub fn set(x: i16, y: i16)
+{
+ kernel::set_console_cursor_position(x, y );
}
-/// Get the current cursor x position.
-pub fn xpos() -> i16 {
- let csbi = kernel::get_console_screen_buffer_info();
- csbi.dwCursorPosition.X
-}
-
-/// Get the current cursor y position.
-pub fn ypos() -> i16 {
- let csbi = kernel::get_console_screen_buffer_info();
- csbi.dwCursorPosition.Y
-}
-
-pub fn move_down(count: u16) {
- let csbi = kernel::get_console_screen_buffer_info();
+/// Reset to saved cursor position
+pub fn reset_to_saved_position()
+{
unsafe {
- let output_handle = handle::get_output_handle();
- SetConsoleCursorPosition(
- output_handle,
- COORD {
- X: csbi.dwCursorPosition.X,
- Y: csbi.dwCursorPosition.Y + count as i16,
- },
- );
+ kernel::set_console_cursor_position(SAVED_CURSOR_POS.0, SAVED_CURSOR_POS.1);
}
}
-/// Set the cursor position to an coordinate (x,y).
-fn set_cursor_pos(x: i16, y: i16) {
- functions::is_cursor_out_of_range(x, y);
-
- let output_handle = handle::get_output_handle();
- let position = COORD { X: x, Y: y };
+/// Save current cursor position to recall later.
+pub fn save_cursor_pos()
+{
+ let position = pos();
unsafe {
- let success = SetConsoleCursorPosition(output_handle, position);
-
- if success == 0 {
- panic!("Cannot set console cursor position");
- }
+ SAVED_CURSOR_POS = (position.0, position.1);
}
}
+
+/// Get current cursor position (X,Y)
+pub fn pos() -> (i16,i16)
+{
+ let csbi = kernel::get_console_screen_buffer_info();
+ ( csbi.dwCursorPosition.X , csbi.dwCursorPosition.Y )
+}
\ No newline at end of file
diff --git a/src/kernel/windows_kernel/handle.rs b/src/kernel/windows_kernel/handle.rs
deleted file mode 100644
index 43bc8c9..0000000
--- a/src/kernel/windows_kernel/handle.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use winapi::um::winnt;
-use winapi::um::winbase;
-use winapi::um::handleapi;
-
-use winapi::um::processenv::{GetStdHandle};
-
-// static mut CONSOLE_INPUT_HANDLE:Option = None;
-static mut CONSOLE_OUTPUT_HANDLE: Option = None;
-
-/// Get the std_output_handle of the console
-pub fn get_output_handle() -> winnt::HANDLE {
- unsafe {
- if let Some(handle) = CONSOLE_OUTPUT_HANDLE {
- handle
- } else {
- let handle = GetStdHandle(winbase::STD_OUTPUT_HANDLE);
- CONSOLE_OUTPUT_HANDLE = Some(handle);
- handle
- }
- }
-}
-
-/// Checks if the console handle is an invalid handle value.
-pub fn is_valid_handle(handle: &winnt::HANDLE) -> bool {
- if *handle == handleapi::INVALID_HANDLE_VALUE {
- true
- } else {
- false
- }
-}
-
diff --git a/src/kernel/windows_kernel/kernel.rs b/src/kernel/windows_kernel/kernel.rs
index 07fbc31..0ee22c9 100644
--- a/src/kernel/windows_kernel/kernel.rs
+++ b/src/kernel/windows_kernel/kernel.rs
@@ -1,16 +1,46 @@
-use winapi::um::wincon::{GetConsoleScreenBufferInfo,CONSOLE_SCREEN_BUFFER_INFO};
-use super::{handle, Empty};
+use winapi::um::winnt::HANDLE;
+use winapi::um::winbase::STD_OUTPUT_HANDLE;
+use winapi::um::handleapi::INVALID_HANDLE_VALUE;
+use winapi::um::processenv::{GetStdHandle};
+use winapi::um::consoleapi::{SetConsoleMode};
+use winapi::um::wincon::{ SetConsoleWindowInfo, SetConsoleCursorPosition, SetConsoleTextAttribute, SetConsoleScreenBufferSize,
+ GetLargestConsoleWindowSize, GetConsoleScreenBufferInfo,
+ FillConsoleOutputCharacterA, FillConsoleOutputAttribute,
+ CONSOLE_SCREEN_BUFFER_INFO, SMALL_RECT, COORD
+};
+
+use super::{Empty};
+
+static mut CONSOLE_OUTPUT_HANDLE: Option = None;
+
+/// Get the std_output_handle of the console
+pub fn get_output_handle() -> HANDLE {
+ unsafe {
+ if let Some(handle) = CONSOLE_OUTPUT_HANDLE {
+ handle
+ } else {
+ let handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_OUTPUT_HANDLE = Some(handle);
+ handle
+ }
+ }
+}
+
+/// Checks if the console handle is an invalid handle value.
+pub fn is_valid_handle(handle: &HANDLE) -> bool {
+ if *handle == INVALID_HANDLE_VALUE {
+ true
+ } else {
+ false
+ }
+}
/// Get console screen buffer info.
pub fn get_console_screen_buffer_info() -> CONSOLE_SCREEN_BUFFER_INFO {
- let output_handle = handle::get_output_handle();
+ let output_handle = get_output_handle();
let mut csbi = CONSOLE_SCREEN_BUFFER_INFO::empty();
let success;
- if handle::is_valid_handle(&output_handle) {
- return CONSOLE_SCREEN_BUFFER_INFO::empty();
- }
-
unsafe { success = GetConsoleScreenBufferInfo(output_handle, &mut csbi) }
if success == 0 {
@@ -20,8 +50,129 @@ pub fn get_console_screen_buffer_info() -> CONSOLE_SCREEN_BUFFER_INFO {
csbi
}
-/// Get the current console colors.
+pub fn get_largest_console_window_size() -> COORD
+{
+ let output_handle = get_output_handle();
+
+ unsafe {
+ GetLargestConsoleWindowSize(output_handle)
+ }
+}
+
pub fn get_original_console_color() -> u16 {
let console_buffer_info = get_console_screen_buffer_info();
console_buffer_info.wAttributes as u16
}
+
+pub fn set_console_mode(console_mode: u32)
+{
+ let output_handle = get_output_handle();
+
+ unsafe {
+ SetConsoleMode(output_handle, console_mode);
+ }
+}
+
+pub fn set_console_cursor_position(x: i16, y: i16)
+{
+ if x < 0 || x >= ::max_value() {
+ panic!("X: {}, Argument Out of Range Exception", x);
+ }
+
+ if y < 0 || y >= ::max_value() {
+ panic!("Y: {}, Argument Out of Range Exception", y);
+ }
+
+ let output_handle = get_output_handle();
+ let position = COORD { X: x, Y: y };
+
+ unsafe {
+ let success = SetConsoleCursorPosition(output_handle, position);
+
+ if success == 0 {
+ panic!("Argument out of range.");
+ }
+ }
+}
+
+pub fn set_console_text_attribute(value: u16)
+{
+ let output_handle = get_output_handle();
+
+ unsafe {
+ SetConsoleTextAttribute(output_handle, value);
+ }
+}
+
+pub fn set_console_info(absolute: bool, rect: &SMALL_RECT) -> bool
+{
+
+ let output_handle = get_output_handle();
+
+ let absolute = match absolute { true => 1, false => 0, };
+ unsafe
+ {
+ let success = SetConsoleWindowInfo(output_handle,absolute ,rect);
+ is_true(success)
+ }
+}
+
+pub fn set_console_screen_buffer_size( size: COORD) -> bool
+{
+ let output_handle = get_output_handle();
+
+ unsafe
+ {
+ let success = SetConsoleScreenBufferSize(output_handle, size);
+ is_true(success)
+ }
+}
+
+pub fn fill_console_output_character(cells_written: &mut u32, start_location: COORD, cells_to_write: u32) -> bool
+{
+ let output_handle = get_output_handle();
+
+ unsafe {
+ // fill the cells in console with blanks
+ let success = FillConsoleOutputCharacterA (
+ output_handle,
+ ' ' as i8,
+ cells_to_write,
+ start_location,
+ cells_written,
+ );
+ is_true(success)
+ }
+}
+
+pub fn fill_console_output_attribute(cells_written: &mut u32, start_location: COORD, cells_to_write: u32) -> bool
+{
+ // Get the position of the current console window
+ let csbi = get_console_screen_buffer_info();
+ let output_handle = get_output_handle();
+
+ let success;
+
+ unsafe {
+ success = FillConsoleOutputAttribute (
+ output_handle,
+ csbi.wAttributes,
+ cells_to_write,
+ start_location,
+ cells_written,
+ );
+ }
+
+ is_true(success)
+}
+
+/// Parse integer to an bool
+fn is_true(value: i32) -> bool
+{
+ if value == 0{
+ false
+ }
+ else{
+ true
+ }
+}
diff --git a/src/kernel/windows_kernel/mod.rs b/src/kernel/windows_kernel/mod.rs
index 4e132bb..3f0d4d7 100644
--- a/src/kernel/windows_kernel/mod.rs
+++ b/src/kernel/windows_kernel/mod.rs
@@ -1,7 +1,6 @@
pub mod cursor;
pub mod color;
pub mod ansi_support;
-pub mod handle;
pub mod kernel;
pub mod terminal;
mod winapi_extentions;
diff --git a/src/kernel/windows_kernel/terminal.rs b/src/kernel/windows_kernel/terminal.rs
index 58a0762..e7851cc 100644
--- a/src/kernel/windows_kernel/terminal.rs
+++ b/src/kernel/windows_kernel/terminal.rs
@@ -1,8 +1,5 @@
-use super::{cursor, handle, kernel};
-
-use winapi;
-use winapi::shared::ntdef::TRUE;
-use winapi::um::wincon::{SetConsoleWindowInfo,FillConsoleOutputCharacterA, FillConsoleOutputAttribute, COORD, CONSOLE_SCREEN_BUFFER_INFO};
+use super::{cursor, kernel};
+use winapi::um::wincon::{SMALL_RECT, COORD};
/// Get the terminal size (y,x)
pub fn terminal_size() -> Option<(u16, u16)> {
@@ -16,7 +13,6 @@ pub fn terminal_size() -> Option<(u16, u16)> {
/// Scroll down `n` rows
pub fn scroll_down(rows: i16) {
- let output_handle = handle::get_output_handle();
let csbi = kernel::get_console_screen_buffer_info();
let mut srct_window;
@@ -28,22 +24,16 @@ pub fn scroll_down(rows: i16) {
srct_window.Top += rows; // move top down
srct_window.Bottom += rows; // move bottom down
- unsafe {
- if SetConsoleWindowInfo(output_handle, TRUE as i32, &mut srct_window) != 1 {
- panic!("Something whent wrong when scrolling down");
+ let success = kernel::set_console_info(true, &mut srct_window);
+ if success {
+ panic!("Something went wrong when scrolling down");
}
- }
}
}
pub fn clear_after_cursor() {
- let output_handle = handle::get_output_handle();
let csbi = kernel::get_console_screen_buffer_info();
-
- // one cell after cursor position
- let mut x = cursor::xpos() as i16 ;
- // one at row of cursor position
- let mut y = cursor::ypos() as i16;
+ let (mut x,mut y) = cursor::pos();
// if cursor position is at the outer right position
if x > csbi.dwSize.X
@@ -53,16 +43,16 @@ pub fn clear_after_cursor() {
}
// location where to start clearing
- let start_loaction = COORD { X: x, Y: y };
+ let start_location = COORD { X: x, Y: y };
// get sum cells before cursor
let cells_to_write = csbi.dwSize.X as u32 * csbi.dwSize.Y as u32;
- clear(output_handle, csbi, start_loaction,cells_to_write);
+ clear(start_location,cells_to_write);
}
pub fn clear_before_cursor() {
- let output_handle = handle::get_output_handle();
let csbi = kernel::get_console_screen_buffer_info();
+ let (xpos,ypos) = cursor::pos();
// one cell after cursor position
let x = 0;
@@ -70,30 +60,27 @@ pub fn clear_before_cursor() {
let y = 0;
// location where to start clearing
- let start_loaction = COORD { X: x, Y: y };
+ let start_location = COORD { X: x, Y: y };
// get sum cells before cursor
- let cells_to_write = (csbi.dwSize.X as u32 * cursor::ypos() as u32) + (cursor::xpos()) as u32;
+ let cells_to_write = (csbi.dwSize.X as u32 * ypos as u32) + (xpos as u32 + 1);
- // println!("{:?}", (csbi.dwSize.X as u32 * (cursor::ypos() - 1) as u32));
- clear(output_handle, csbi, start_loaction, cells_to_write);
+ clear(start_location, cells_to_write);
}
pub fn clear_entire_screen() {
- let output_handle = handle::get_output_handle();
let csbi = kernel::get_console_screen_buffer_info();
-
// position x at start
let x = 0;
// position y at start
let y = 0;
// location where to start clearing
- let start_loaction = COORD { X: x, Y: y };
+ let start_location = COORD { X: x, Y: y };
// get sum cells before cursor
let cells_to_write = csbi.dwSize.X as u32 * csbi.dwSize.Y as u32;
- clear(output_handle, csbi, start_loaction, cells_to_write);
+ clear( start_location, cells_to_write);
// put the cursor back at (0, 0)
cursor::set(0, 0);
@@ -101,21 +88,19 @@ pub fn clear_entire_screen() {
pub fn clear_current_line()
{
- let output_handle = handle::get_output_handle();
let csbi = kernel::get_console_screen_buffer_info();
-
// position x at start
let x = 0;
// position y at start
- let y = cursor::ypos();
+ let y = cursor::pos().1;
// location where to start clearing
- let start_loaction = COORD { X: x, Y: y };
+ let start_location = COORD { X: x, Y: y };
// get sum cells before cursor
let cells_to_write = csbi.dwSize.X as u32;
- clear(output_handle, csbi, start_loaction, cells_to_write);
+ clear(start_location, cells_to_write);
// put the cursor back at (0, 0)
cursor::set(x, y);
@@ -123,62 +108,114 @@ pub fn clear_current_line()
pub fn clear_until_line()
{
- let output_handle = handle::get_output_handle();
let csbi = kernel::get_console_screen_buffer_info();
-
- // position x at start
- let x = cursor::xpos();
- // position y at start
- let y = cursor::ypos();
+ let (x,y) = cursor::pos();
// location where to start clearing
- let start_loaction = COORD { X: x -1, Y: y };
+ let start_location = COORD { X: x, Y: y };
// get sum cells before cursor
- let cells_to_write = (csbi.dwSize.X - x) as u32 - 1;
+ let cells_to_write = (csbi.dwSize.X - x) as u32;
- clear(output_handle, csbi, start_loaction, cells_to_write);
+ clear(start_location, cells_to_write);
// put the cursor back at (0, 0)
cursor::set(x, y);
}
+pub fn resize_terminal(width: i16, height: i16)
+{
+ if width <= 0
+ {
+ panic!("Cannot set the terminal width lower than 1");
+ }
+
+ if height <= 0
+ {
+ panic!("Cannot set the terminal height lower then 1")
+ }
+
+ // Get the position of the current console window
+ let csbi = kernel::get_console_screen_buffer_info();
+ let mut success = false;
+
+ // If the buffer is smaller than this new window size, resize the
+ // buffer to be large enough. Include window position.
+ let mut resize_buffer = false;
+ let mut size = COORD { X: csbi.dwSize.X, Y: csbi.dwSize.Y };
+
+ if csbi.dwSize.X < csbi.srWindow.Left + width
+ {
+ if csbi.srWindow.Left >= i16::max_value() - width
+ {
+ panic!("Argument out of range when setting terminal width.");
+ }
+
+ size.X = csbi.srWindow.Left + width;
+ resize_buffer = true;
+ }
+ if csbi.dwSize.Y < csbi.srWindow.Top + height {
+ if csbi.srWindow.Top >= i16::max_value() - height
+ {
+ panic!("Argument out of range when setting terminal height");
+ }
+
+ size.Y = csbi.srWindow.Top + height;
+ resize_buffer = true;
+ }
+
+ if resize_buffer {
+ success = kernel::set_console_screen_buffer_size(size);
+
+ if !success
+ {
+ panic!("Something went wrong when setting screen buffer size.");
+ }
+ }
+
+ let mut fsr_window: SMALL_RECT = csbi.srWindow;
+ // Preserve the position, but change the size.
+ fsr_window.Bottom = fsr_window.Top + height;
+ fsr_window.Right = fsr_window.Left + width;
+
+ let success = kernel::set_console_info(true, &fsr_window);
+
+ if success {
+ // If we resized the buffer, un-resize it.
+ if resize_buffer {
+ kernel::set_console_screen_buffer_size(csbi.dwSize);
+ }
+
+ let bounds = kernel::get_largest_console_window_size();
+
+ if width > bounds.X
+ {
+ panic!("Argument width: {} out of range when setting terminal width.", width);
+ }
+ if height > bounds.Y
+ {
+ panic!("Argument height: {} out of range when setting terminal height", height);
+ }
+ }
+}
+
fn clear(
- handle: winapi::um::winnt::HANDLE,
- csbi: CONSOLE_SCREEN_BUFFER_INFO,
start_loaction: COORD,
cells_to_write: u32
) {
let mut cells_written = 0;
- let mut success;
+ let mut success = false;
- unsafe {
- // fill the cells in console with blanks
- success = FillConsoleOutputCharacterA (
- handle,
- ' ' as i8,
- cells_to_write,
- start_loaction,
- &mut cells_written,
- );
- }
+ success = kernel::fill_console_output_character(&mut cells_written,start_loaction,cells_to_write);
- if success == 0 {
- panic!("Couldnot clear screen after cursor");
+ if !success {
+ panic!("Could not clear screen after cursor");
}
cells_written = 0;
- unsafe {
- success = FillConsoleOutputAttribute (
- handle,
- csbi.wAttributes,
- cells_to_write,
- start_loaction,
- &mut cells_written,
- );
- }
+ success = kernel::fill_console_output_attribute(&mut cells_written,start_loaction, cells_to_write);
- if success == 0 {
+ if !success {
panic!("Couldnot reset attributes after cursor");
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 0c45579..13f3459 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,7 @@
#[macro_use]
mod shared;
mod kernel;
+
pub mod crossterm_cursor;
pub mod crossterm_style;
pub mod crossterm_terminal;
diff --git a/src/shared/functions.rs b/src/shared/functions.rs
deleted file mode 100644
index 6229242..0000000
--- a/src/shared/functions.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub fn is_cursor_out_of_range(x: i16, y: i16) {
- if x < 0 || x >= ::max_value() {
- panic!("Argument Out of Range Exception");
- }
-
- if y < 0 || y >= ::max_value() {
- panic!("Argument Out of Range Exception");
- }
-}
diff --git a/src/shared/mod.rs b/src/shared/mod.rs
index a507168..65134bb 100644
--- a/src/shared/mod.rs
+++ b/src/shared/mod.rs
@@ -1,4 +1,3 @@
#[macro_use]
pub mod macros;
pub mod traits;
-pub mod functions;
diff --git a/src/shared/traits.rs b/src/shared/traits.rs
index 0861ab4..edaeef6 100644
--- a/src/shared/traits.rs
+++ b/src/shared/traits.rs
@@ -6,7 +6,7 @@ pub trait Construct {
Self: Sized;
}
-/// This trait is used to create an empty instance of an struct.
+/// This trait can be used to create an empty instance of an struct.
pub trait Empty {
fn empty() -> Self;
}
diff --git a/todo.txt b/todo.txt
index a120d56..51316d2 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1 +1,15 @@
-Windows logic clear aan passen before after cursor
\ No newline at end of file
+Windows logic clear aan passen before after cursor
+
+ideas:
+
+https://apple.stackexchange.com/questions/33736/can-a-terminal-window-be-resized-with-a-terminal-command
+
+
+
+new inplemented:
+
+Safe and restore cursor
+Resize terminal
+Styling font with attributes
+RGB color option added for unix
+ANSI cutom color value input added for unix
\ No newline at end of file