2 * (c) The GRASP/AQUA Project, Glasgow University, 1994-2002
4 * hWaitForInput Runtime Support
7 /* select and supporting types is not Posix */
8 /* #include "PosixSource.h" */
12 * inputReady(fd) checks to see whether input is available on the file
13 * descriptor 'fd'. Input meaning 'can I safely read at least a
14 * *character* from this file object without blocking?'
17 fdReady(int fd, int write, int msecs, int isSock)
20 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
37 /* select() will consider the descriptor set in the range of 0 to
41 tv.tv_sec = msecs / 1000;
42 tv.tv_usec = (msecs % 1000) * 1000;
44 while ((ready = select(maxfd, &rfd, &wfd, NULL, &tv)) < 0 ) {
45 if (errno != EINTR ) {
50 /* 1 => Input ready, 0 => not ready, -1 => error */
53 #if defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32)
56 HANDLE hFile = (HANDLE)_get_osfhandle(fd);
59 switch (GetFileType(hFile)) {
66 // nightmare. A Console Handle will appear to be ready
67 // (WaitForSingleObject() returned WAIT_OBJECT_0) when
68 // it has events in its input buffer, but these events might
69 // not be keyboard events, so when we read from the Handle the
70 // read() will block. So here we try to discard non-keyboard
71 // events from a console handle's input buffer and then try
72 // the WaitForSingleObject() again.
74 while (1) // keep trying until we find a real key event
76 rc = WaitForSingleObject( hFile, msecs );
78 case WAIT_TIMEOUT: return 0;
79 case WAIT_OBJECT_0: break;
80 default: /* WAIT_FAILED */ maperrno(); return -1;
83 while (1) // discard non-key events
85 rc = PeekConsoleInput(hFile, buf, 1, &count);
86 // printf("peek, rc=%d, count=%d, type=%d\n", rc, count, buf[0].EventType);
89 if (rc == ERROR_INVALID_HANDLE || rc == ERROR_INVALID_FUNCTION) {
97 if (count == 0) break; // no more events => wait again
99 // discard console events that are not "key down", because
100 // these will also be discarded by ReadFile().
101 if (buf[0].EventType == KEY_EVENT &&
102 buf[0].Event.KeyEvent.bKeyDown &&
103 buf[0].Event.KeyEvent.uChar.AsciiChar != '\0')
105 // it's a proper keypress:
110 // it's a non-key event, a key up event, or a
111 // non-character key (e.g. shift). discard it.
112 rc = ReadConsoleInput(hFile, buf, 1, &count);
115 if (rc == ERROR_INVALID_HANDLE || rc == ERROR_INVALID_FUNCTION) {
128 // assume that disk files are always ready:
132 // WaitForMultipleObjects() doesn't work for pipes (it
133 // always returns WAIT_OBJECT_0 even when no data is
134 // available). If the HANDLE is a pipe, therefore, we try
137 rc = PeekNamedPipe( hFile, NULL, 0, NULL, &avail, NULL );
146 if (rc == ERROR_BROKEN_PIPE) {
147 return 1; // this is probably what we want
149 if (rc != ERROR_INVALID_HANDLE && rc != ERROR_INVALID_FUNCTION) {
154 /* PeekNamedPipe didn't work - fall through to the general case */
157 rc = WaitForSingleObject( hFile, msecs );
159 /* 1 => Input ready, 0 => not ready, -1 => error */
161 case WAIT_TIMEOUT: return 0;
162 case WAIT_OBJECT_0: return 1;
163 default: /* WAIT_FAILED */ maperrno(); return -1;