1 // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Windows console handling
13 // FIXME (#13400): this is only a tiny fraction of the Windows console api
18 use std::io::prelude::*;
22 use {Terminal,UnwrappableTerminal};
24 /// A Terminal implementation which uses the Win32 Console API.
25 pub struct WinConsole<T> {
27 def_foreground: color::Color,
28 def_background: color::Color,
29 foreground: color::Color,
30 background: color::Color,
33 #[allow(non_snake_case)]
35 struct CONSOLE_SCREEN_BUFFER_INFO {
36 dwSize: [libc::c_short; 2],
37 dwCursorPosition: [libc::c_short; 2],
38 wAttributes: libc::WORD,
39 srWindow: [libc::c_short; 4],
40 dwMaximumWindowSize: [libc::c_short; 2],
43 #[allow(non_snake_case)]
44 #[link(name = "kernel32")]
46 fn SetConsoleTextAttribute(handle: libc::HANDLE, attr: libc::WORD) -> libc::BOOL;
47 fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
48 fn GetConsoleScreenBufferInfo(handle: libc::HANDLE,
49 info: *mut CONSOLE_SCREEN_BUFFER_INFO) -> libc::BOOL;
52 fn color_to_bits(color: color::Color) -> u16 {
53 // magic numbers from mingw-w64's wincon.h
55 let bits = match color % 8 {
60 color::YELLOW => 0x2 | 0x4,
61 color::MAGENTA => 0x1 | 0x4,
62 color::CYAN => 0x1 | 0x2,
63 color::WHITE => 0x1 | 0x2 | 0x4,
74 fn bits_to_color(bits: u16) -> color::Color {
75 let color = match bits & 0x7 {
81 0x5 => color::MAGENTA,
87 color | (bits & 0x8) // copy the hi-intensity bit
90 impl<T: Write+Send+'static> WinConsole<T> {
92 let _unused = self.buf.flush();
93 let mut accum: libc::WORD = 0;
94 accum |= color_to_bits(self.foreground);
95 accum |= color_to_bits(self.background) << 4;
98 // Magic -11 means stdout, from
99 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
101 // You may be wondering, "but what about stderr?", and the answer
102 // to that is that setting terminal attributes on the stdout
103 // handle also sets them for stderr, since they go to the same
104 // terminal! Admittedly, this is fragile, since stderr could be
105 // redirected to a different console. This is good enough for
106 // rustc though. See #13400.
107 let out = GetStdHandle(-11);
108 SetConsoleTextAttribute(out, accum);
112 /// Returns `None` whenever the terminal cannot be created for some
114 pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
118 let mut buffer_info = ::std::mem::uninitialized();
119 if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
120 fg = bits_to_color(buffer_info.wAttributes);
121 bg = bits_to_color(buffer_info.wAttributes >> 4);
127 Some(box WinConsole { buf: out,
128 def_foreground: fg, def_background: bg,
129 foreground: fg, background: bg } as Box<Terminal<T>+Send>)
133 impl<T: Write> Write for WinConsole<T> {
134 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
138 fn flush(&mut self) -> io::Result<()> {
143 impl<T: Write+Send+'static> Terminal<T> for WinConsole<T> {
144 fn fg(&mut self, color: color::Color) -> io::Result<bool> {
145 self.foreground = color;
151 fn bg(&mut self, color: color::Color) -> io::Result<bool> {
152 self.background = color;
158 fn attr(&mut self, attr: attr::Attr) -> io::Result<bool> {
160 attr::ForegroundColor(f) => {
165 attr::BackgroundColor(b) => {
174 fn supports_attr(&self, attr: attr::Attr) -> bool {
175 // it claims support for underscore and reverse video, but I can't get
176 // it to do anything -cmr
178 attr::ForegroundColor(_) | attr::BackgroundColor(_) => true,
183 fn reset(&mut self) -> io::Result<()> {
184 self.foreground = self.def_foreground;
185 self.background = self.def_background;
191 fn get_ref<'a>(&'a self) -> &'a T { &self.buf }
193 fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
196 impl<T: Write+Send+'static> UnwrappableTerminal<T> for WinConsole<T> {
197 fn unwrap(self) -> T { self.buf }