Added resizing terminal. Styling font with attributes for unix systems inplemented. Windows kernel refactored and cleared out some grammer mistakes. (Windows tested and unix jet to be tested).

This commit is contained in:
T 2018-01-25 18:26:08 +01:00
parent 34e3ebfbbc
commit 0df9ad1015
31 changed files with 1087 additions and 620 deletions

File diff suppressed because it is too large Load Diff

View File

@ -16,5 +16,8 @@ winapi = { version = "0.3", features = ["winbase","winuser","consoleapi","proces
[target.'cfg(unix)'.dependencies]
libc = "0.2"
[[bin]]
name = "a"
path = "./examples/bin.rs"

View File

@ -11,5 +11,8 @@ pub mod cursor;
pub mod terminal;
fn main() {
terminal::resize_terminal();
print!(paint("asdf").with(Color::Black).on(Color::Red).black().red());
println!()
}

View File

@ -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);

View File

@ -76,6 +76,18 @@ pub fn print()
get().goto(10,5).print("@");
}
/// Save cursor position for recall later
pub fn safe_position()
{
get().safe_position();
}
/// Save cursor position for recall later
pub fn reset_position()
{
get().reset_position();
}

View File

@ -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()
{
@ -116,3 +124,12 @@ pub fn scroll_up()
// Scroll up 10 lines.
let terminal_size = 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(2,2);
}

View File

@ -44,4 +44,16 @@ impl ITerminalCursor for AnsiCursor {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}D"), count);
}
fn safe_position(&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"));
}
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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();
}
}

View File

View File

@ -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.

View File

@ -2,8 +2,6 @@
//! Like styling the font, foreground color and background color.
use std::fmt;
use std::convert::From;
use std::str::FromStr;
use Construct;
use crossterm_style::{ObjectStyle, StyledObject};
@ -14,79 +12,6 @@ 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<String> 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<Self, Self::Err> {
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<Box<ITerminalColor>>,
@ -237,3 +162,5 @@ where
{
ObjectStyle::new().apply_to(val)
}

View File

@ -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;

View File

@ -5,3 +5,91 @@ 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;
#[cfg(unix)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)]
pub enum Attribute {
Bold = 1,
Dim = 2,
Italic = 3,
Underlined = 4,
Blink = 5,
Reverse = 7,
Hidden = 8,
}
/// 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<String> 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<Self, Self::Err> {
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),
}
}
}

View File

@ -1,11 +1,13 @@
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<Color>,
pub bg_color: Option<Color>,
#[cfg(unix)]
pub attrs: Vec<Attribute>
}
impl Default for ObjectStyle {
@ -13,6 +15,8 @@ impl Default for ObjectStyle {
ObjectStyle {
fg_color: Some(Color::White),
bg_color: Some(Color::Black),
#[cfg(unix)]
attrs: Vec::new()
}
}
}
@ -34,6 +38,8 @@ impl ObjectStyle {
return ObjectStyle {
fg_color: None,
bg_color: None,
#[cfg(unix)]
attrs: Vec::new()
};
}
@ -48,4 +54,9 @@ impl ObjectStyle {
self.fg_color = Some(color);
self
}
pub fn add_attr(mut self, attr: Attribute)
{
self.attrs.push(attr);
}
}

View File

@ -1,6 +1,7 @@
use std;
use std::fmt;
use std::io::Write;
use super::super::Attribute;
use crossterm_style::{Color, ObjectStyle};
@ -55,6 +56,29 @@ impl<D> StyledObject<D> {
self.object_style = self.object_style.bg(background_color);
self
}
pub fn attrs(mut self, attrs: Vec<Attribute>) -> StyledObject<D>
{
for attr in attrs.iter() {
self.attr(attr);
}
self
}
pub fn attr(mut self, attr: Attribute) -> StyledObject<D>
{
self.object_style.add_attr(attr);
self
}
#[inline(always)] pub fn bold(self) -> StyledObject<D> { self.attr(Attribute::Bold) }
#[inline(always)] pub fn dim(self) -> StyledObject<D> { self.attr(Attribute::Dim) }
#[inline(always)] pub fn italic(self) -> StyledObject<D> { self.attr(Attribute::Italic) }
#[inline(always)] pub fn underlined(self) -> StyledObject<D> { self.attr(Attribute::Underlined) }
#[inline(always)] pub fn blink(self) -> StyledObject<D> { self.attr(Attribute::Blink) }
#[inline(always)] pub fn reverse(self) -> StyledObject<D> { self.attr(Attribute::Reverse) }
#[inline(always)] pub fn hidden(self) -> StyledObject<D> { self.attr(Attribute::Hidden) }
}
/// This is used to make StyledObject able to be displayed.
@ -78,6 +102,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");

View File

@ -50,4 +50,9 @@ impl ITerminal for UnixTerminal {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("{}T"), count);
}
fn set_size(width: i16, height: i16) {
let mut some_writer = io::stdout();
write!(&mut some_writer, csi!("8;{};{}t"), width, height);
}
}

View File

@ -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);
}

View File

@ -120,6 +120,17 @@ impl Terminal {
terminal.scroll_down(count);
}
}
/// Set the terminal size.
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.

View File

@ -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); }
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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 )
}

View File

@ -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<winnt::HANDLE> = None;
static mut CONSOLE_OUTPUT_HANDLE: Option<winnt::HANDLE> = 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
}
}

View File

@ -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<HANDLE> = 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 >= <i16>::max_value() {
panic!("X: {}, Argument Out of Range Exception", x);
}
if y < 0 || y >= <i16>::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 mut 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
}
}

View File

@ -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;

View File

@ -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");
}
}

View File

@ -1,9 +1,3 @@
pub fn is_cursor_out_of_range(x: i16, y: i16) {
if x < 0 || x >= <i16>::max_value() {
panic!("Argument Out of Range Exception");
}
if y < 0 || y >= <i16>::max_value() {
panic!("Argument Out of Range Exception");
}
}

View File

@ -6,6 +6,8 @@ pub trait Construct {
Self: Sized;
}
/// This trait is used to create an empty instance of an struct.
pub trait Empty {
fn empty() -> Self;

View File

@ -1 +1,5 @@
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