Skip to content

Commit b11c572

Browse files
committed
Restore original terminal colors after error messages on Windows.
1 parent 5d335c9 commit b11c572

File tree

1 file changed

+51
-3
lines changed

1 file changed

+51
-3
lines changed

src/libterm/win.rs

+51-3
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,29 @@ use Terminal;
2323
/// A Terminal implementation which uses the Win32 Console API.
2424
pub struct WinConsole<T> {
2525
buf: T,
26+
def_foreground: color::Color,
27+
def_background: color::Color,
2628
foreground: color::Color,
2729
background: color::Color,
2830
}
2931

32+
#[allow(non_snake_case)]
33+
#[repr(C)]
34+
struct CONSOLE_SCREEN_BUFFER_INFO {
35+
dwSize: [libc::c_short, ..2],
36+
dwCursorPosition: [libc::c_short, ..2],
37+
wAttributes: libc::WORD,
38+
srWindow: [libc::c_short, ..4],
39+
dwMaximumWindowSize: [libc::c_short, ..2],
40+
}
41+
3042
#[allow(non_snake_case)]
3143
#[link(name = "kernel32")]
3244
extern "system" {
3345
fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
3446
fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
47+
fn GetConsoleScreenBufferInfo(handle: libc::HANDLE,
48+
info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL;
3549
}
3650

3751
fn color_to_bits(color: color::Color) -> u16 {
@@ -56,6 +70,26 @@ fn color_to_bits(color: color::Color) -> u16 {
5670
}
5771
}
5872

73+
fn bits_to_color(bits: u16) -> color::Color {
74+
let color = match bits & 0x7 {
75+
0 => color::BLACK,
76+
0x1 => color::BLUE,
77+
0x2 => color::GREEN,
78+
0x4 => color::RED,
79+
0x6 => color::YELLOW,
80+
0x5 => color::MAGENTA,
81+
0x3 => color::CYAN,
82+
0x7 => color::WHITE,
83+
_ => unreachable!()
84+
};
85+
86+
if bits >= 8 {
87+
color | 0x8
88+
} else {
89+
color
90+
}
91+
}
92+
5993
impl<T: Writer> WinConsole<T> {
6094
fn apply(&mut self) {
6195
let _unused = self.buf.flush();
@@ -91,7 +125,21 @@ impl<T: Writer> Writer for WinConsole<T> {
91125

92126
impl<T: Writer> Terminal<T> for WinConsole<T> {
93127
fn new(out: T) -> Option<WinConsole<T>> {
94-
Some(WinConsole { buf: out, foreground: color::WHITE, background: color::BLACK })
128+
let fg;
129+
let bg;
130+
unsafe {
131+
let mut buffer_info = ::std::mem::uninitialized();
132+
if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
133+
fg = bits_to_color(buffer_info.wAttributes);
134+
bg = bits_to_color(buffer_info.wAttributes >> 4);
135+
} else {
136+
fg = color::WHITE;
137+
bg = color::BLACK;
138+
}
139+
}
140+
Some(WinConsole { buf: out,
141+
def_foreground: fg, def_background: bg,
142+
foreground: fg, background: bg } )
95143
}
96144

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

136184
fn reset(&mut self) -> IoResult<()> {
137-
self.foreground = color::WHITE;
138-
self.background = color::BLACK;
185+
self.foreground = self.def_foreground;
186+
self.background = self.def_background;
139187
self.apply();
140188

141189
Ok(())

0 commit comments

Comments
 (0)