diff --git a/src/libterm/win.rs b/src/libterm/win.rs index cd61f9bb35ed1..0aae85503d07d 100644 --- a/src/libterm/win.rs +++ b/src/libterm/win.rs @@ -23,15 +23,29 @@ use Terminal; /// A Terminal implementation which uses the Win32 Console API. pub struct WinConsole { 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 { @@ -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 WinConsole { fn apply(&mut self) { let _unused = self.buf.flush(); @@ -91,7 +125,21 @@ impl Writer for WinConsole { impl Terminal for WinConsole { fn new(out: T) -> Option> { - 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 { @@ -134,8 +182,8 @@ impl Terminal for WinConsole { } 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(())