CLEAR-INPUT-STREAM and LISTEN-STREAM now work with windows consoles and pipes (M. Goffioul)

This commit is contained in:
jjgarcia 2005-01-11 14:40:31 +00:00
parent 94ba2a064f
commit 7ef23a5341
2 changed files with 64 additions and 21 deletions

View file

@ -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

View file

@ -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<nr; n++)
if (buf[n].EventType == KEY_EVENT) {
free(buf);
return ECL_LISTEN_AVAILABLE;
#else
hnd = (HANDLE)_get_osfhandle(fileno(fp));
switch (GetFileType(hnd)) {
case FILE_TYPE_CHAR: {
DWORD dw, dw_read, cm;
if (GetNumberOfConsoleInputEvents(hnd, &dw)) {
if (!GetConsoleMode(hnd, &cm))
FEwin32_error("GetConsoleMode() failed", 0);
if (dw > 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<dw_read; i++)
if (recs[i].EventType == KEY_EVENT &&
recs[i].Event.KeyEvent.bKeyDown &&
recs[i].Event.KeyEvent.uChar.AsciiChar == 13)
return ECL_LISTEN_AVAILABLE;
} else {
for (i=0; i<dw_read; i++)
if (recs[i].EventType == KEY_EVENT &&
recs[i].Event.KeyEvent.bKeyDown &&
recs[i].Event.KeyEvent.uChar.AsciiChar != 0)
return ECL_LISTEN_AVAILABLE;
}
}
}
free(buf);
return ECL_LISTEN_NO_CHAR;
} else
FEwin32_error("GetNumberOfConsoleInputEvents() failed", 0);
break;
}
return ECL_LISTEN_NO_CHAR;
case FILE_TYPE_DISK:
/* use regular file code below */
break;
case FILE_TYPE_PIPE: {
DWORD dw;
if (PeekNamedPipe(hnd, NULL, 0, NULL, &dw, NULL) == 0)
return (dw > 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.