From 3617c1e8f577a39f19108ceb9eb468ef57d4034b Mon Sep 17 00:00:00 2001 From: "Edward Z. Yang" Date: Tue, 7 Sep 2010 15:41:44 +0000 Subject: [PATCH] More accurate isatty test for MinGW. --- GHC/IO/FD.hs | 7 ++++++- System/Posix/Internals.hs | 3 +++ cbits/consUtils.c | 23 +++++++++++++++++++++++ include/consUtils.h | 1 + 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/GHC/IO/FD.hs b/GHC/IO/FD.hs index 0480bb6..c67615d 100644 --- a/GHC/IO/FD.hs +++ b/GHC/IO/FD.hs @@ -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 diff --git a/System/Posix/Internals.hs b/System/Posix/Internals.hs index 31b4fff..941dd5e 100644 --- a/System/Posix/Internals.hs +++ b/System/Posix/Internals.hs @@ -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 -- --------------------------------------------------------------------------- diff --git a/cbits/consUtils.c b/cbits/consUtils.c index 7c50c7b..55266b4 100644 --- a/cbits/consUtils.c +++ b/cbits/consUtils.c @@ -14,6 +14,29 @@ #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) { diff --git a/include/consUtils.h b/include/consUtils.h index 953f5c7..588139c 100644 --- a/include/consUtils.h +++ b/include/consUtils.h @@ -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); -- 1.7.10.4