Skip to content

Commit

Permalink
win: Add WinConsoleInfo struct
Browse files Browse the repository at this point in the history
 Parallel API to terminfo terminals is also added:
  * WinConsoleInfo::from_env()
  * WinConsole::new_with_consoleinfo()

 Just like terminfo, this allows to check if we are going to get
 errors before moving `out`.

 Related: Stebalien#57

Signed-off-by: Mohammad AlSaleh <CE.Mohammad.AlSaleh@gmail.com>
  • Loading branch information
MoSal committed Aug 20, 2018
1 parent dd20c18 commit 7d89824
Showing 1 changed file with 46 additions and 17 deletions.
63 changes: 46 additions & 17 deletions src/win.rs
Expand Up @@ -32,6 +32,16 @@ use win::winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE};
use win::winapi::um::fileapi::{CreateFileA, OPEN_EXISTING};
use win::winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE, HANDLE};


/// Console info which can be used by a Terminal implementation
/// which uses the Win32 Console API.
pub struct WinConsoleInfo {
def_foreground: color::Color,
def_background: color::Color,
foreground: color::Color,
background: color::Color,
}

/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
buf: T,
Expand Down Expand Up @@ -133,22 +143,10 @@ fn test_conout() {
assert!(conout().is_ok())
}

impl<T: Write + Send> WinConsole<T> {
fn apply(&mut self) -> io::Result<()> {
let out = conout()?;
let _unused = self.buf.flush();
let mut accum: WORD = 0;
accum |= color_to_bits(self.foreground);
accum |= color_to_bits(self.background) << 4;
unsafe {
SetConsoleTextAttribute(*out, accum);
}
Ok(())
}

/// Returns `Err` whenever the terminal cannot be created for some
impl WinConsoleInfo {
/// Returns `Err` whenever console info cannot be retrieved for some
/// reason.
pub fn new(out: T) -> io::Result<WinConsole<T>> {
pub fn from_env() -> io::Result<()> {
let fg;
let bg;
let handle = conout()?;
Expand All @@ -161,8 +159,7 @@ impl<T: Write + Send> WinConsole<T> {
return Err(io::Error::last_os_error());
}
}
Ok(WinConsole {
buf: out,
Ok(WinConsoleInfo {
def_foreground: fg,
def_background: bg,
foreground: fg,
Expand All @@ -171,6 +168,38 @@ impl<T: Write + Send> WinConsole<T> {
}
}

impl<T: Write + Send> WinConsole<T> {
fn apply(&mut self) -> io::Result<()> {
let out = conout()?;
let _unused = self.buf.flush();
let mut accum: WORD = 0;
accum |= color_to_bits(self.foreground);
accum |= color_to_bits(self.background) << 4;
unsafe {
SetConsoleTextAttribute(*out, accum);
}
Ok(())
}

/// Create a new WinConsole with the given WinConsoleInfo and out
pub fn new_with_consoleinfo(out: T, consoleinfo: WinConsoleInfo) -> WinConsole<T> {
Ok(WinConsole {
buf: out,
def_foreground: consoleinfo.def_foreground,
def_background: consoleinfo.def_background,
foreground: consoleinfo.foreground,
background: consoleinfo.background,
})
}

/// Returns `Err` whenever the terminal cannot be created for some
/// reason.
pub fn new(out: T) -> io::Result<WinConsole<T>> {
let consoleinfo = WinConsoleInfo::from_env()?;
Self::new_with_consoleinfo(out, consoleinfo)
}
}

impl<T: Write> Write for WinConsole<T> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buf.write(buf)
Expand Down

0 comments on commit 7d89824

Please sign in to comment.