libncurses: Import https://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.5.tar.gz changes

Change-Id: I3433d30ca01359fd2e3623ede96b531f0b39cbfa
Signed-off-by: micky387 <mickaelsaibi@free.fr>
diff --git a/ncurses/win32con/gettimeofday.c b/ncurses/win32con/gettimeofday.c
index 867041f..603a6f4 100644
--- a/ncurses/win32con/gettimeofday.c
+++ b/ncurses/win32con/gettimeofday.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2008-2010,2014 Free Software Foundation, Inc.              *
+ * Copyright 2020,2023 Thomas E. Dickey                                     *
+ * Copyright 2008-2010,2014 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -35,11 +36,12 @@
 
 #include <windows.h>
 
-MODULE_ID("$Id: gettimeofday.c,v 1.3 2014/04/26 19:41:34 juergen Exp $")
+MODULE_ID("$Id: gettimeofday.c,v 1.7 2023/02/25 20:05:36 tom Exp $")
 
+#if HAVE_GETTIMEOFDAY == 2
 #define JAN1970 116444736000000000LL	/* the value for 01/01/1970 00:00 */
 
-int
+NCURSES_EXPORT(int)
 gettimeofday(struct timeval *tv, void *tz GCC_UNUSED)
 {
     union {
@@ -52,3 +54,4 @@
     tv->tv_sec = (long) ((data.since1601 - JAN1970) / 10000000LL);
     return (0);
 }
+#endif // HAVE_GETTIMEOFDAY == 2
diff --git a/ncurses/win32con/wcwidth.c b/ncurses/win32con/wcwidth.c
index cdef64a..5584366 100644
--- a/ncurses/win32con/wcwidth.c
+++ b/ncurses/win32con/wcwidth.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 2010 Free Software Foundation, Inc.                        *
+ * Copyright 2020 Thomas E. Dickey                                          *
+ * Copyright 2010 Free Software Foundation, Inc.                            *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -27,7 +28,7 @@
  ****************************************************************************/
 #include <curses.priv.h>
 
-MODULE_ID("$Id: wcwidth.c,v 1.2 2010/08/07 20:52:43 tom Exp $")
+MODULE_ID("$Id: wcwidth.c,v 1.4 2020/07/11 21:02:10 tom Exp $")
 
 #if USE_WIDEC_SUPPORT
 #define mk_wcwidth(ucs)          _nc_wcwidth(ucs)
@@ -35,10 +36,10 @@
 #define mk_wcwidth_cjk(ucs)      _nc_wcwidth_cjk(ucs)
 #define mk_wcswidth_cjk(pwcs, n) _nc_wcswidth_cjk(pwcs, n)
 
-extern int mk_wcwidth(wchar_t);
-extern int mk_wcswidth(const wchar_t *, size_t);
-extern int mk_wcwidth_cjk(wchar_t);
-extern int mk_wcswidth_cjk(const wchar_t *, size_t);
+NCURSES_EXPORT(int) mk_wcwidth(wchar_t);
+NCURSES_EXPORT(int) mk_wcswidth(const wchar_t *, size_t);
+NCURSES_EXPORT(int) mk_wcwidth_cjk(wchar_t);
+NCURSES_EXPORT(int) mk_wcswidth_cjk(const wchar_t *, size_t);
 
 #include <wcwidth.h>
 #else
diff --git a/ncurses/win32con/win32_driver.c b/ncurses/win32con/win32_driver.c
new file mode 100644
index 0000000..0a43588
--- /dev/null
+++ b/ncurses/win32con/win32_driver.c
@@ -0,0 +1,1225 @@
+/****************************************************************************
+ * Copyright 2018-2020,2023 Thomas E. Dickey                                *
+ * Copyright 2008-2016,2017 Free Software Foundation, Inc.                  *
+ *                                                                          *
+ * Permission is hereby granted, free of charge, to any person obtaining a  *
+ * copy of this software and associated documentation files (the            *
+ * "Software"), to deal in the Software without restriction, including      *
+ * without limitation the rights to use, copy, modify, merge, publish,      *
+ * distribute, distribute with modifications, sublicense, and/or sell       *
+ * copies of the Software, and to permit persons to whom the Software is    *
+ * furnished to do so, subject to the following conditions:                 *
+ *                                                                          *
+ * The above copyright notice and this permission notice shall be included  *
+ * in all copies or substantial portions of the Software.                   *
+ *                                                                          *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
+ * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
+ * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
+ *                                                                          *
+ * Except as contained in this notice, the name(s) of the above copyright   *
+ * holders shall not be used in advertising or otherwise to promote the     *
+ * sale, use or other dealings in this Software without prior written       *
+ * authorization.                                                           *
+ ****************************************************************************/
+
+/****************************************************************************
+ *  Author: Juergen Pfeifer                                                 *
+ *     and: Thomas E. Dickey                                                *
+ ****************************************************************************/
+
+/*
+ * TODO - improve screen-repainting performance, using implied wraparound to reduce write's
+ * TODO - make it optional whether screen is restored or not when non-buffered
+ */
+
+#include <curses.priv.h>
+#ifdef _NC_WINDOWS
+#if (defined(__MINGW32__) || defined(__MINGW64__))
+#include <wchar.h>
+#else
+#include <tchar.h>
+#endif
+#include <io.h>
+
+#define CUR TerminalType(my_term).
+
+MODULE_ID("$Id: win32_driver.c,v 1.4 2023/09/16 16:29:24 tom Exp $")
+
+#define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
+#define EXP_OPTIMIZE 0
+
+static bool console_initialized = FALSE;
+
+#define AssertTCB() assert(TCB != 0 && (TCB->magic == WINMAGIC))
+#define validateConsoleHandle() (AssertTCB() , console_initialized ||\
+                                 (console_initialized=\
+                                  _nc_console_checkinit(TRUE,FALSE)))
+#define SetSP() assert(TCB->csp != 0); sp = TCB->csp; (void) sp
+#define AdjustY() (WINCONSOLE.buffered ?\
+                   0 : (int) WINCONSOLE.SBI.srWindow.Top)
+#define RevAttr(attr) (WORD) (((attr) & 0xff00) |   \
+                              ((((attr) & 0x07) << 4) | \
+                               (((attr) & 0x70) >> 4)))
+
+#if USE_WIDEC_SUPPORT
+#define write_screen WriteConsoleOutputW
+#define read_screen  ReadConsoleOutputW
+#else
+#define write_screen WriteConsoleOutput
+#define read_screen  ReadConsoleOutput
+#endif
+
+static WORD
+MapAttr(WORD res, attr_t ch)
+{
+    if (ch & A_COLOR) {
+	int p;
+
+	p = PairNumber(ch);
+	if (p > 0 && p < CON_NUMPAIRS) {
+	    WORD a;
+	    a = WINCONSOLE.pairs[p];
+	    res = (WORD) ((res & 0xff00) | a);
+	}
+    }
+
+    if (ch & A_REVERSE) {
+	res = RevAttr(res);
+    }
+
+    if (ch & A_STANDOUT) {
+	res = RevAttr(res) | BACKGROUND_INTENSITY;
+    }
+
+    if (ch & A_BOLD)
+	res |= FOREGROUND_INTENSITY;
+
+    if (ch & A_DIM)
+	res |= BACKGROUND_INTENSITY;
+
+    return res;
+}
+
+#if 0				/* def TRACE */
+static void
+dump_screen(const char *fn, int ln)
+{
+    int max_cells = (WINCONSOLE.SBI.dwSize.Y *
+		     (1 + WINCONSOLE.SBI.dwSize.X)) + 1;
+    char output[max_cells];
+    CHAR_INFO save_screen[max_cells];
+    COORD save_size;
+    SMALL_RECT save_region;
+    COORD bufferCoord;
+
+    T(("dump_screen %s@%d", fn, ln));
+
+    save_region.Top = WINCONSOLE.SBI.srWindow.Top;
+    save_region.Left = WINCONSOLE.SBI.srWindow.Left;
+    save_region.Bottom = WINCONSOLE.SBI.srWindow.Bottom;
+    save_region.Right = WINCONSOLE.SBI.srWindow.Right;
+
+    save_size.X = (SHORT) (save_region.Right - save_region.Left + 1);
+    save_size.Y = (SHORT) (save_region.Bottom - save_region.Top + 1);
+
+    bufferCoord.X = bufferCoord.Y = 0;
+
+    if (read_screen(WINCONSOLE.hdl,
+		    save_screen,
+		    save_size,
+		    bufferCoord,
+		    &save_region)) {
+	int i, j;
+	int ij = 0;
+	int k = 0;
+
+	for (i = save_region.Top; i <= save_region.Bottom; ++i) {
+	    for (j = save_region.Left; j <= save_region.Right; ++j) {
+		output[k++] = save_screen[ij++].Char.AsciiChar;
+	    }
+	    output[k++] = '\n';
+	}
+	output[k] = 0;
+
+	T(("DUMP: %d,%d - %d,%d",
+	   save_region.Top,
+	   save_region.Left,
+	   save_region.Bottom,
+	   save_region.Right));
+	T(("%s", output));
+    }
+}
+
+#else
+#define dump_screen(fn,ln)	/* nothing */
+#endif
+
+#if USE_WIDEC_SUPPORT
+/*
+ * TODO: support surrogate pairs
+ * TODO: support combining characters
+ * TODO: support acsc
+ * TODO: _nc_wacs should be part of sp.
+ */
+static BOOL
+con_write16(TERMINAL_CONTROL_BLOCK * TCB,
+	    int y, int x, cchar_t *str, int limit)
+{
+    int actual = 0;
+    CHAR_INFO *ci = TypeAlloca(CHAR_INFO, limit);
+    COORD loc, siz;
+    SMALL_RECT rec;
+    int i;
+    cchar_t ch;
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+
+    for (i = actual = 0; i < limit; i++) {
+	ch = str[i];
+	if (isWidecExt(ch))
+	    continue;
+	ci[actual].Char.UnicodeChar = CharOf(ch);
+	ci[actual].Attributes = MapAttr(WINCONSOLE.SBI.wAttributes,
+					AttrOf(ch));
+	if (AttrOf(ch) & A_ALTCHARSET) {
+	    if (_nc_wacs) {
+		int which = CharOf(ch);
+		if (which > 0
+		    && which < ACS_LEN
+		    && CharOf(_nc_wacs[which]) != 0) {
+		    ci[actual].Char.UnicodeChar = CharOf(_nc_wacs[which]);
+		} else {
+		    ci[actual].Char.UnicodeChar = ' ';
+		}
+	    }
+	}
+	++actual;
+    }
+
+    loc.X = (SHORT) 0;
+    loc.Y = (SHORT) 0;
+    siz.X = (SHORT) actual;
+    siz.Y = 1;
+
+    rec.Left = (SHORT) x;
+    rec.Top = (SHORT) (y + AdjustY());
+    rec.Right = (SHORT) (x + limit - 1);
+    rec.Bottom = rec.Top;
+
+    return write_screen(WINCONSOLE.hdl, ci, siz, loc, &rec);
+}
+#define con_write(tcb, y, x, str, n) con_write16(tcb, y, x, str, n)
+#else
+static BOOL
+con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
+{
+    CHAR_INFO *ci = TypeAlloca(CHAR_INFO, n);
+    COORD loc, siz;
+    SMALL_RECT rec;
+    int i;
+    chtype ch;
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+
+    for (i = 0; i < n; i++) {
+	ch = str[i];
+	ci[i].Char.AsciiChar = ChCharOf(ch);
+	ci[i].Attributes = MapAttr(WINCONSOLE.SBI.wAttributes,
+				   ChAttrOf(ch));
+	if (ChAttrOf(ch) & A_ALTCHARSET) {
+	    if (sp->_acs_map)
+		ci[i].Char.AsciiChar =
+		ChCharOf(NCURSES_SP_NAME(_nc_acs_char) (sp, ChCharOf(ch)));
+	}
+    }
+
+    loc.X = (short) 0;
+    loc.Y = (short) 0;
+    siz.X = (short) n;
+    siz.Y = 1;
+
+    rec.Left = (short) x;
+    rec.Top = (short) y;
+    rec.Right = (short) (x + n - 1);
+    rec.Bottom = rec.Top;
+
+    return write_screen(WINCONSOLE.hdl, ci, siz, loc, &rec);
+}
+#define con_write(tcb, y, x, str, n) con_write8(tcb, y, x, str, n)
+#endif
+
+#if EXP_OPTIMIZE
+/*
+ * Comparing new/current screens, determine the last column-index for a change
+ * beginning on the given row,col position.  Unlike a serial terminal, there is
+ * no cost for "moving" the "cursor" on the line as we update it.
+ */
+static int
+find_end_of_change(SCREEN *sp, int row, int col)
+{
+    int result = col;
+    struct ldat *curdat = CurScreen(sp)->_line + row;
+    struct ldat *newdat = NewScreen(sp)->_line + row;
+
+    while (col <= newdat->lastchar) {
+#if USE_WIDEC_SUPPORT
+	if (isWidecExt(curdat->text[col]) ||
+	    isWidecExt(newdat->text[col])) {
+	    result = col;
+	} else if (memcmp(&curdat->text[col],
+			  &newdat->text[col],
+			  sizeof(curdat->text[0]))) {
+	    result = col;
+	} else {
+	    break;
+	}
+#else
+	if (curdat->text[col] != newdat->text[col]) {
+	    result = col;
+	} else {
+	    break;
+	}
+#endif
+	++col;
+    }
+    return result;
+}
+
+/*
+ * Given a row,col position at the end of a change-chunk, look for the
+ * beginning of the next change-chunk.
+ */
+static int
+find_next_change(SCREEN *sp, int row, int col)
+{
+    struct ldat *curdat = CurScreen(sp)->_line + row;
+    struct ldat *newdat = NewScreen(sp)->_line + row;
+    int result = newdat->lastchar + 1;
+
+    while (++col <= newdat->lastchar) {
+#if USE_WIDEC_SUPPORT
+	if (isWidecExt(curdat->text[col]) !=
+	    isWidecExt(newdat->text[col])) {
+	    result = col;
+	    break;
+	} else if (memcmp(&curdat->text[col],
+			  &newdat->text[col],
+			  sizeof(curdat->text[0]))) {
+	    result = col;
+	    break;
+	}
+#else
+	if (curdat->text[col] != newdat->text[col]) {
+	    result = col;
+	    break;
+	}
+#endif
+    }
+    return result;
+}
+
+#define EndChange(first) \
+	find_end_of_change(sp, y, first)
+#define NextChange(last)                        \
+	find_next_change(sp, y, last)
+
+#endif /* EXP_OPTIMIZE */
+
+#define MARK_NOCHANGE(win,row)                 \
+    win->_line[row].firstchar = _NOCHANGE;     \
+    win->_line[row].lastchar  = _NOCHANGE
+
+static bool
+restore_original_screen(void)
+{
+    COORD bufferCoord;
+    bool result = FALSE;
+    SMALL_RECT save_region = WINCONSOLE.save_region;
+
+    T(("... restoring %s", WINCONSOLE.window_only ?
+       "window" : "entire buffer"));
+
+    bufferCoord.X = (SHORT) (WINCONSOLE.window_only ?
+			     WINCONSOLE.SBI.srWindow.Left : 0);
+    bufferCoord.Y = (SHORT) (WINCONSOLE.window_only ?
+			     WINCONSOLE.SBI.srWindow.Top : 0);
+
+    if (write_screen(WINCONSOLE.hdl,
+		     WINCONSOLE.save_screen,
+		     WINCONSOLE.save_size,
+		     bufferCoord,
+		     &save_region)) {
+	result = TRUE;
+	mvcur(-1, -1, LINES - 2, 0);
+	T(("... restore original screen contents ok %dx%d (%d,%d - %d,%d)",
+	   WINCONSOLE.save_size.Y,
+	   WINCONSOLE.save_size.X,
+	   save_region.Top,
+	   save_region.Left,
+	   save_region.Bottom,
+	   save_region.Right));
+    } else {
+	T(("... restore original screen contents err"));
+    }
+    return result;
+}
+
+static const char *
+wcon_name(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    (void) TCB;
+    return "win32console";
+}
+
+static int
+wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    int result = ERR;
+    int y, nonempty, n, x0, x1, Width, Height;
+    SCREEN *sp;
+
+    T((T_CALLED("win32con::wcon_doupdate(%p)"), TCB));
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	Width = screen_columns(sp);
+	Height = screen_lines(sp);
+	nonempty = Min(Height, NewScreen(sp)->_maxy + 1);
+
+	T(("... %dx%d clear cur:%d new:%d",
+	   Height, Width,
+	   CurScreen(sp)->_clear,
+	   NewScreen(sp)->_clear));
+
+	if (SP_PARM->_endwin == ewSuspend) {
+
+	    T(("coming back from shell mode"));
+	    NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_ARG);
+
+	    NCURSES_SP_NAME(_nc_mvcur_resume) (NCURSES_SP_ARG);
+	    NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_ARG);
+	    SP_PARM->_mouse_resume(SP_PARM);
+
+	    SP_PARM->_endwin = ewRunning;
+	}
+
+	if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
+	    int x;
+#if USE_WIDEC_SUPPORT
+	    cchar_t *empty = TypeAlloca(cchar_t, Width);
+	    wchar_t blank[2] =
+	    {
+		L' ', L'\0'
+	    };
+
+	    for (x = 0; x < Width; x++)
+		setcchar(&empty[x], blank, 0, 0, 0);
+#else
+	    chtype *empty = TypeAlloca(chtype, Width);
+
+	    for (x = 0; x < Width; x++)
+		empty[x] = ' ';
+#endif
+
+	    for (y = 0; y < nonempty; y++) {
+		con_write(TCB, y, 0, empty, Width);
+		memcpy(empty,
+		       CurScreen(sp)->_line[y].text,
+		       (size_t) Width * sizeof(empty[0]));
+	    }
+	    CurScreen(sp)->_clear = FALSE;
+	    NewScreen(sp)->_clear = FALSE;
+	    touchwin(NewScreen(sp));
+	    T(("... cleared %dx%d lines @%d of screen", nonempty, Width,
+	       AdjustY()));
+	}
+
+	for (y = 0; y < nonempty; y++) {
+	    x0 = NewScreen(sp)->_line[y].firstchar;
+	    if (x0 != _NOCHANGE) {
+#if EXP_OPTIMIZE
+		int x2;
+		int limit = NewScreen(sp)->_line[y].lastchar;
+		while ((x1 = EndChange(x0)) <= limit) {
+		    while ((x2 = NextChange(x1)) <=
+			   limit && x2 <= (x1 + 2)) {
+			x1 = x2;
+		    }
+		    n = x1 - x0 + 1;
+		    memcpy(&CurScreen(sp)->_line[y].text[x0],
+			   &NewScreen(sp)->_line[y].text[x0],
+			   n * sizeof(CurScreen(sp)->_line[y].text[x0]));
+		    con_write(TCB,
+			      y,
+			      x0,
+			      &CurScreen(sp)->_line[y].text[x0], n);
+		    x0 = NextChange(x1);
+		}
+
+		/* mark line changed successfully */
+		if (y <= NewScreen(sp)->_maxy) {
+		    MARK_NOCHANGE(NewScreen(sp), y);
+		}
+		if (y <= CurScreen(sp)->_maxy) {
+		    MARK_NOCHANGE(CurScreen(sp), y);
+		}
+#else
+		x1 = NewScreen(sp)->_line[y].lastchar;
+		n = x1 - x0 + 1;
+		if (n > 0) {
+		    memcpy(&CurScreen(sp)->_line[y].text[x0],
+			   &NewScreen(sp)->_line[y].text[x0],
+			   (size_t) n *
+			   sizeof(CurScreen(sp)->_line[y].text[x0]));
+		    con_write(TCB,
+			      y,
+			      x0,
+			      &CurScreen(sp)->_line[y].text[x0], n);
+
+		    /* mark line changed successfully */
+		    if (y <= NewScreen(sp)->_maxy) {
+			MARK_NOCHANGE(NewScreen(sp), y);
+		    }
+		    if (y <= CurScreen(sp)->_maxy) {
+			MARK_NOCHANGE(CurScreen(sp), y);
+		    }
+		}
+#endif
+	    }
+	}
+
+	/* put everything back in sync */
+	for (y = nonempty; y <= NewScreen(sp)->_maxy; y++) {
+	    MARK_NOCHANGE(NewScreen(sp), y);
+	}
+	for (y = nonempty; y <= CurScreen(sp)->_maxy; y++) {
+	    MARK_NOCHANGE(CurScreen(sp), y);
+	}
+
+	if (!NewScreen(sp)->_leaveok) {
+	    CurScreen(sp)->_curx = NewScreen(sp)->_curx;
+	    CurScreen(sp)->_cury = NewScreen(sp)->_cury;
+
+	    TCB->drv->td_hwcur(TCB,
+			       0,
+			       0,
+			       CurScreen(sp)->_cury,
+			       CurScreen(sp)->_curx);
+	}
+	_nc_console_selectActiveHandle();
+	result = OK;
+    }
+    returnCode(result);
+}
+
+static bool
+wcon_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
+	       const char *tname,
+	       int *errret GCC_UNUSED)
+{
+    bool code = FALSE;
+
+    T((T_CALLED("win32con::wcon_CanHandle(%p)"), TCB));
+
+    assert((TCB != 0) && (tname != 0));
+
+    TCB->magic = WINMAGIC;
+
+    if (tname == 0 || *tname == 0) {
+	if (!_nc_console_vt_supported())
+	    code = TRUE;
+    } else if (tname != 0 && *tname == '#') {
+	/*
+	 * Use "#" (a character which cannot begin a terminal's name) to
+	 * select specific driver from the table.
+	 *
+	 * In principle, we could have more than one non-terminfo driver,
+	 * e.g., "win32gui".
+	 */
+	size_t n = strlen(tname + 1);
+	if (n != 0
+	    && ((strncmp(tname + 1, "win32console", n) == 0)
+		|| (strncmp(tname + 1, "win32con", n) == 0))) {
+	    code = TRUE;
+	}
+    } else if (tname != 0 && stricmp(tname, "unknown") == 0) {
+	code = TRUE;
+    }
+
+    /*
+     * This is intentional, to avoid unnecessary breakage of applications
+     * using <term.h> symbols.
+     */
+    if (code && (TerminalType(&TCB->term).Booleans == 0)) {
+	_nc_init_termtype(&TerminalType(&TCB->term));
+#if NCURSES_EXT_NUMBERS
+	_nc_export_termtype2(&TCB->term.type, &TerminalType(&TCB->term));
+#endif
+    }
+
+    if (!code) {
+	if (_nc_console_test(0)) {
+	    T(("isTermInfoConsole=TRUE"));
+	    WINCONSOLE.isTermInfoConsole = TRUE;
+	}
+    }
+    returnBool(code);
+}
+
+static int
+wcon_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
+		 int beepFlag)
+{
+    SCREEN *sp;
+    int res = ERR;
+
+    int high = (WINCONSOLE.SBI.srWindow.Bottom -
+		WINCONSOLE.SBI.srWindow.Top + 1);
+    int wide = (WINCONSOLE.SBI.srWindow.Right -
+		WINCONSOLE.SBI.srWindow.Left + 1);
+    int max_cells = (high * wide);
+    int i;
+
+    CHAR_INFO *this_screen = TypeAlloca(CHAR_INFO, max_cells);
+    CHAR_INFO *that_screen = TypeAlloca(CHAR_INFO, max_cells);
+    COORD this_size;
+    SMALL_RECT this_region;
+    COORD bufferCoord;
+
+    if (validateConsoleHandle()) {
+	SetSP();
+	this_region.Top = WINCONSOLE.SBI.srWindow.Top;
+	this_region.Left = WINCONSOLE.SBI.srWindow.Left;
+	this_region.Bottom = WINCONSOLE.SBI.srWindow.Bottom;
+	this_region.Right = WINCONSOLE.SBI.srWindow.Right;
+
+	this_size.X = (SHORT) wide;
+	this_size.Y = (SHORT) high;
+
+	bufferCoord.X = this_region.Left;
+	bufferCoord.Y = this_region.Top;
+
+	if (!beepFlag &&
+	    read_screen(WINCONSOLE.hdl,
+			this_screen,
+			this_size,
+			bufferCoord,
+			&this_region)) {
+
+	    memcpy(that_screen,
+		   this_screen,
+		   sizeof(CHAR_INFO) * (size_t) max_cells);
+
+	    for (i = 0; i < max_cells; i++) {
+		that_screen[i].Attributes =
+		    RevAttr(that_screen[i].Attributes);
+	    }
+
+	    write_screen(WINCONSOLE.hdl, that_screen, this_size,
+			 bufferCoord, &this_region);
+	    Sleep(200);
+	    write_screen(WINCONSOLE.hdl, this_screen, this_size,
+			 bufferCoord, &this_region);
+
+	} else {
+	    MessageBeep(MB_ICONWARNING);	/* MB_OK might be better */
+	}
+	res = OK;
+    }
+    return res;
+}
+
+static int
+wcon_print(TERMINAL_CONTROL_BLOCK * TCB,
+	   char *data GCC_UNUSED,
+	   int len GCC_UNUSED)
+{
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+
+    return ERR;
+}
+
+static int
+wcon_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
+		   int fg GCC_UNUSED,
+		   int bg GCC_UNUSED)
+{
+    SCREEN *sp;
+    int code = ERR;
+
+    AssertTCB();
+    SetSP();
+
+    return (code);
+}
+
+static void
+wcon_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
+	      int fore,
+	      int color,
+	      int (*outc) (SCREEN *, int) GCC_UNUSED)
+{
+    (void) TCB;
+    if (validateConsoleHandle()) {
+	WORD a = _nc_console_MapColor(fore, color);
+	a |= (WORD) ((WINCONSOLE.SBI.wAttributes) & (fore ? 0xfff8 : 0xff8f));
+	SetConsoleTextAttribute(WINCONSOLE.hdl, a);
+	_nc_console_get_SBI();
+    }
+}
+
+static bool
+wcon_rescol(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    bool res = FALSE;
+
+    (void) TCB;
+    if (validateConsoleHandle()) {
+	WORD a = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
+	SetConsoleTextAttribute(WINCONSOLE.hdl, a);
+	_nc_console_get_SBI();
+	res = TRUE;
+    }
+    return res;
+}
+
+static bool
+wcon_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    int result = FALSE;
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+
+    return result;
+}
+
+static int
+wcon_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
+{
+    int result = ERR;
+
+    T((T_CALLED("win32con::wcon_size(%p)"), TCB));
+
+    if (validateConsoleHandle() &&
+	(Lines != NULL) && (Cols != NULL)) {
+	_nc_console_size(Lines, Cols);
+	result = OK;
+    }
+    returnCode(result);
+}
+
+static int
+wcon_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
+	     int l GCC_UNUSED,
+	     int c GCC_UNUSED)
+{
+    AssertTCB();
+    return ERR;
+}
+
+static int
+wcon_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
+{
+    int result = ERR;
+
+    T((T_CALLED("win32con::wcon_sgmode(TCB=(%p),setFlag=%d,TTY=(%p)"),
+       TCB, setFlag, buf));
+    if (buf != NULL && validateConsoleHandle()) {
+
+	if (setFlag) {
+	    _nc_console_setmode(WINCONSOLE.hdl, buf);
+	    TCB->term.Nttyb = *buf;
+	} else {
+	    _nc_console_getmode(WINCONSOLE.hdl, &(TCB->term.Nttyb));
+	    *buf = TCB->term.Nttyb;
+	}
+	result = OK;
+    }
+    returnCode(result);
+}
+
+#define MIN_WIDE 80
+#define MIN_HIGH 24
+
+static int
+wcon_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
+{
+    SCREEN *sp;
+    TERMINAL *_term = (TERMINAL *) TCB;
+    int code = ERR;
+
+    if (validateConsoleHandle()) {
+	sp = TCB->csp;
+
+	T((T_CALLED("win32con::wcon_mode(%p, progFlag=%d, defFlag=%d)"),
+	   TCB, progFlag, defFlag));
+
+	WINCONSOLE.progMode = progFlag;
+	WINCONSOLE.lastOut = progFlag ? WINCONSOLE.hdl : WINCONSOLE.out;
+	SetConsoleActiveScreenBuffer(WINCONSOLE.lastOut);
+
+	if (progFlag) /* prog mode */  {
+	    if (defFlag) {
+		if ((wcon_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
+		    code = OK;
+		}
+	    } else {
+		/* reset_prog_mode */
+		if (wcon_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
+		    if (sp) {
+			if (sp->_keypad_on)
+			    _nc_keypad(sp, TRUE);
+		    }
+		    if (!WINCONSOLE.buffered) {
+			_nc_console_set_scrollback(FALSE, &WINCONSOLE.SBI);
+		    }
+		    code = OK;
+		}
+	    }
+	    T(("... buffered:%d, clear:%d",
+	       WINCONSOLE.buffered, CurScreen(sp)->_clear));
+	} else {		/* shell mode */
+	    if (defFlag) {
+		/* def_shell_mode */
+		if (wcon_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
+		    code = OK;
+		}
+	    } else {
+		/* reset_shell_mode */
+		if (sp) {
+		    _nc_keypad(sp, FALSE);
+		    NCURSES_SP_NAME(_nc_flush) (sp);
+		}
+		code = wcon_sgmode(TCB, TRUE, &(_term->Ottyb));
+		if (!WINCONSOLE.buffered) {
+		    _nc_console_set_scrollback(TRUE, &WINCONSOLE.save_SBI);
+		    if (!restore_original_screen())
+			code = ERR;
+		}
+		SetConsoleCursorInfo(WINCONSOLE.hdl, &WINCONSOLE.save_CI);
+	    }
+	}
+
+    }
+    returnCode(code);
+}
+
+static void
+wcon_screen_init(SCREEN *sp GCC_UNUSED)
+{
+}
+
+static void
+wcon_wrap(SCREEN *sp GCC_UNUSED)
+{
+}
+
+static void
+wcon_release(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    T((T_CALLED("win32con::wcon_release(%p)"), TCB));
+
+    AssertTCB();
+    if (TCB->prop)
+	free(TCB->prop);
+
+    returnVoid;
+}
+
+static void
+wcon_init(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    T((T_CALLED("win32con::wcon_init(%p)"), TCB));
+
+    AssertTCB();
+
+    if (!(console_initialized = _nc_console_checkinit(TRUE, FALSE))) {
+	returnVoid;
+    }
+
+    if (TCB) {
+	TCB->info.initcolor = TRUE;
+	TCB->info.canchange = FALSE;
+	TCB->info.hascolor = TRUE;
+	TCB->info.caninit = TRUE;
+
+	TCB->info.maxpairs = CON_NUMPAIRS;
+	TCB->info.maxcolors = 8;
+	TCB->info.numlabels = 0;
+	TCB->info.labelwidth = 0;
+	TCB->info.labelheight = 0;
+	TCB->info.nocolorvideo = 1;
+	TCB->info.tabsize = 8;
+
+	TCB->info.numbuttons = WINCONSOLE.numButtons;
+	TCB->info.defaultPalette = _nc_cga_palette;
+
+    }
+    returnVoid;
+}
+
+static void
+wcon_initpair(TERMINAL_CONTROL_BLOCK * TCB,
+	      int pair,
+	      int f,
+	      int b)
+{
+    SCREEN *sp;
+
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	if ((pair > 0) && (pair < CON_NUMPAIRS) && (f >= 0) && (f < 8)
+	    && (b >= 0) && (b < 8)) {
+	    WINCONSOLE.pairs[pair] =
+		_nc_console_MapColor(true, f) |
+		_nc_console_MapColor(false, b);
+	}
+    }
+}
+
+static void
+wcon_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
+	       int color GCC_UNUSED,
+	       int r GCC_UNUSED,
+	       int g GCC_UNUSED,
+	       int b GCC_UNUSED)
+{
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+}
+
+static void
+wcon_do_color(TERMINAL_CONTROL_BLOCK * TCB,
+	      int old_pair GCC_UNUSED,
+	      int pair GCC_UNUSED,
+	      int reverse GCC_UNUSED,
+	      int (*outc) (SCREEN *, int) GCC_UNUSED
+)
+{
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+}
+
+static void
+wcon_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    SCREEN *sp;
+
+    T((T_CALLED("win32con::wcon_initmouse(%p)"), TCB));
+
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	sp->_mouse_type = M_TERM_DRIVER;
+    }
+    returnVoid;
+}
+
+static int
+wcon_testmouse(TERMINAL_CONTROL_BLOCK * TCB,
+	       int delay
+	       EVENTLIST_2nd(_nc_eventlist * evl))
+{
+    int rc = 0;
+    SCREEN *sp;
+
+    T((T_CALLED("win32con::wcon_testmouse(%p)"), TCB));
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
+	    rc = TW_MOUSE;
+	} else {
+	    rc = TCBOf(sp)->drv->td_twait(TCBOf(sp),
+					  TWAIT_MASK,
+					  delay,
+					  (int *) 0
+					  EVENTLIST_2nd(evl));
+	}
+    }
+
+    returnCode(rc);
+}
+
+static int
+wcon_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
+	   int yold GCC_UNUSED, int xold GCC_UNUSED,
+	   int y, int x)
+{
+    int ret = ERR;
+
+    (void) TCB;
+    if (validateConsoleHandle()) {
+	COORD loc;
+	loc.X = (short) x;
+	loc.Y = (short) (y + AdjustY());
+	SetConsoleCursorPosition(WINCONSOLE.hdl, loc);
+	ret = OK;
+    }
+    return ret;
+}
+
+static void
+wcon_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
+	     int labnum GCC_UNUSED,
+	     char *text GCC_UNUSED)
+{
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+}
+
+static void
+wcon_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
+		  int OnFlag GCC_UNUSED)
+{
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+}
+
+static chtype
+wcon_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
+{
+    chtype res = A_NORMAL;
+    res |= (A_BOLD | A_DIM | A_REVERSE | A_STANDOUT | A_COLOR);
+    return res;
+}
+
+static void
+wcon_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    SCREEN *sp;
+
+    AssertTCB();
+    SetSP();
+}
+
+static void
+wcon_initacs(TERMINAL_CONTROL_BLOCK * TCB,
+	     chtype *real_map GCC_UNUSED,
+	     chtype *fake_map GCC_UNUSED)
+{
+#define DATA(a,b) { a, b }
+    static struct {
+	int acs_code;
+	int use_code;
+    } table[] = {
+	DATA('a', 0xb1),	/* ACS_CKBOARD  */
+	    DATA('f', 0xf8),	/* ACS_DEGREE   */
+	    DATA('g', 0xf1),	/* ACS_PLMINUS  */
+	    DATA('j', 0xd9),	/* ACS_LRCORNER */
+	    DATA('l', 0xda),	/* ACS_ULCORNER */
+	    DATA('k', 0xbf),	/* ACS_URCORNER */
+	    DATA('m', 0xc0),	/* ACS_LLCORNER */
+	    DATA('n', 0xc5),	/* ACS_PLUS     */
+	    DATA('q', 0xc4),	/* ACS_HLINE    */
+	    DATA('t', 0xc3),	/* ACS_LTEE     */
+	    DATA('u', 0xb4),	/* ACS_RTEE     */
+	    DATA('v', 0xc1),	/* ACS_BTEE     */
+	    DATA('w', 0xc2),	/* ACS_TTEE     */
+	    DATA('x', 0xb3),	/* ACS_VLINE    */
+	    DATA('y', 0xf3),	/* ACS_LEQUAL   */
+	    DATA('z', 0xf2),	/* ACS_GEQUAL   */
+	    DATA('0', 0xdb),	/* ACS_BLOCK    */
+	    DATA('{', 0xe3),	/* ACS_PI       */
+	    DATA('}', 0x9c),	/* ACS_STERLING */
+	    DATA(',', 0xae),	/* ACS_LARROW   */
+	    DATA('+', 0xaf),	/* ACS_RARROW   */
+	    DATA('~', 0xf9),	/* ACS_BULLET   */
+    };
+#undef DATA
+    unsigned n;
+
+    SCREEN *sp;
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	for (n = 0; n < SIZEOF(table); ++n) {
+	    real_map[table[n].acs_code] =
+		(chtype) table[n].use_code | A_ALTCHARSET;
+	    if (sp != 0)
+		sp->_screen_acs_map[table[n].acs_code] = TRUE;
+	}
+    }
+}
+
+static int
+wcon_twait(TERMINAL_CONTROL_BLOCK * TCB,
+	   int mode,
+	   int milliseconds,
+	   int *timeleft
+	   EVENTLIST_2nd(_nc_eventlist * evl))
+{
+    SCREEN *sp;
+    int code = 0;
+
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	code = _nc_console_twait(sp,
+				 WINCONSOLE.inp,
+				 mode,
+				 milliseconds,
+				 timeleft EVENTLIST_2nd(evl));
+    }
+    return code;
+}
+
+static int
+wcon_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
+{
+    SCREEN *sp;
+    int n = -1;
+
+    T((T_CALLED("win32con::wcon_read(%p)"), TCB));
+
+    assert(buf);
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	n = _nc_console_read(sp, WINCONSOLE.inp, buf);
+    }
+    returnCode(n);
+}
+
+static int
+wcon_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
+{
+    T((T_CALLED("win32con::wcon_nap(%p, %d)"), TCB, ms));
+    Sleep((DWORD) ms);
+    returnCode(OK);
+}
+
+static int
+wcon_cursorSet(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int mode)
+{
+    int res = -1;
+
+    T((T_CALLED("win32con:wcon_cursorSet(%d)"), mode));
+    if (validateConsoleHandle()) {
+	CONSOLE_CURSOR_INFO this_CI = WINCONSOLE.save_CI;
+	switch (mode) {
+	case 0:
+	    this_CI.bVisible = FALSE;
+	    break;
+	case 1:
+	    break;
+	case 2:
+	    this_CI.dwSize = 100;
+	    break;
+	}
+	SetConsoleCursorInfo(WINCONSOLE.hdl, &this_CI);
+    }
+    returnCode(res);
+}
+
+static bool
+wcon_kyExist(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int keycode)
+{
+    bool found = FALSE;
+
+    T((T_CALLED("win32con::wcon_kyExist(%d)"), keycode));
+    found = _nc_console_keyExist(keycode);
+    returnBool(found);
+}
+
+static int
+wcon_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
+{
+    SCREEN *sp;
+    int code = ERR;
+
+    T((T_CALLED("win32con::wcon_kpad(%p, %d)"), TCB, flag));
+
+    if (validateConsoleHandle()) {
+	SetSP();
+
+	if (sp) {
+	    code = OK;
+	}
+    }
+    returnCode(code);
+}
+
+static int
+wcon_keyok(TERMINAL_CONTROL_BLOCK * TCB,
+	   int keycode,
+	   int flag)
+{
+    int code = ERR;
+    SCREEN *sp;
+
+    T((T_CALLED("win32con::wcon_keyok(%p, %d, %d)"), TCB, keycode, flag));
+
+    if (validateConsoleHandle()) {
+	SetSP();
+	if (sp) {
+	    code = _nc_console_keyok(keycode, flag);
+	}
+    }
+    returnCode(code);
+}
+
+NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
+    FALSE,
+	wcon_name,		/* Name          */
+	wcon_CanHandle,		/* CanHandle     */
+	wcon_init,		/* init          */
+	wcon_release,		/* release       */
+	wcon_size,		/* size          */
+	wcon_sgmode,		/* sgmode        */
+	wcon_conattr,		/* conattr       */
+	wcon_mvcur,		/* hwcur         */
+	wcon_mode,		/* mode          */
+	wcon_rescol,		/* rescol        */
+	wcon_rescolors,		/* rescolors     */
+	wcon_setcolor,		/* color         */
+	wcon_dobeepflash,	/* DoBeepFlash   */
+	wcon_initpair,		/* initpair      */
+	wcon_initcolor,		/* initcolor     */
+	wcon_do_color,		/* docolor       */
+	wcon_initmouse,		/* initmouse     */
+	wcon_testmouse,		/* testmouse     */
+	wcon_setfilter,		/* setfilter     */
+	wcon_hwlabel,		/* hwlabel       */
+	wcon_hwlabelOnOff,	/* hwlabelOnOff  */
+	wcon_doupdate,		/* update        */
+	wcon_defaultcolors,	/* defaultcolors */
+	wcon_print,		/* print         */
+	wcon_size,		/* getsize       */
+	wcon_setsize,		/* setsize       */
+	wcon_initacs,		/* initacs       */
+	wcon_screen_init,	/* scinit        */
+	wcon_wrap,		/* scexit        */
+	wcon_twait,		/* twait         */
+	wcon_read,		/* read          */
+	wcon_nap,		/* nap           */
+	wcon_kpad,		/* kpad          */
+	wcon_keyok,		/* kyOk          */
+	wcon_kyExist,		/* kyExist       */
+	wcon_cursorSet		/* cursorSet     */
+};
+
+#endif /* _NC_WINDOWS */
diff --git a/ncurses/win32con/win_driver.c b/ncurses/win32con/win_driver.c
index 78ccfed..2425b3a 100644
--- a/ncurses/win32con/win_driver.c
+++ b/ncurses/win32con/win_driver.c
@@ -1,5 +1,6 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright 2018-2021,2023 Thomas E. Dickey                                *
+ * Copyright 2008-2016,2017 Free Software Foundation, Inc.                  *
  *                                                                          *
  * Permission is hereby granted, free of charge, to any person obtaining a  *
  * copy of this software and associated documentation files (the            *
@@ -40,7 +41,7 @@
 
 #include <curses.priv.h>
 
-#ifdef __MINGW32__
+#ifdef _WIN32
 #include <tchar.h>
 #else
 #include <windows.h>
@@ -52,13 +53,13 @@
 #define PSAPI_VERSION 2
 #include <psapi.h>
 
-#define CUR my_term.type.
+#define CUR TerminalType(my_term).
 
-MODULE_ID("$Id: win_driver.c,v 1.55 2015/02/28 21:30:23 tom Exp $")
+#define CONTROL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
 
-#ifndef __GNUC__
-#  error We need GCC to compile for MinGW
-#endif
+MODULE_ID("$Id: win_driver.c,v 1.74 2023/09/16 16:27:44 tom Exp $")
+
+#define TypeAlloca(type,count) (type*) _alloca(sizeof(type) * (size_t) (count))
 
 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
 
@@ -83,39 +84,40 @@
 #define write_screen WriteConsoleOutput
 #define read_screen  ReadConsoleOutput
 #endif
-
+/* *INDENT-OFF* */
 static const LONG keylist[] =
 {
-    GenMap(VK_PRIOR, KEY_PPAGE),
-    GenMap(VK_NEXT, KEY_NPAGE),
-    GenMap(VK_END, KEY_END),
-    GenMap(VK_HOME, KEY_HOME),
-    GenMap(VK_LEFT, KEY_LEFT),
-    GenMap(VK_UP, KEY_UP),
-    GenMap(VK_RIGHT, KEY_RIGHT),
-    GenMap(VK_DOWN, KEY_DOWN),
+    GenMap(VK_PRIOR,  KEY_PPAGE),
+    GenMap(VK_NEXT,   KEY_NPAGE),
+    GenMap(VK_END,    KEY_END),
+    GenMap(VK_HOME,   KEY_HOME),
+    GenMap(VK_LEFT,   KEY_LEFT),
+    GenMap(VK_UP,     KEY_UP),
+    GenMap(VK_RIGHT,  KEY_RIGHT),
+    GenMap(VK_DOWN,   KEY_DOWN),
     GenMap(VK_DELETE, KEY_DC),
     GenMap(VK_INSERT, KEY_IC)
 };
 static const LONG ansi_keys[] =
 {
-    GenMap(VK_PRIOR, 'I'),
-    GenMap(VK_NEXT, 'Q'),
-    GenMap(VK_END, 'O'),
-    GenMap(VK_HOME, 'H'),
-    GenMap(VK_LEFT, 'K'),
-    GenMap(VK_UP, 'H'),
-    GenMap(VK_RIGHT, 'M'),
-    GenMap(VK_DOWN, 'P'),
+    GenMap(VK_PRIOR,  'I'),
+    GenMap(VK_NEXT,   'Q'),
+    GenMap(VK_END,    'O'),
+    GenMap(VK_HOME,   'H'),
+    GenMap(VK_LEFT,   'K'),
+    GenMap(VK_UP,     'H'),
+    GenMap(VK_RIGHT,  'M'),
+    GenMap(VK_DOWN,   'P'),
     GenMap(VK_DELETE, 'S'),
     GenMap(VK_INSERT, 'R')
 };
+/* *INDENT-ON* */
 #define N_INI ((int)array_length(keylist))
 #define FKEYS 24
 #define MAPSIZE (FKEYS + N_INI)
 #define NUMPAIRS 64
 
-/*   A process can only have a single console, so it's safe
+/*   A process can only have a single console, so it is safe
      to maintain all the information about it in a single
      static structure.
  */
@@ -124,7 +126,6 @@
     BOOL buffered;
     BOOL window_only;
     BOOL progMode;
-    BOOL isMinTTY;
     BOOL isTermInfoConsole;
     HANDLE out;
     HANDLE inp;
@@ -261,7 +262,7 @@
 con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
 {
     int actual = 0;
-    CHAR_INFO ci[limit];
+    CHAR_INFO *ci = TypeAlloca(CHAR_INFO, limit);
     COORD loc, siz;
     SMALL_RECT rec;
     int i;
@@ -310,7 +311,7 @@
 static BOOL
 con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
 {
-    CHAR_INFO ci[n];
+    CHAR_INFO *ci = TypeAlloca(CHAR_INFO, n);
     COORD loc, siz;
     SMALL_RECT rec;
     int i;
@@ -487,14 +488,14 @@
 
 	Width = screen_columns(sp);
 	Height = screen_lines(sp);
-	nonempty = min(Height, NewScreen(sp)->_maxy + 1);
+	nonempty = Min(Height, NewScreen(sp)->_maxy + 1);
 
 	T(("... %dx%d clear cur:%d new:%d",
 	   Height, Width,
 	   CurScreen(sp)->_clear,
 	   NewScreen(sp)->_clear));
 
-	if (SP_PARM->_endwin) {
+	if (SP_PARM->_endwin == ewSuspend) {
 
 	    T(("coming back from shell mode"));
 	    NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_ARG);
@@ -503,13 +504,13 @@
 	    NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_ARG);
 	    SP_PARM->_mouse_resume(SP_PARM);
 
-	    SP_PARM->_endwin = FALSE;
+	    SP_PARM->_endwin = ewRunning;
 	}
 
 	if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
 	    int x;
 #if USE_WIDEC_SUPPORT
-	    cchar_t empty[Width];
+	    cchar_t *empty = TypeAlloca(cchar_t, Width);
 	    wchar_t blank[2] =
 	    {
 		L' ', L'\0'
@@ -518,7 +519,7 @@
 	    for (x = 0; x < Width; x++)
 		setcchar(&empty[x], blank, 0, 0, 0);
 #else
-	    chtype empty[Width];
+	    chtype *empty = TypeAlloca(chtype, Width);
 
 	    for (x = 0; x < Width; x++)
 		empty[x] = ' ';
@@ -611,6 +612,12 @@
     returnCode(result);
 }
 
+#ifdef __MING32__
+#define SysISATTY(fd) _isatty(fd)
+#else
+#define SysISATTY(fd) isatty(fd)
+#endif
+
 static bool
 wcon_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
 	       const char *tname,
@@ -642,14 +649,19 @@
 	}
     } else if (tname != 0 && stricmp(tname, "unknown") == 0) {
 	code = TRUE;
+    } else if (SysISATTY(TCB->term.Filedes)) {
+	code = TRUE;
     }
 
     /*
      * This is intentional, to avoid unnecessary breakage of applications
      * using <term.h> symbols.
      */
