Skip to content

Commit

Permalink
Restore original terminal colors after error messages on Windows.
Browse files Browse the repository at this point in the history
  • Loading branch information
vadimcn committed Sep 20, 2014
1 parent 5d335c9 commit b11c572
Showing 1 changed file with 51 additions and 3 deletions.
54 changes: 51 additions & 3 deletions src/libterm/win.rs
Expand Up @@ -23,15 +23,29 @@ use Terminal;
/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
buf: T,
def_foreground: color::Color,
def_background: color::Color,
foreground: color::Color,
background: color::Color,
}

#[allow(non_snake_case)]
#[repr(C)]
struct CONSOLE_SCREEN_BUFFER_INFO {
dwSize: [libc::c_short, ..2],
dwCursorPosition: [libc::c_short, ..2],
wAttributes: libc::WORD,
srWindow: [libc::c_short, ..4],
dwMaximumWindowSize: [libc::c_short, ..2],
}

#[allow(non_snake_case)]
#[link(name = "kernel32")]
extern "system" {
fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
fn GetConsoleScreenBufferInfo(handle: libc::HANDLE,
info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL;
}

fn color_to_bits(color: color::Color) -> u16 {
Expand All @@ -56,6 +70,26 @@ fn color_to_bits(color: color::Color) -> u16 {
}
}

fn bits_to_color(bits: u16) -> color::Color {
let color = match bits & 0x7 {
0 => color::BLACK,
0x1 => color::BLUE,
0x2 => color::GREEN,
0x4 => color::RED,
0x6 => color::YELLOW,
0x5 => color::MAGENTA,
0x3 => color::CYAN,
0x7 => color::WHITE,
_ => unreachable!()
};

if bits >= 8 {
color | 0x8
} else {
color
}
}

impl<T: Writer> WinConsole<T> {
fn apply(&mut self) {
let _unused = self.buf.flush();
Expand Down Expand Up @@ -91,7 +125,21 @@ impl<T: Writer> Writer for WinConsole<T> {

impl<T: Writer> Terminal<T> for WinConsole<T> {
fn new(out: T) -> Option<WinConsole<T>> {
Some(WinConsole { buf: out, foreground: color::WHITE, background: color::BLACK })
let fg;
let bg;
unsafe {
let mut buffer_info = ::std::mem::uninitialized();
if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
fg = bits_to_color(buffer_info.wAttributes);
bg = bits_to_color(buffer_info.wAttributes >> 4);
} else {
fg = color::WHITE;
bg = color::BLACK;
}
}
Some(WinConsole { buf: out,
def_foreground: fg, def_background: bg,
foreground: fg, background: bg } )
}

fn fg(&mut self, color: color::Color) -> IoResult<bool> {
Expand Down Expand Up @@ -134,8 +182,8 @@ impl<T: Writer> Terminal<T> for WinConsole<T> {
}

fn reset(&mut self) -> IoResult<()> {
self.foreground = color::WHITE;
self.background = color::BLACK;
self.foreground = self.def_foreground;
self.background = self.def_background;
self.apply();

Ok(())
Expand Down

5 comments on commit b11c572

@bors
Copy link
Contributor

@bors bors commented on b11c572 Sep 21, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at vadimcn@b11c572

@bors
Copy link
Contributor

@bors bors commented on b11c572 Sep 21, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging vadimcn/rust/term-colors = b11c572 into auto

@bors
Copy link
Contributor

@bors bors commented on b11c572 Sep 21, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vadimcn/rust/term-colors = b11c572 merged ok, testing candidate = 9fcfcaa

@bors
Copy link
Contributor

@bors bors commented on b11c572 Sep 21, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on b11c572 Sep 21, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 9fcfcaa

Please sign in to comment.