1 //! Windows console handling
3 // FIXME (#13400): this is only a tiny fraction of the Windows console api
8 use std::io::prelude::*;
14 /// A Terminal implementation that uses the Win32 Console API.
15 pub struct WinConsole<T> {
17 def_foreground: color::Color,
18 def_background: color::Color,
19 foreground: color::Color,
20 background: color::Color,
27 type HANDLE = *mut u8;
29 #[allow(non_snake_case)]
38 #[allow(non_snake_case)]
45 #[allow(non_snake_case)]
47 struct CONSOLE_SCREEN_BUFFER_INFO {
49 dwCursorPosition: COORD,
52 dwMaximumWindowSize: COORD,
55 #[allow(non_snake_case)]
56 #[link(name = "kernel32")]
58 fn SetConsoleTextAttribute(handle: HANDLE, attr: WORD) -> BOOL;
59 fn GetStdHandle(which: DWORD) -> HANDLE;
60 fn GetConsoleScreenBufferInfo(handle: HANDLE, info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> BOOL;
63 fn color_to_bits(color: color::Color) -> u16 {
64 // magic numbers from mingw-w64's wincon.h
66 let bits = match color % 8 {
71 color::YELLOW => 0x2 | 0x4,
72 color::MAGENTA => 0x1 | 0x4,
73 color::CYAN => 0x1 | 0x2,
74 color::WHITE => 0x1 | 0x2 | 0x4,
85 fn bits_to_color(bits: u16) -> color::Color {
86 let color = match bits & 0x7 {
92 0x5 => color::MAGENTA,
98 color | (bits & 0x8) // copy the hi-intensity bit
101 impl<T: Write + Send + 'static> WinConsole<T> {
102 fn apply(&mut self) {
103 let _unused = self.buf.flush();
104 let mut accum: WORD = 0;
105 accum |= color_to_bits(self.foreground);
106 accum |= color_to_bits(self.background) << 4;
109 // Magic -11 means stdout, from
110 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
112 // You may be wondering, "but what about stderr?", and the answer
113 // to that is that setting terminal attributes on the stdout
114 // handle also sets them for stderr, since they go to the same
115 // terminal! Admittedly, this is fragile, since stderr could be
116 // redirected to a different console. This is good enough for
117 // rustc though. See #13400.
118 let out = GetStdHandle(-11i32 as DWORD);
119 SetConsoleTextAttribute(out, accum);
123 /// Returns `None` whenever the terminal cannot be created for some reason.
124 pub fn new(out: T) -> io::Result<WinConsole<T>> {
129 let mut buffer_info = ::std::mem::uninitialized();
130 if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as DWORD), &mut buffer_info) != 0 {
131 fg = bits_to_color(buffer_info.wAttributes);
132 bg = bits_to_color(buffer_info.wAttributes >> 4);
148 impl<T: Write> Write for WinConsole<T> {
149 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
153 fn flush(&mut self) -> io::Result<()> {
158 impl<T: Write + Send + 'static> Terminal for WinConsole<T> {
161 fn fg(&mut self, color: color::Color) -> io::Result<bool> {
162 self.foreground = color;
168 fn bg(&mut self, color: color::Color) -> io::Result<bool> {
169 self.background = color;
175 fn attr(&mut self, attr: Attr) -> io::Result<bool> {
177 Attr::ForegroundColor(f) => {
182 Attr::BackgroundColor(b) => {
191 fn supports_attr(&self, attr: Attr) -> bool {
192 // it claims support for underscore and reverse video, but I can't get
193 // it to do anything -cmr
195 Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => true,
200 fn reset(&mut self) -> io::Result<bool> {
201 self.foreground = self.def_foreground;
202 self.background = self.def_background;
208 fn get_ref(&self) -> &T {
212 fn get_mut(&mut self) -> &mut T {
216 fn into_inner(self) -> T