-    if (code && (TCB->term.type.Booleans == 0)) {
-	_nc_init_termtype(&(TCB->term.type));
+    if (code && (TerminalType(&TCB->term).Booleans == 0)) {
+	_nc_init_termtype(&TerminalType(&TCB->term));
+#if NCURSES_EXT_NUMBERS
+	_nc_export_termtype2(&TCB->term.type, &TerminalType(&TCB->term));
+#endif
     }
 
     if (!code) {
@@ -671,8 +683,8 @@
     int max_cells = (high * wide);
     int i;
 
-    CHAR_INFO this_screen[max_cells];
-    CHAR_INFO that_screen[max_cells];
+    CHAR_INFO *this_screen = TypeAlloca(CHAR_INFO, max_cells);
+    CHAR_INFO *that_screen = TypeAlloca(CHAR_INFO, max_cells);
     COORD this_size;
     SMALL_RECT this_region;
     COORD bufferCoord;
@@ -697,7 +709,9 @@
 			bufferCoord,
 			&this_region)) {
 
-	    memcpy(that_screen, this_screen, sizeof(that_screen));
+	    memcpy(that_screen,
+		   this_screen,
+		   sizeof(CHAR_INFO) * (size_t) max_cells);
 
 	    for (i = 0; i < max_cells; i++) {
 		that_screen[i].Attributes = RevAttr(that_screen[i].Attributes);
@@ -1313,7 +1327,9 @@
 }
 
 static int
-wcon_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
+wcon_testmouse(TERMINAL_CONTROL_BLOCK * TCB,
+	       int delay
+	       EVENTLIST_2nd(_nc_eventlist * evl))
 {
     int rc = 0;
     SCREEN *sp;
@@ -1470,10 +1486,10 @@
 		     FROM_LEFT_4TH_BUTTON_PRESSED | \
 		     RIGHTMOST_BUTTON_PRESSED)
 
-static int
+static mmask_t
 decode_mouse(SCREEN *sp, int mask)
 {
-    int result = 0;
+    mmask_t result = 0;
 
     (void) sp;
     assert(sp && console_initialized);
@@ -1525,6 +1541,10 @@
     int diff;
     bool isImmed = (milliseconds == 0);
 
+#ifdef NCURSES_WGETCH_EVENTS
+    (void) evl;			/* TODO: implement wgetch-events */
+#endif
+
 #define CONSUME() ReadConsoleInput(fd,&inp_rec,1,&nRead)
 
     assert(sp);
@@ -1632,7 +1652,7 @@
 			     CON.inp,
 			     mode,
 			     milliseconds,
-			     timeleft EVENTLIST_2nd(_nc_eventlist * evl));
+			     timeleft EVENTLIST_2nd(evl));
     }
     return code;
 }
