More accurate isatty test for MinGW.
authorEdward Z. Yang <ezyang@mit.edu>
Tue, 7 Sep 2010 15:41:44 +0000 (15:41 +0000)
committerEdward Z. Yang <ezyang@mit.edu>
Tue, 7 Sep 2010 15:41:44 +0000 (15:41 +0000)
GHC/IO/FD.hs
System/Posix/Internals.hs
cbits/consUtils.c
include/consUtils.h

index 0480bb6..c67615d 100644 (file)
@@ -374,7 +374,12 @@ foreign import ccall safe "fdReady"
 -- Terminal-related stuff
 
 isTerminal :: FD -> IO Bool
-isTerminal fd = c_isatty (fdFD fd) >>= return.toBool
+isTerminal fd =
+#if defined(mingw32_HOST_OS)
+    is_console (fdFD fd) >>= return.toBool
+#else
+    c_isatty (fdFD fd) >>= return.toBool
+#endif
 
 setEcho :: FD -> Bool -> IO () 
 setEcho fd on = System.Posix.Internals.setEcho (fdFD fd) on
index 31b4fff..941dd5e 100644 (file)
@@ -311,6 +311,9 @@ foreign import ccall unsafe "consUtils.h set_console_echo__"
 foreign import ccall unsafe "consUtils.h get_console_echo__"
    get_console_echo :: CInt -> IO CInt
 
+foreign import ccall unsafe "consUtils.h is_console__"
+   is_console :: CInt -> IO CInt
+
 #endif
 
 -- ---------------------------------------------------------------------------
index 7c50c7b..55266b4 100644 (file)
 #define _get_osfhandle get_osfhandle
 #endif
 
+int is_console__(int fd) {
+    DWORD st;
+    HANDLE h;
+    if (!_isatty(fd)) {
+        /* TTY must be a character device */
+        return 0;
+    }
+    h = get_osfhandle(fd);
+    if (h == INVALID_HANDLE_VALUE) {
+        /* Broken handle can't be terminal */
+        return 0;
+    }
+    if (GetConsoleMode(h, &st) == INVALID_HANDLE_VALUE) {
+        /* GetConsoleMode appears to fail when it's not a TTY.  In
+           particular, it's what most of our terminal functions
+           assume works, so if it doesn't work for all intents
+           and purposes we're not dealing with a terminal. */
+        return 0;
+    }
+    return 1;
+}
+
+
 int
 set_console_buffering__(int fd, int cooked)
 {
index 953f5c7..588139c 100644 (file)
@@ -5,6 +5,7 @@
  */
 #ifndef __CONSUTILS_H__
 #define __CONSUTILS_H__
+extern int is_console__(int fd);
 extern int set_console_buffering__(int fd, int cooked);
 extern int set_console_echo__(int fd, int on);
 extern int get_console_echo__(int fd);