diff --git a/src/CHANGELOG b/src/CHANGELOG index 29e2dd3bf..4e79c8cd3 100644 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -67,6 +67,11 @@ ECL 1.0 - DO/DO* are no longer primitives, but rather macros that build on top of the SI::WHILE iteration primitive. + - LISTEN and CLEAR-INPUT-STREAM now work with the Windows console and + pipes as expected. + + - User break with Ctrl+C is now also capture under Windows. + * Internals: - The compiler now uses a more detailed tree to represent the code, keeping diff --git a/src/c/file.d b/src/c/file.d index f96ee6685..3244e04e3 100644 --- a/src/c/file.d +++ b/src/c/file.d @@ -1661,6 +1661,14 @@ BEGIN: case smm_input: if (fp == NULL) wrong_file_handler(strm); +#if defined(mingw32) || defined(_MSC_VER) + if (isatty(fileno(fp))) { + /* Flushes Win32 console */ + if (!FlushConsoleInputBuffer((HANDLE)_get_osfhandle(fileno(fp)))) + FEwin32_error("FlushConsoleInputBuffer() failed", 0); + /* Do not stop here: the FILE structure needs also to be flushed */ + } +#endif while (flisten(fp) == ECL_LISTEN_AVAILABLE) { getc(fp); } @@ -1773,6 +1781,9 @@ flisten(FILE *fp) fd_set fds; int retv, fd; struct timeval tv = { 0, 0 }; +#endif +#if defined(mingw32) || defined(_MSC_VER) + HANDLE hnd; #endif if (feof(fp)) return ECL_LISTEN_EOF; @@ -1795,29 +1806,56 @@ flisten(FILE *fp) return (c > 0)? ECL_LISTEN_AVAILABLE : ECL_LISTEN_NO_CHAR; } #endif /* FIONREAD */ -#endif -#if 0 - if (isatty(fileno(fp))) { - /* console input */ - HANDLE hnd = _get_osfhandle(_fileno(fp)); - DWORD n; - if (!GetNumberOfConsoleInputEvents(hnd, &n)) - FElibc_error("GetNumberOfConsoleInputEvents() returned an error value", 0); - if (n > 0) { - PINPUT_RECORD buf = (PINPUT_RECORD)malloc(n*sizeof(INPUT_RECORD)); - DWORD nr; - if (!PeekConsoleInput(hnd, buf, n, &nr)) { - free(buf); - FElibc_error("PeekConsoleInput() returned an error value", 0); - } - for (n=0; n 0) { + PINPUT_RECORD recs = (PINPUT_RECORD)GC_malloc(sizeof(INPUT_RECORD)*dw); + int i; + if (!PeekConsoleInput(hnd, recs, dw, &dw_read)) + FEwin32_error("PeekConsoleInput failed()", 0); + if (dw_read > 0) { + if (cm & ENABLE_LINE_INPUT) { + for (i=0; i 0 ? ECL_LISTEN_AVAILABLE : ECL_LISTEN_NO_CHAR); + else if (GetLastError() == ERROR_BROKEN_PIPE) + return ECL_LISTEN_EOF; + else + FEwin32_error("PeekNamedPipe() failed", 0); + break; + } + default: + FEerror("Unsupported Windows file type: ~A", 1, MAKE_FIXNUM(GetFileType(hnd))); + break; } #endif /* This code is portable, and implements the expected behavior for regular files.