@@ -1658,14 +1678,14 @@
 
 	if (sp->_drv_mouse_new_buttons) {
 
-	    work.bstate |= (mmask_t) decode_mouse(sp, sp->_drv_mouse_new_buttons);
+	    work.bstate |= decode_mouse(sp, sp->_drv_mouse_new_buttons);
 
 	} else {
 
 	    /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
-	    work.bstate |= (mmask_t) (decode_mouse(sp,
-						   sp->_drv_mouse_old_buttons)
-				      >> 1);
+	    work.bstate |= (decode_mouse(sp,
+					 sp->_drv_mouse_old_buttons)
+			    >> 1);
 
 	    result = TRUE;
 	}
@@ -1857,7 +1877,7 @@
 #if WINVER >= 0x0600
 /*   This function tests, whether or not the ncurses application
      is running as a descendant of MSYS2/cygwin mintty terminal
-     application. mintty doesn't use Windows Console for it's screen
+     application. mintty doesn't use Windows Console for its screen
      I/O, so the native Windows _isatty doesn't recognize it as
      character device. But we can discover we are at the end of an
      Pipe and can query to server side of the pipe, looking whether
@@ -1947,11 +1967,6 @@
 {
     int result = 0;
 
-#ifdef __MING32__
-#define SysISATTY(fd) _isatty(fd)
-#else
-#define SysISATTY(fd) isatty(fd)
-#endif
     if (SysISATTY(fd)) {
 	result = 1;
     } else {
@@ -1964,7 +1979,7 @@
 
 /*   This is used when running in terminfo mode to discover,
      whether or not the "terminal" is actually a Windows
-     Console. It's the responsibilty of the console to deal
+     Console. It is the responsibility of the console to deal
      with the terminal escape sequences that are sent by
      terminfo.
  */
