Skip to content

Commit

Permalink
cargo run --example something will ICE
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Atashian <[email protected]>
  • Loading branch information
retep998 committed Apr 28, 2015
1 parent 10cc9f2 commit 2b94c82
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 29 deletions.
20 changes: 20 additions & 0 deletions examples/something.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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!");
}
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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.
//
Expand Down Expand Up @@ -79,7 +79,7 @@ pub fn stdout() -> Option<Box<StdoutTerminal>> {
pub fn stdout() -> Option<Box<StdoutTerminal>> {
TerminfoTerminal::new(io::stdout()).map(|t| {
Box::new(t) as Box<StdoutTerminal>
}).or_else(|| WinConsole::new(io::stdout()).map(|t| {
}).or_else(|| WinConsole::new(io::stdout()).ok().map(|t| {
Box::new(t) as Box<StdoutTerminal>
}))
}
Expand All @@ -99,7 +99,7 @@ pub fn stderr() -> Option<Box<StderrTerminal>> {
pub fn stderr() -> Option<Box<StderrTerminal>> {
TerminfoTerminal::new(io::stderr()).map(|t| {
Box::new(t) as Box<StderrTerminal>
}).or_else(|| WinConsole::new(io::stderr()).map(|t| {
}).or_else(|| WinConsole::new(io::stderr()).ok().map(|t| {
Box::new(t) as Box<StderrTerminal>
}))
}
Expand Down
75 changes: 49 additions & 26 deletions src/win.rs
Original file line number Diff line number Diff line change
@@ -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.
//
Expand All @@ -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<T> {
Expand Down Expand Up @@ -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<winapi::HANDLE> {
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<T: Write+Send> WinConsole<T> {
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<WinConsole<T>> {
pub fn new(out: T) -> io::Result<WinConsole<T>> {
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,
Expand All @@ -130,14 +140,14 @@ impl<T: Write> Write for WinConsole<T> {
impl<T: Write+Send> Terminal<T> for WinConsole<T> {
fn fg(&mut self, color: color::Color) -> io::Result<bool> {
self.foreground = color;
self.apply();
try!(self.apply());

Ok(true)
}

fn bg(&mut self, color: color::Color) -> io::Result<bool> {
self.background = color;
self.apply();
try!(self.apply());

Ok(true)
}
Expand All @@ -146,12 +156,12 @@ impl<T: Write+Send> Terminal<T> for WinConsole<T> {
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)
Expand All @@ -170,11 +180,24 @@ impl<T: Write+Send> Terminal<T> for WinConsole<T> {
fn reset(&mut self) -> io::Result<bool> {
self.foreground = self.def_foreground;
self.background = self.def_background;
self.apply();
try!(self.apply());

Ok(true)
}


fn cursor_up(&mut self) -> io::Result<bool> {
unimplemented!()
//if GetConsoleScreenBufferInfo(
}

fn delete_line(&mut self) -> io::Result<bool> {
unimplemented!()
}

fn carriage_return(&mut self) -> io::Result<bool> {
unimplemented!()
}

fn get_ref<'a>(&'a self) -> &'a T { &self.buf }

fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
Expand Down

0 comments on commit 2b94c82

Please sign in to comment.