From bb16b12a6acb8600af88f367112dc8562552fea0 Mon Sep 17 00:00:00 2001
From: Katsu Kawakami <kkawa1570@gmail.com>
Date: Sun, 12 Jun 2016 22:20:03 -0400
Subject: [PATCH] Adding Window-specific isatty function

libc does not define the STDIN_FILENO & STDOUT_FILENO for the windows
platform.  We instead check whether or not stdin and stdout are TTY
by checking the GetConsoleMode output.
---
 src/lib.rs         |  4 ++--
 src/tty/mod.rs     | 12 ++++++++----
 src/tty/unix.rs    | 16 +++++++++++++++-
 src/tty/windows.rs | 18 ++++++++++++++++++
 4 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs
index d2e60e4e..302ced7c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -900,8 +900,8 @@ impl<'completer> Editor<'completer> {
         // if the number of columns is stored here, we need a SIGWINCH handler...
         let editor = Editor {
             unsupported_term: tty::is_unsupported_term(),
-            stdin_isatty: tty::is_a_tty(libc::STDIN_FILENO),
-            stdout_isatty: tty::is_a_tty(libc::STDOUT_FILENO),
+            stdin_isatty: tty::is_a_tty(tty::StandardStream::StdIn),
+            stdout_isatty: tty::is_a_tty(tty::StandardStream::StdOut),
             history: History::new(),
             completer: None,
             kill_ring: KillRing::new(60),
diff --git a/src/tty/mod.rs b/src/tty/mod.rs
index ef8a1a0b..72cc3f36 100644
--- a/src/tty/mod.rs
+++ b/src/tty/mod.rs
@@ -22,8 +22,12 @@ pub trait Terminal {
     fn disable_raw_mode(&self) -> Result<()>;
 }
 
-/// Check to see if `fd` is a TTY
-pub fn is_a_tty(fd: libc::c_int) -> bool {
-    unsafe { libc::isatty(fd) != 0 }
+/// Enum for Standard Streams 
+///
+/// libc::STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO is not defined for the
+/// Windows platform.  We will use this enum instead when calling isatty
+/// function
+pub enum StandardStream {
+    StdIn,
+    StdOut,
 }
-
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index fce1b6a0..d3f192df 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -5,6 +5,7 @@ use std;
 use nix::sys::termios;
 use nix::errno::Errno;
 use super::Terminal;
+use super::StandardStream;
 use ::Result;
 use ::error;
 
@@ -65,6 +66,19 @@ pub fn is_unsupported_term() -> bool {
     }
 }
 
+
+/// Return whether or not STDIN, STDOUT or STDERR is a TTY
+pub fn is_a_tty(stream: StandardStream) -> bool {
+    extern crate libc;
+
+    let fd = match stream {
+            StandardStream::StdIn => libc::STDIN_FILENO,
+            StandardStream::StdOut => libc::STDOUT_FILENO,
+        };
+
+    unsafe { libc::isatty(fd) != 0 }
+}
+
 /// Structure that will contain the original termios before enabling RAW mode
 pub struct UnixTerminal {
     original_termios: Option<termios::Termios>
@@ -75,7 +89,7 @@ impl Terminal for UnixTerminal {
     fn enable_raw_mode(&mut self) -> Result<()> {
         use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP, IXON,
                                 OPOST, VMIN, VTIME};
-        if !super::is_a_tty(libc::STDIN_FILENO) {
+        if !is_a_tty(StandardStream::StdIn) {
             return Err(error::ReadlineError::from_errno(Errno::ENOTTY));
         }
         let original_termios = try!(termios::tcgetattr(libc::STDIN_FILENO));
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index 3a9772b1..b661d2f1 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -1,3 +1,21 @@
+extern crate kernel32;
+extern crate winapi;
+
+use super::StandardStream;
+
+/// Return whether or not STDIN, STDOUT or STDERR is a TTY
+fn is_a_tty(stream: StandardStream) -> bool {
+    let handle = match stream {
+            StandardStream::StdIn => winapi::winbase::STD_INPUT_HANDLE,
+            StandardStream::Stdout => winapi::winbase::STD_OUTPUT_HANDLE,
+    };
+
+    unsafe {
+            let handle = kernel32::GetStdHandle(handle);
+            let mut out = 0;
+            kernel32::GetConsoleMode(handle, &mut out) != 0
+    }
+}
 
 /// Checking for an unsupported TERM in windows is a no-op
 pub fn is_unsupported_term() -> bool {
-- 
GitLab