FIX #2189: re-enabled cooked mode for Console-connected Handles on Windows
[ghc-base.git] / cbits / consUtils.c
1 /* 
2  * (c) The University of Glasgow 2002
3  *
4  * Win32 Console API support
5  */
6 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32) || defined(__CYGWIN__)
7 /* to the end */
8
9 #include "consUtils.h"
10 #include <windows.h>
11 #include <io.h>
12
13 #if defined(__CYGWIN__)
14 #define _get_osfhandle get_osfhandle
15 #endif
16
17 int
18 set_console_buffering__(int fd, int cooked)
19 {
20     HANDLE h;
21     DWORD  st;
22     /* According to GetConsoleMode() docs, it is not possible to
23        leave ECHO_INPUT enabled without also having LINE_INPUT,
24        so we have to turn both off here. */
25     DWORD flgs = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
26     
27     if ( (h = (HANDLE)_get_osfhandle(fd)) != INVALID_HANDLE_VALUE ) {
28         /* Only for console-connected Handles */
29       if ( GetFileType(h) == FILE_TYPE_CHAR ) {
30         if ( GetConsoleMode(h,&st) &&
31              SetConsoleMode(h, cooked ? (st | flgs) : st & ~flgs)  ) {
32             return 0;
33         }
34       }
35     }
36     return -1;
37 }
38
39 int
40 set_console_echo__(int fd, int on)
41 {
42     HANDLE h;
43     DWORD  st;
44     DWORD flgs = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT;
45     
46     if ( (h = (HANDLE)_get_osfhandle(fd)) != INVALID_HANDLE_VALUE ) {
47         if ( GetConsoleMode(h,&st) && 
48              SetConsoleMode(h,( on ? (st | flgs) : (st & ~ENABLE_ECHO_INPUT))) ) {
49             return 0;
50         }
51     }
52     return -1;
53 }
54
55 int
56 get_console_echo__(int fd)
57 {
58     HANDLE h;
59     DWORD  st;
60     
61     if ( (h = (HANDLE)_get_osfhandle(fd)) != INVALID_HANDLE_VALUE ) {
62         if ( GetConsoleMode(h,&st) ) {
63             return (st & ENABLE_ECHO_INPUT ? 1 : 0);
64         }
65     }
66     return -1;
67 }
68
69 int
70 flush_input_console__(int fd)
71 {
72     HANDLE h = (HANDLE)_get_osfhandle(fd);
73     
74     if ( h != INVALID_HANDLE_VALUE ) {
75         /* If the 'fd' isn't connected to a console; treat the flush
76          * operation as a NOP.
77          */
78         DWORD unused;
79         if ( !GetConsoleMode(h,&unused) &&
80              GetLastError() == ERROR_INVALID_HANDLE ) {
81             return 0;
82         }
83         if ( FlushConsoleInputBuffer(h) ) {
84             return 0;
85         }
86     }
87     /* ToDo: translate GetLastError() into something errno-friendly */
88     return -1;
89 }
90
91 #endif /* defined(__MINGW32__) || ... */