From 2b94c822fc0590a5f9bdc99fad541d0c3518f2a3 Mon Sep 17 00:00:00 2001 From: Peter Atashian Date: Mon, 27 Apr 2015 20:33:46 -0400 Subject: [PATCH] `cargo run --example something` will ICE Signed-off-by: Peter Atashian --- examples/something.rs | 20 ++++++++++++ src/lib.rs | 6 ++-- src/win.rs | 75 ++++++++++++++++++++++++++++--------------- 3 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 examples/something.rs diff --git a/examples/something.rs b/examples/something.rs new file mode 100644 index 00000000..d1697b12 --- /dev/null +++ b/examples/something.rs @@ -0,0 +1,20 @@ +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate term; + +use term::Terminal; + +fn main() { + let mut out = term::stdout().unwrap(); + out.fg(5); + out.bg(4); + writeln!(&mut out, "Hello World!"); +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 669e3a84..de8628f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -79,7 +79,7 @@ pub fn stdout() -> Option> { pub fn stdout() -> Option> { TerminfoTerminal::new(io::stdout()).map(|t| { Box::new(t) as Box - }).or_else(|| WinConsole::new(io::stdout()).map(|t| { + }).or_else(|| WinConsole::new(io::stdout()).ok().map(|t| { Box::new(t) as Box })) } @@ -99,7 +99,7 @@ pub fn stderr() -> Option> { pub fn stderr() -> Option> { TerminfoTerminal::new(io::stderr()).map(|t| { Box::new(t) as Box - }).or_else(|| WinConsole::new(io::stderr()).map(|t| { + }).or_else(|| WinConsole::new(io::stderr()).ok().map(|t| { Box::new(t) as Box })) } diff --git a/src/win.rs b/src/win.rs index 16aee60f..4f72739f 100644 --- a/src/win.rs +++ b/src/win.rs @@ -1,4 +1,4 @@ -// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -17,10 +17,11 @@ extern crate winapi; use std::io::prelude::*; use std::io; +use std::ptr; use Attr; use color; -use {Terminal,UnwrappableTerminal}; +use {Terminal, UnwrappableTerminal}; /// A Terminal implementation which uses the Win32 Console API. pub struct WinConsole { @@ -69,45 +70,54 @@ fn bits_to_color(bits: u16) -> color::Color { color | (bits & 0x8) // copy the hi-intensity bit } +// Just get a handle to the current console buffer whatever it is +fn conout() -> io::Result { + let handle = unsafe { + kernel32::CreateFileA("CONOUT$\0".as_ptr() as winapi::LPCSTR, winapi::GENERIC_WRITE, + winapi::FILE_SHARE_WRITE, ptr::null_mut(), winapi::OPEN_EXISTING, 0, ptr::null_mut()) + }; + if handle == winapi::INVALID_HANDLE_VALUE { + Err(io::Error::last_os_error()) + } else { + Ok(handle) + } +} + +// This test will only pass if it is running in an actual console, probably +#[test] +fn test_conout() { + assert!(conout().is_ok()) +} + impl WinConsole { - fn apply(&mut self) { + fn apply(&mut self) -> io::Result<()> { + let out = try!(conout()); let _unused = self.buf.flush(); let mut accum: winapi::WORD = 0; accum |= color_to_bits(self.foreground); accum |= color_to_bits(self.background) << 4; - unsafe { - // Magic -11 means stdout, from - // http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx - // - // You may be wondering, "but what about stderr?", and the answer - // to that is that setting terminal attributes on the stdout - // handle also sets them for stderr, since they go to the same - // terminal! Admittedly, this is fragile, since stderr could be - // redirected to a different console. This is good enough for - // rustc though. See #13400. - let out = kernel32::GetStdHandle(-11i32 as winapi::DWORD); kernel32::SetConsoleTextAttribute(out, accum); } + Ok(()) } /// Returns `None` whenever the terminal cannot be created for some /// reason. - pub fn new(out: T) -> Option> { + pub fn new(out: T) -> io::Result> { let fg; let bg; + let handle = try!(conout()); unsafe { let mut buffer_info = ::std::mem::uninitialized(); - let out = kernel32::GetStdHandle(-11i32 as winapi::DWORD); - if kernel32::GetConsoleScreenBufferInfo(out, &mut buffer_info) != 0 { + if kernel32::GetConsoleScreenBufferInfo(handle, &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; + return Err(io::Error::last_os_error()); } } - Some(WinConsole { + Ok(WinConsole { buf: out, def_foreground: fg, def_background: bg, @@ -130,14 +140,14 @@ impl Write for WinConsole { impl Terminal for WinConsole { fn fg(&mut self, color: color::Color) -> io::Result { self.foreground = color; - self.apply(); + try!(self.apply()); Ok(true) } fn bg(&mut self, color: color::Color) -> io::Result { self.background = color; - self.apply(); + try!(self.apply()); Ok(true) } @@ -146,12 +156,12 @@ impl Terminal for WinConsole { match attr { Attr::ForegroundColor(f) => { self.foreground = f; - self.apply(); + try!(self.apply()); Ok(true) }, Attr::BackgroundColor(b) => { self.background = b; - self.apply(); + try!(self.apply()); Ok(true) }, _ => Ok(false) @@ -170,11 +180,24 @@ impl Terminal for WinConsole { fn reset(&mut self) -> io::Result { self.foreground = self.def_foreground; self.background = self.def_background; - self.apply(); + try!(self.apply()); Ok(true) } - + + fn cursor_up(&mut self) -> io::Result { + unimplemented!() + //if GetConsoleScreenBufferInfo( + } + + fn delete_line(&mut self) -> io::Result { + unimplemented!() + } + + fn carriage_return(&mut self) -> io::Result { + unimplemented!() + } + fn get_ref<'a>(&'a self) -> &'a T { &self.buf } fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }