diff --git a/rustfmt.toml b/rustfmt.toml
index 44148a2d3c3ed6bc75e28e1c55eec63f4d720698..6496add0b747be108c2a26d5848d6604179d3a12 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1 +1,3 @@
-reorder_imports = true
+reorder_imports = false
+normalise_comments = false
+write_mode = "Overwrite"
\ No newline at end of file
diff --git a/src/consts.rs b/src/consts.rs
index 375afe632cbaa1a28f9c20ae157ed9b4762f1498..31cbead410b6d29ad1c2780cc20fee97f6839679 100644
--- a/src/consts.rs
+++ b/src/consts.rs
@@ -14,6 +14,8 @@ pub enum KeyPress {
     Left,
     Meta(char),
     Null,
+    PageDown,
+    PageUp,
     Right,
     Tab, // Ctrl('I')
     Up,
@@ -33,12 +35,12 @@ pub fn char_to_key_press(c: char) -> KeyPress {
         '\x05' => KeyPress::Ctrl('E'),
         '\x06' => KeyPress::Ctrl('F'),
         '\x07' => KeyPress::Ctrl('G'),
-        '\x08' => KeyPress::Backspace,
+        '\x08' => KeyPress::Backspace, // '\b'
         '\x09' => KeyPress::Tab,
-        '\x0a' => KeyPress::Ctrl('J'),
+        '\x0a' => KeyPress::Ctrl('J'), // '\n' (10)
         '\x0b' => KeyPress::Ctrl('K'),
         '\x0c' => KeyPress::Ctrl('L'),
-        '\x0d' => KeyPress::Enter,
+        '\x0d' => KeyPress::Enter, // '\r' (13)
         '\x0e' => KeyPress::Ctrl('N'),
         '\x10' => KeyPress::Ctrl('P'),
         '\x12' => KeyPress::Ctrl('R'),
diff --git a/src/lib.rs b/src/lib.rs
index 214aff1de66bba055491222b1f9af571da6a7b92..1b0202d83eca6cb79dec43ba051e7a6f57b145c9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -37,7 +37,6 @@ pub mod line_buffer;
 mod char_iter;
 pub mod config;
 
-#[macro_use]
 mod tty;
 
 use std::fmt;
@@ -45,9 +44,9 @@ use std::io::{self, Read, Write};
 use std::mem;
 use std::path::Path;
 use std::result;
-use std::sync::atomic;
 #[cfg(unix)]
 use nix::sys::signal;
+use tty::Terminal;
 
 use encode_unicode::CharExt;
 use completion::{Completer, longest_common_prefix};
@@ -71,7 +70,7 @@ struct State<'out, 'prompt> {
     old_rows: usize, // Number of rows used so far (from start of prompt to end of input)
     history_index: usize, // The history index we are currently editing
     snapshot: LineBuffer, // Current edited line before history browsing/completion
-    output_handle: tty::Handle, // output handle (for windows)
+    term: Terminal, // terminal
 }
 
 #[derive(Copy, Clone, Debug, Default)]
@@ -82,12 +81,12 @@ struct Position {
 
 impl<'out, 'prompt> State<'out, 'prompt> {
     fn new(out: &'out mut Write,
-           output_handle: tty::Handle,
+           term: Terminal,
            prompt: &'prompt str,
            history_index: usize)
            -> State<'out, 'prompt> {
         let capacity = MAX_LINE;
-        let cols = tty::get_columns(output_handle);
+        let cols = term.get_columns();
         let prompt_size = calculate_position(prompt, Position::default(), cols);
         State {
             out: out,
@@ -99,7 +98,7 @@ impl<'out, 'prompt> State<'out, 'prompt> {
             old_rows: prompt_size.row,
             history_index: history_index,
             snapshot: LineBuffer::with_capacity(capacity),
-            output_handle: output_handle,
+            term: term,
         }
     }
 
@@ -175,24 +174,20 @@ impl<'out, 'prompt> State<'out, 'prompt> {
 
     #[cfg(windows)]
     fn refresh(&mut self, prompt: &str, prompt_size: Position) -> Result<()> {
-        let handle = self.output_handle;
         // calculate the position of the end of the input line
         let end_pos = calculate_position(&self.line, prompt_size, self.cols);
         // calculate the desired position of the cursor
         let cursor = calculate_position(&self.line[..self.line.pos()], prompt_size, self.cols);
 
         // position at the start of the prompt, clear to end of previous input
-        let mut info = unsafe { mem::zeroed() };
-        check!(kernel32::GetConsoleScreenBufferInfo(handle, &mut info));
+        let mut info = try!(self.term.get_console_screen_buffer_info());
         info.dwCursorPosition.X = 0;
         info.dwCursorPosition.Y -= self.cursor.row as i16;
-        check!(kernel32::SetConsoleCursorPosition(handle, info.dwCursorPosition));
+        try!(self.term.set_console_cursor_position(info.dwCursorPosition));
         let mut _count = 0;
-        check!(kernel32::FillConsoleOutputCharacterA(handle,
-                                                 ' ' as winapi::CHAR,
-                                                 (info.dwSize.X * (self.old_rows as i16 +1)) as winapi::DWORD,
-                                                 info.dwCursorPosition,
-                                                 &mut _count));
+        try!(self.term
+            .fill_console_output_character((info.dwSize.X * (self.old_rows as i16 + 1)) as u32,
+                                           info.dwCursorPosition));
         let mut ab = String::new();
         // display the prompt
         ab.push_str(prompt); // TODO handle ansi escape code (SetConsoleTextAttribute)
@@ -201,10 +196,10 @@ impl<'out, 'prompt> State<'out, 'prompt> {
         try!(write_and_flush(self.out, ab.as_bytes()));
 
         // position the cursor
-        check!(kernel32::GetConsoleScreenBufferInfo(handle, &mut info));
+        let mut info = try!(self.term.get_console_screen_buffer_info());
         info.dwCursorPosition.X = cursor.col as i16;
         info.dwCursorPosition.Y -= (end_pos.row - cursor.row) as i16;
-        check!(kernel32::SetConsoleCursorPosition(handle, info.dwCursorPosition));
+        try!(self.term.set_console_cursor_position(info.dwCursorPosition));
 
         self.cursor = cursor;
         self.old_rows = end_pos.row;
@@ -213,7 +208,7 @@ impl<'out, 'prompt> State<'out, 'prompt> {
     }
 
     fn update_columns(&mut self) {
-        self.cols = tty::get_columns(self.output_handle);
+        self.cols = self.term.get_columns();
     }
 }
 
@@ -646,7 +641,7 @@ fn page_completions<R: Read>(rdr: &mut tty::RawReader<R>,
                                  .unwrap() + min_col_pad);
     let num_cols = s.cols / max_width;
 
-    let mut pause_row = tty::get_rows(s.output_handle) - 1;
+    let mut pause_row = s.term.get_rows() - 1;
     let num_rows = (candidates.len() + num_cols - 1) / num_cols;
     let mut ab = String::new();
     for row in 0..num_rows {
@@ -665,7 +660,7 @@ fn page_completions<R: Read>(rdr: &mut tty::RawReader<R>,
                 KeyPress::Char('y') |
                 KeyPress::Char('Y') |
                 KeyPress::Char(' ') => {
-                    pause_row += tty::get_rows(s.output_handle) - 1;
+                    pause_row += s.term.get_rows() - 1;
                 }
                 KeyPress::Enter => {
                     pause_row += 1;
@@ -785,17 +780,19 @@ fn readline_edit<C: Completer>(prompt: &str,
     let completer = editor.completer.as_ref().map(|c| c as &Completer);
 
     let mut stdout = io::stdout();
-    let stdout_handle = try!(tty::stdout_handle());
 
     editor.kill_ring.reset();
-    let mut s = State::new(&mut stdout, stdout_handle, prompt, editor.history.len());
+    let mut s = State::new(&mut stdout,
+                           editor.term.clone(),
+                           prompt,
+                           editor.history.len());
     try!(s.refresh_line());
 
-    let mut rdr = try!(tty::RawReader::new(io::stdin()));
+    let mut rdr = try!(s.term.create_reader());
 
     loop {
         let rk = rdr.next_key(true);
-        if rk.is_err() && tty::SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst) {
+        if rk.is_err() && s.term.sigwinch() {
             s.update_columns();
             try!(s.refresh_line());
             continue;
@@ -884,7 +881,7 @@ fn readline_edit<C: Completer>(prompt: &str,
             }
             KeyPress::Ctrl('L') => {
                 // Clear the screen leaving the current line at the top of the screen.
-                try!(tty::clear_screen(&mut s.out, s.output_handle));
+                try!(s.term.clear_screen(&mut s.out));
                 try!(s.refresh_line())
             }
             KeyPress::Ctrl('N') |
@@ -1050,9 +1047,7 @@ fn readline_direct() -> Result<String> {
 
 /// Line editor
 pub struct Editor<C: Completer> {
-    unsupported_term: bool,
-    stdin_isatty: bool,
-    stdout_isatty: bool,
+    term: Terminal,
     history: History,
     completer: Option<C>,
     kill_ring: KillRing,
@@ -1061,30 +1056,25 @@ pub struct Editor<C: Completer> {
 
 impl<C: Completer> Editor<C> {
     pub fn new(config: Config) -> Editor<C> {
-        let editor = Editor {
-            unsupported_term: tty::is_unsupported_term(),
-            stdin_isatty: tty::is_a_tty(tty::STDIN_FILENO),
-            stdout_isatty: tty::is_a_tty(tty::STDOUT_FILENO),
+        let term = Terminal::new();
+        Editor {
+            term: term,
             history: History::new(config),
             completer: None,
             kill_ring: KillRing::new(60),
             config: config,
-        };
-        if !editor.unsupported_term && editor.stdin_isatty && editor.stdout_isatty {
-            tty::install_sigwinch_handler();
         }
-        editor
     }
 
     /// This method will read a line from STDIN and will display a `prompt`
     pub fn readline(&mut self, prompt: &str) -> Result<String> {
-        if self.unsupported_term {
+        if self.term.is_unsupported() {
             // Write prompt and flush it to stdout
             let mut stdout = io::stdout();
             try!(write_and_flush(&mut stdout, prompt.as_bytes()));
 
             readline_direct()
-        } else if !self.stdin_isatty {
+        } else if !self.term.is_stdin_tty() {
             // Not a tty: read from file / pipe.
             readline_direct()
         } else {
@@ -1121,9 +1111,9 @@ impl<C: Completer> Editor<C> {
 
 impl<C: Completer> fmt::Debug for Editor<C> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("State")
-            .field("unsupported_term", &self.unsupported_term)
-            .field("stdin_isatty", &self.stdin_isatty)
+        f.debug_struct("Editor")
+            .field("term", &self.term)
+            .field("config", &self.config)
             .finish()
     }
 }
@@ -1137,17 +1127,14 @@ mod test {
     use config::Config;
     use {Position, State};
     use super::Result;
-    use tty::Handle;
-
-    fn default_handle() -> Handle {
-        ()
-    }
+    use tty::Terminal;
 
     fn init_state<'out>(out: &'out mut Write,
                         line: &str,
                         pos: usize,
                         cols: usize)
                         -> State<'out, 'static> {
+        let term = Terminal::new();
         State {
             out: out,
             prompt: "",
@@ -1158,7 +1145,7 @@ mod test {
             old_rows: 0,
             history_index: 0,
             snapshot: LineBuffer::with_capacity(100),
-            output_handle: default_handle(),
+            term: term,
         }
     }
 
diff --git a/src/tty/mod.rs b/src/tty/mod.rs
index 22c6793842de9d5abf9d74371b5ebc33f126f8e9..82e2ed670c3437b3caae1dd443c016ab5b436074 100644
--- a/src/tty/mod.rs
+++ b/src/tty/mod.rs
@@ -2,7 +2,6 @@
 
 // If on Windows platform import Windows TTY module
 // and re-export into mod.rs scope
-#[macro_use]
 #[cfg(windows)]
 mod windows;
 #[cfg(windows)]
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index ff1d0b31d8cf354262e5fd2418c801bb7a986f1d..bbc57b54cb68122d27b319e44d7bfc270ab84817 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -12,10 +12,9 @@ use consts::{self, KeyPress};
 use ::Result;
 use ::error;
 
-pub type Handle = ();
 pub type Mode = termios::Termios;
-pub const STDIN_FILENO: libc::c_int = libc::STDIN_FILENO;
-pub const STDOUT_FILENO: libc::c_int = libc::STDOUT_FILENO;
+const STDIN_FILENO: libc::c_int = libc::STDIN_FILENO;
+const STDOUT_FILENO: libc::c_int = libc::STDOUT_FILENO;
 
 /// Unsupported Terminals that don't support RAW mode
 static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb", "cons25", "emacs"];
@@ -31,14 +30,14 @@ const TIOCGWINSZ: libc::c_int = 0x5413;
 
 /// Try to get the number of columns in the current terminal,
 /// or assume 80 if it fails.
-pub fn get_columns(_: Handle) -> usize {
+fn get_columns() -> usize {
     let (cols, _) = get_win_size();
     cols
 }
 
 /// Try to get the number of rows in the current terminal,
 /// or assume 24 if it fails.
-pub fn get_rows(_: Handle) -> usize {
+fn get_rows() -> usize {
     let (_, rows) = get_win_size();
     rows
 }
@@ -66,7 +65,7 @@ fn get_win_size() -> (usize, usize) {
 
 /// Check TERM environment variable to see if current term is in our
 /// unsupported list
-pub fn is_unsupported_term() -> bool {
+fn is_unsupported_term() -> bool {
     use std::ascii::AsciiExt;
     match std::env::var("TERM") {
         Ok(term) => {
@@ -82,11 +81,11 @@ pub fn is_unsupported_term() -> bool {
 
 
 /// Return whether or not STDIN, STDOUT or STDERR is a TTY
-pub fn is_a_tty(fd: libc::c_int) -> bool {
+fn is_a_tty(fd: libc::c_int) -> bool {
     unsafe { libc::isatty(fd) != 0 }
 }
 
-/// Enable raw mode for the TERM
+/// Enable RAW mode for the terminal.
 pub fn enable_raw_mode() -> Result<Mode> {
     use nix::errno::Errno::ENOTTY;
     use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP, IXON,
@@ -110,18 +109,13 @@ pub fn enable_raw_mode() -> Result<Mode> {
     Ok(original_mode)
 }
 
-/// Disable Raw mode for the term
+/// Disable RAW mode for the terminal.
 pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
     try!(termios::tcsetattr(STDIN_FILENO, termios::TCSAFLUSH, &original_mode));
     Ok(())
 }
 
-pub fn stdout_handle() -> Result<Handle> {
-    Ok(())
-}
-
-/// Clear the screen. Used to handle ctrl+l
-pub fn clear_screen(w: &mut Write, _: Handle) -> Result<()> {
+fn clear_screen(w: &mut Write) -> Result<()> {
     try!(w.write_all(b"\x1b[H\x1b[2J"));
     try!(w.flush());
     Ok(())
@@ -168,9 +162,13 @@ impl<R: Read> RawReader<R> {
                 let seq3 = try!(self.next_char());
                 if seq3 == '~' {
                     match seq2 {
+                        // '1' => Ok(KeyPress::Home),
                         '3' => Ok(KeyPress::Delete),
-                        // TODO '1' // Home
-                        // TODO '4' // End
+                        // '4' => Ok(KeyPress::End),
+                        '5' => Ok(KeyPress::PageUp),
+                        '6' => Ok(KeyPress::PageDown),
+                        '7' => Ok(KeyPress::Home),
+                        '8' => Ok(KeyPress::End),
                         _ => Ok(KeyPress::UnknownEscSeq),
                     }
                 } else {
@@ -178,7 +176,7 @@ impl<R: Read> RawReader<R> {
                 }
             } else {
                 match seq2 {
-                    'A' => Ok(KeyPress::Up),
+                    'A' => Ok(KeyPress::Up), // ANSI
                     'B' => Ok(KeyPress::Down),
                     'C' => Ok(KeyPress::Right),
                     'D' => Ok(KeyPress::Left),
@@ -191,6 +189,10 @@ impl<R: Read> RawReader<R> {
             // ESC O sequences.
             let seq2 = try!(self.next_char());
             match seq2 {
+                'A' => Ok(KeyPress::Up),
+                'B' => Ok(KeyPress::Down),
+                'C' => Ok(KeyPress::Right),
+                'D' => Ok(KeyPress::Left),
                 'F' => Ok(KeyPress::End),
                 'H' => Ok(KeyPress::Home),
                 _ => Ok(KeyPress::UnknownEscSeq),
@@ -222,9 +224,9 @@ impl<R: Read> RawReader<R> {
 }
 
 static SIGWINCH_ONCE: sync::Once = sync::ONCE_INIT;
-pub static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
+static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
 
-pub fn install_sigwinch_handler() {
+fn install_sigwinch_handler() {
     SIGWINCH_ONCE.call_once(|| unsafe {
         let sigwinch = signal::SigAction::new(signal::SigHandler::Handler(sigwinch_handler),
                                               signal::SaFlag::empty(),
@@ -236,3 +238,63 @@ pub fn install_sigwinch_handler() {
 extern "C" fn sigwinch_handler(_: signal::SigNum) {
     SIGWINCH.store(true, atomic::Ordering::SeqCst);
 }
+
+pub type Terminal = PosixTerminal;
+
+#[derive(Clone, Debug)]
+pub struct PosixTerminal {
+    unsupported: bool,
+    stdin_isatty: bool,
+}
+
+impl PosixTerminal {
+    pub fn new() -> PosixTerminal {
+        let term = PosixTerminal {
+            unsupported: is_unsupported_term(),
+            stdin_isatty: is_a_tty(STDIN_FILENO),
+        };
+        if !term.unsupported && term.stdin_isatty && is_a_tty(STDOUT_FILENO) {
+            install_sigwinch_handler();
+        }
+        term
+    }
+
+    // Init checks:
+
+    /// Check if current terminal can provide a rich line-editing user interface.
+    pub fn is_unsupported(&self) -> bool {
+        self.unsupported
+    }
+
+    /// check if stdin is connected to a terminal.
+    pub fn is_stdin_tty(&self) -> bool {
+        self.stdin_isatty
+    }
+
+    // Interactive loop:
+
+    /// Get the number of columns in the current terminal.
+    pub fn get_columns(&self) -> usize {
+        get_columns()
+    }
+
+    /// Get the number of rows in the current terminal.
+    pub fn get_rows(&self) -> usize {
+        get_rows()
+    }
+
+    /// Create a RAW reader
+    pub fn create_reader(&self) -> Result<RawReader<std::io::Stdin>> {
+        RawReader::new(std::io::stdin())
+    }
+
+    /// Check if a SIGWINCH signal has been received
+    pub fn sigwinch(&self) -> bool {
+        SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst)
+    }
+
+    /// Clear the screen. Used to handle ctrl+l
+    pub fn clear_screen(&mut self, w: &mut Write) -> Result<()> {
+        clear_screen(w)
+    }
+}
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index f1b09587532fd332dccb852d4d5e48dcc8910c5c..310ed12ca9771fae4d1253d62a4c7ef44ce4fc66 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -11,10 +11,9 @@ use consts::{self, KeyPress};
 use ::error;
 use ::Result;
 
-pub type Handle = winapi::HANDLE;
 pub type Mode = winapi::DWORD;
-pub const STDIN_FILENO: winapi::DWORD = winapi::STD_INPUT_HANDLE;
-pub const STDOUT_FILENO: winapi::DWORD = winapi::STD_OUTPUT_HANDLE;
+const STDIN_FILENO: winapi::DWORD = winapi::STD_INPUT_HANDLE;
+const STDOUT_FILENO: winapi::DWORD = winapi::STD_OUTPUT_HANDLE;
 
 fn get_std_handle(fd: winapi::DWORD) -> Result<winapi::HANDLE> {
     let handle = unsafe { kernel32::GetStdHandle(fd) };
@@ -40,21 +39,17 @@ macro_rules! check {
     };
 }
 
-/// Try to get the number of columns in the current terminal,
-/// or assume 80 if it fails.
-pub fn get_columns(handle: Handle) -> usize {
+fn get_columns(handle: winapi::HANDLE) -> usize {
     let (cols, _) = get_win_size(handle);
     cols
 }
 
-/// Try to get the number of rows in the current terminal,
-/// or assume 24 if it fails.
-pub fn get_rows(handle: Handle) -> usize {
+fn get_rows(handle: winapi::HANDLE) -> usize {
     let (_, rows) = get_win_size(handle);
     rows
 }
 
-fn get_win_size(handle: Handle) -> (usize, usize) {
+fn get_win_size(handle: winapi::HANDLE) -> (usize, usize) {
     let mut info = unsafe { mem::zeroed() };
     match unsafe { kernel32::GetConsoleScreenBufferInfo(handle, &mut info) } {
         0 => (80, 24),
@@ -62,11 +57,6 @@ fn get_win_size(handle: Handle) -> (usize, usize) {
     }
 }
 
-/// Checking for an unsupported TERM in windows is a no-op
-pub fn is_unsupported_term() -> bool {
-    false
-}
-
 fn get_console_mode(handle: winapi::HANDLE) -> Result<Mode> {
     let mut original_mode = 0;
     check!(kernel32::GetConsoleMode(handle, &mut original_mode));
@@ -74,7 +64,7 @@ fn get_console_mode(handle: winapi::HANDLE) -> Result<Mode> {
 }
 
 /// Return whether or not STDIN, STDOUT or STDERR is a TTY
-pub fn is_a_tty(fd: winapi::DWORD) -> bool {
+fn is_a_tty(fd: winapi::DWORD) -> bool {
     let handle = get_std_handle(fd);
     match handle {
         Ok(handle) => {
@@ -109,13 +99,8 @@ pub fn disable_raw_mode(original_mode: Mode) -> Result<()> {
     Ok(())
 }
 
-pub fn stdout_handle() -> Result<Handle> {
-    let handle = try!(get_std_handle(STDOUT_FILENO));
-    Ok(handle)
-}
-
 /// Clear the screen. Used to handle ctrl+l
-pub fn clear_screen(_: &mut Write, handle: Handle) -> Result<()> {
+fn clear_screen(_: &mut Write, handle: winapi::HANDLE) -> Result<()> {
     let mut info = unsafe { mem::zeroed() };
     check!(kernel32::GetConsoleScreenBufferInfo(handle, &mut info));
     let coord = winapi::COORD { X: 0, Y: 0 };
@@ -236,8 +221,84 @@ impl<R: Read> Iterator for RawReader<R> {
     }
 }
 
-pub static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
+static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;
+
+pub type Terminal = Console;
+
+#[derive(Clone,Debug)]
+pub struct Console {
+    stdin_isatty: bool,
+    stdout_handle: winapi::HANDLE,
+}
+
+impl Console {
+    pub fn new() -> Console {
+        use std::ptr;
+        let stdout_handle = get_std_handle(STDOUT_FILENO).unwrap_or(ptr::null_mut());
+        Console {
+            stdin_isatty: is_a_tty(STDIN_FILENO),
+            stdout_handle: stdout_handle,
+        }
+    }
+
+    /// Checking for an unsupported TERM in windows is a no-op
+    pub fn is_unsupported(&self) -> bool {
+        false
+    }
+
+    pub fn is_stdin_tty(&self) -> bool {
+        self.stdin_isatty
+    }
 
-pub fn install_sigwinch_handler() {
+    // pub fn install_sigwinch_handler(&mut self) {
     // See ReadConsoleInputW && WINDOW_BUFFER_SIZE_EVENT
+    // }
+
+    /// Try to get the number of columns in the current terminal,
+    /// or assume 80 if it fails.
+    pub fn get_columns(&self) -> usize {
+        get_columns(self.stdout_handle)
+    }
+
+    /// Try to get the number of rows in the current terminal,
+    /// or assume 24 if it fails.
+    pub fn get_rows(&self) -> usize {
+        get_rows(self.stdout_handle)
+    }
+
+    pub fn create_reader(&self) -> Result<RawReader<io::Stdin>> {
+        RawReader::new(io::stdin()) // FIXME
+    }
+
+    pub fn sigwinch(&self) -> bool {
+        SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst)
+    }
+
+    pub fn clear_screen(&mut self, w: &mut Write) -> Result<()> {
+        clear_screen(w, self.stdout_handle)
+    }
+
+    pub fn get_console_screen_buffer_info(&self) -> Result<winapi::CONSOLE_SCREEN_BUFFER_INFO> {
+        let mut info = unsafe { mem::zeroed() };
+        check!(kernel32::GetConsoleScreenBufferInfo(self.stdout_handle, &mut info));
+        Ok(info)
+    }
+
+    pub fn set_console_cursor_position(&mut self, pos: winapi::COORD) -> Result<()> {
+        check!(kernel32::SetConsoleCursorPosition(self.stdout_handle, pos));
+        Ok(())
+    }
+
+    pub fn fill_console_output_character(&mut self,
+                                         length: winapi::DWORD,
+                                         pos: winapi::COORD)
+                                         -> Result<()> {
+        let mut _count = 0;
+        check!(kernel32::FillConsoleOutputCharacterA(self.stdout_handle,
+                                                     ' ' as winapi::CHAR,
+                                                     length,
+                                                     pos,
+                                                     &mut _count));
+        Ok(())
+    }
 }