Skip to content

Commit

Permalink
On Windows, set the console mode before every call to ReadConsoleInputW.
Browse files Browse the repository at this point in the history
If input is a pipe (either directly from the cmd line or via LESSOPEN),
the Windows cmd processor may reset the console mode when the pipe writer
terminates. Since we can't detect when that happens, just set the mode
before every read.
  • Loading branch information
gwsw committed Oct 1, 2023
1 parent c2e3b8f commit c7ffe20
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 18 deletions.
29 changes: 17 additions & 12 deletions screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ static int sy_fg_color; /* Color of system text (before less) */
static int sy_bg_color;
public int sgr_mode; /* Honor ANSI sequences rather than using above */
#if MSDOS_COMPILER==WIN32C
static DWORD init_output_mode; /* The initial console output mode */
public DWORD init_console_mode; /* The initial console output mode */
public DWORD curr_console_mode; /* The current console output mode */
public int vt_enabled = -1; /* Is virtual terminal processing available? */
#endif
#else
Expand Down Expand Up @@ -1170,7 +1171,7 @@ public void get_term(void)
* before any file operations have been done on fd0.
*/
SET_BINARY(0);
GetConsoleMode(con_out, &init_output_mode);
GetConsoleMode(con_out, &init_console_mode);
GetConsoleScreenBufferInfo(con_out, &scr);
curr_attr = scr.wAttributes;
sy_bg_color = (curr_attr & BG_COLORS) >> 4; /* normalize */
Expand Down Expand Up @@ -1564,16 +1565,16 @@ static void initcolor(void)
*/
static void win32_init_vt_term(void)
{
DWORD output_mode;
DWORD console_mode;

if (vt_enabled == 0 || (vt_enabled == 1 && con_out == con_out_ours))
return;

GetConsoleMode(con_out, &output_mode);
vt_enabled = SetConsoleMode(con_out,
output_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
console_mode = curr_console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
vt_enabled = SetConsoleMode(con_out, console_mode);
if (vt_enabled)
{
curr_console_mode = console_mode;
auto_wrap = 0;
ignaw = 1;
}
Expand All @@ -1582,7 +1583,7 @@ static void win32_init_vt_term(void)
static void win32_deinit_vt_term(void)
{
if (vt_enabled == 1 && con_out == con_out_save)
SetConsoleMode(con_out, init_output_mode);
SetConsoleMode(con_out, init_console_mode);
}

/*
Expand Down Expand Up @@ -1699,8 +1700,8 @@ public void init_mouse(void)
ltputs(sc_s_mousecap, sc_height, putchr);
#else
#if MSDOS_COMPILER==WIN32C
SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT
| ENABLE_EXTENDED_FLAGS /* disable quick edit */);
curr_console_mode = ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS; /* disable quick edit */
SetConsoleMode(tty, curr_console_mode);

#endif
#endif
Expand All @@ -1716,8 +1717,8 @@ public void deinit_mouse(void)
ltputs(sc_e_mousecap, sc_height, putchr);
#else
#if MSDOS_COMPILER==WIN32C
SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS
| (console_mode & ENABLE_QUICK_EDIT_MODE));
curr_console_mode = ENABLE_PROCESSED_INPUT | ENABLE_EXTENDED_FLAGS | (curr_console_mode & ENABLE_QUICK_EDIT_MODE);
SetConsoleMode(tty, curr_console_mode);
#endif
#endif
}
Expand Down Expand Up @@ -3034,6 +3035,11 @@ public int win32_kbhit(void)
for (;;)
{
DWORD nread;
/*
* When an input pipe closes, cmd may reset the console mode,
* so set the mode every time we read input.
*/
SetConsoleMode(tty, curr_console_mode);
PeekConsoleInputW(tty, &xip.ir, 1, &nread);
if (nread == 0)
return (FALSE);
Expand Down Expand Up @@ -3102,4 +3108,3 @@ public void WIN32textout(char *text, int len)
#endif
}
#endif

13 changes: 7 additions & 6 deletions ttyin.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
#define _WIN32_WINNT 0x400
#endif
#include <windows.h>
public DWORD console_mode;
public HANDLE tty;
extern DWORD init_console_mode;
extern DWORD curr_console_mode;
#else
public int tty;
#endif
Expand Down Expand Up @@ -87,9 +88,9 @@ public void open_getchr(void)
tty = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ, &sa,
OPEN_EXISTING, 0L, NULL);
GetConsoleMode(tty, &console_mode);
/* Make sure we get Ctrl+C events. */
SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
curr_console_mode = ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT;
SetConsoleMode(tty, curr_console_mode);
#else
#if MSDOS_COMPILER
extern int fd0;
Expand Down Expand Up @@ -119,21 +120,21 @@ public void open_getchr(void)
public void close_getchr(void)
{
#if MSDOS_COMPILER==WIN32C
SetConsoleMode(tty, console_mode);
SetConsoleMode(tty, init_console_mode);
CloseHandle(tty);
#endif
}

#if MSDOS_COMPILER==WIN32C
/*
* Close the pipe, restoring the keyboard (CMD resets it, losing the mouse).
* Close the pipe, restoring the console mode (CMD resets it, losing the mouse).
*/
public int pclose(FILE *f)
{
int result;

result = _pclose(f);
SetConsoleMode(tty, ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT);
SetConsoleMode(tty, curr_console_mode);
return result;
}
#endif
Expand Down

0 comments on commit c7ffe20

Please sign in to comment.