@@ -2066,7 +2081,8 @@
 _nc_mingw_testmouse(
 		       SCREEN *sp,
 		       HANDLE fd,
-		       int delay)
+		       int delay
+		       EVENTLIST_2nd(_nc_eventlist * evl))
 {
     int rc = 0;
 
@@ -2108,16 +2124,16 @@
 	if (b && nRead > 0) {
 	    if (rc < 0)
 		rc = 0;
-	    rc += nRead;
+	    rc = rc + (int) nRead;
 	    if (inp_rec.EventType == KEY_EVENT) {
 		if (!inp_rec.Event.KeyEvent.bKeyDown)
 		    continue;
 		*buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
 		vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
 		/*
-		 * There are 24 virtual function-keys, and typically
-		 * 12 function-keys on a keyboard.  Use the shift-modifier
-		 * to provide the remaining 12 keys.
+		 * There are 24 virtual function-keys (defined in winuser.h),
+		 * and typically 12 function-keys on a keyboard.  Use the
+		 * shift-modifier to provide the remaining keys.
 		 */
 		if (vk >= VK_F1 && vk <= VK_F12) {
 		    if (inp_rec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) {
@@ -2134,6 +2150,11 @@
 			ungetch('\0');
 			*buf = AnsiKey(vk);
 		    }
+		} else if (vk == VK_BACK) {
+		    if (!(inp_rec.Event.KeyEvent.dwControlKeyState
+			  & (SHIFT_PRESSED | CONTROL_PRESSED))) {
+			*buf = KEY_BACKSPACE;
+		    }
 		}
 		break;
 	    } else if (inp_rec.EventType == MOUSE_EVENT) {
@@ -2152,7 +2173,7 @@
 static bool
 InitConsole(void)
 {
-    /* initalize once, or not at all */
+    /* initialize once, or not at all */
     if (!console_initialized) {
 	int i;
 	DWORD num_buttons;
@@ -2161,9 +2182,6 @@
 	BOOL b;
 
 	START_TRACE();
-	if (_nc_mingw_isatty(0)) {
-	    CON.isMinTTY = TRUE;
-	}
 
 	for (i = 0; i < (N_INI + FKEYS); i++) {
 	    if (i < N_INI) {
@@ -2202,14 +2220,14 @@
 	for (i = 0; i < NUMPAIRS; i++)
 	    CON.pairs[i] = a;
 
-	CON.inp = GetStdHandle(STD_INPUT_HANDLE);
-	CON.out = GetStdHandle(STD_OUTPUT_HANDLE);
-
 	b = AllocConsole();
 
 	if (!b)
 	    b = AttachConsole(ATTACH_PARENT_PROCESS);
 
+	CON.inp = GetDirectHandle("CONIN$", FILE_SHARE_READ);
+	CON.out = GetDirectHandle("CONOUT$", FILE_SHARE_WRITE);
+
 	if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) {
 	    T(("... will not buffer console"));
 	    buffered = FALSE;
@@ -2217,7 +2235,7 @@
 	} else {
 	    T(("... creating console buffer"));
 	    CON.hdl = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
-						0,
+						FILE_SHARE_READ | FILE_SHARE_WRITE,
 						NULL,
 						CONSOLE_TEXTMODE_BUFFER,
 						NULL);