]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/win32con/win_driver.c
ncurses 5.9 - patch 20140426
[ncurses.git] / ncurses / win32con / win_driver.c
index 51e4d0f5d999fcb61b2659157610db6c22e6f7ee..4c6d6dc3fa0ba03d9a8713c2dd1d345262ef2fa4 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2013,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            *
@@ -28,6 +28,7 @@
 
 /****************************************************************************
  *  Author: Juergen Pfeifer                                                 *
+ *     and: Thomas E. Dickey                                                *
  ****************************************************************************/
 
 /*
@@ -38,7 +39,7 @@
 #include <curses.priv.h>
 #define CUR my_term.type.
 
-MODULE_ID("$Id: win_driver.c,v 1.18 2013/03/02 19:48:06 tom Exp $")
+MODULE_ID("$Id: win_driver.c,v 1.33 2014/04/26 19:32:05 juergen Exp $")
 
 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
 
@@ -51,6 +52,8 @@ MODULE_ID("$Id: win_driver.c,v 1.18 2013/03/02 19:48:06 tom Exp $")
 
 #define GenMap(vKey,key) MAKELONG(key, vKey)
 
+#define AdjustY(p) ((p)->buffered ? 0 : (int) (p)->SBI.srWindow.Top)
+
 static const LONG keylist[] =
 {
     GenMap(VK_PRIOR, KEY_PPAGE),
@@ -68,6 +71,7 @@ static const LONG keylist[] =
 #define FKEYS 24
 #define MAPSIZE (FKEYS + N_INI)
 #define NUMPAIRS 64
+#define HANDLE_CAST(f) (HANDLE)(intptr_t)(f)
 
 typedef struct props {
     CONSOLE_SCREEN_BUFFER_INFO SBI;
@@ -76,10 +80,119 @@ typedef struct props {
     DWORD map[MAPSIZE];
     DWORD rmap[MAPSIZE];
     WORD pairs[NUMPAIRS];
+    bool buffered;             /* normally allocate console-buffer */
+    bool window_only;          /* ..if not, we save buffer or window-only */
+    COORD origin;
+    CHAR_INFO *save_screen;
 } Properties;
 
 #define PropOf(TCB) ((Properties*)TCB->prop)
 
+#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
+     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
+     or not this is mintty.
+ */
+static int
+_ismintty(int fd, LPHANDLE pMinTTY)
+{
+    HANDLE handle;
+    DWORD dw;
+
+    handle = HANDLE_CAST(_get_osfhandle(fd));
+    if (handle == INVALID_HANDLE_VALUE)
+       return 0;
+
+    dw = GetFileType(handle);
+    if (dw == FILE_TYPE_PIPE) {
+       if (GetNamedPipeInfo(handle, 0, 0, 0, 0)) {
+           ULONG pPid;
+           /* Requires NT6 */
+           if (GetNamedPipeServerProcessId(handle, &pPid)) {
+               TCHAR buf[MAX_PATH];
+               DWORD len = 0;
+               /* These security attributes may allow us to
+                  create a remote thread in mintty to manipulate
+                  the terminal state remotely */
+               HANDLE pHandle = OpenProcess(PROCESS_CREATE_THREAD
+                                            | PROCESS_QUERY_INFORMATION
+                                            | PROCESS_VM_OPERATION
+                                            | PROCESS_VM_WRITE
+                                            | PROCESS_VM_READ,
+                                            FALSE,
+                                            pPid);
+               if (pMinTTY)
+                   *pMinTTY = INVALID_HANDLE_VALUE;
+               if (pHandle == INVALID_HANDLE_VALUE)
+                   return 0;
+               if (len = GetProcessImageFileName(pHandle,
+                                                 buf,
+                                                 (DWORD) (sizeof(buf) /
+                                                          sizeof(*buf)))) {
+                   TCHAR *pos = _tcsrchr(buf, _T('\\'));
+                   if (pos) {
+                       pos++;
+                       if (_tcsnicmp(pos, _TEXT("mintty.exe"), 10) == 0) {
+                           if (pMinTTY)
+                               *pMinTTY = pHandle;
+                           return 1;
+                       }
+                   }
+               }
+           }
+       }
+    }
+    return 0;
+}
+#endif
+
+/*   Our replacement for the systems _isatty to include also
+     a test for mintty. This is called from the NC_ISATTY macro
+     defined in curses.priv.h
+ */
+int
+_nc_mingw_isatty(int fd)
+{
+    if (_isatty(fd))
+       return 1;
+#if WINVER < 0x0600
+    return 0;
+#else
+    return _ismintty(fd, NULL);
+#endif
+}
+
+/*   Borrowed from ansicon project.
+     Check whether or not a I/O handle is associated with
+     a Windows console.
+*/
+static BOOL
+IsConsoleHandle(HANDLE hdl)
+{
+    DWORD dwFlag = 0;
+    if (!GetConsoleMode(hdl, &dwFlag)) {
+       return (int) WriteConsoleA(hdl, NULL, 0, &dwFlag, NULL);
+    }
+    return (int) (dwFlag & ENABLE_PROCESSED_OUTPUT);
+}
+
+/*   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
+     with the terminal escape sequences that are sent by
+     terminfo.
+ */
+int
+_nc_mingw_isconsole(int fd)
+{
+    HANDLE hdl = HANDLE_CAST(_get_osfhandle(fd));
+    return (int) IsConsoleHandle(hdl);
+}
+
 int
 _nc_mingw_ioctl(int fd GCC_UNUSED,
                long int request GCC_UNUSED,
@@ -119,16 +232,22 @@ MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, attr_t ch)
        if (p > 0 && p < NUMPAIRS && TCB != 0 && sp != 0) {
            WORD a;
            a = PropOf(TCB)->pairs[p];
-           res = (res & 0xff00) | a;
+           res = (WORD) ((res & 0xff00) | a);
        }
     }
 
-    if (ch & A_REVERSE)
-       res = ((res & 0xff00) | (((res & 0x07) << 4) | ((res & 0x70) >> 4)));
+    if (ch & A_REVERSE) {
+       res = (WORD) ((res & 0xff00) |
+                     (((res & 0x07) << 4) |
+                      ((res & 0x70) >> 4)));
+    }
 
-    if (ch & A_STANDOUT)
-       res = ((res & 0xff00) | (((res & 0x07) << 4) | ((res & 0x70) >> 4))
-              | BACKGROUND_INTENSITY);
+    if (ch & A_STANDOUT) {
+       res = (WORD) ((res & 0xff00) |
+                     (((res & 0x07) << 4) |
+                      ((res & 0x70) >> 4)) |
+                     BACKGROUND_INTENSITY);
+    }
 
     if (ch & A_BOLD)
        res |= FOREGROUND_INTENSITY;
@@ -157,6 +276,7 @@ con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
     int i;
     cchar_t ch;
     SCREEN *sp;
+    Properties *p = PropOf(TCB);
 
     AssertTCB();
 
@@ -191,7 +311,7 @@ con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
     siz.Y = 1;
 
     rec.Left = (short) x;
-    rec.Top = (short) y;
+    rec.Top = (SHORT) (y + AdjustY(p));
     rec.Right = (short) (x + limit - 1);
     rec.Bottom = rec.Top;
 
@@ -222,7 +342,7 @@ con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
        if (ChAttrOf(ch) & A_ALTCHARSET) {
            if (sp->_acs_map)
                ci[i].Char.AsciiChar =
-                   ChCharOf(NCURSES_SP_NAME(_nc_acs_char) (sp, ChCharOf(ch)));
+               ChCharOf(NCURSES_SP_NAME(_nc_acs_char) (sp, ChCharOf(ch)));
        }
     }
 
@@ -329,8 +449,51 @@ selectActiveHandle(TERMINAL_CONTROL_BLOCK * TCB)
     }
 }
 
+static bool
+restore_original_screen(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    COORD bufferCoord;
+    SMALL_RECT writeRegion;
+    Properties *p = PropOf(TCB);
+    bool result = FALSE;
+
+    if (p->window_only) {
+       writeRegion.Top = p->SBI.srWindow.Top;
+       writeRegion.Left = p->SBI.srWindow.Left;
+       writeRegion.Bottom = p->SBI.srWindow.Bottom;
+       writeRegion.Right = p->SBI.srWindow.Right;
+       T(("... restoring window"));
+    } else {
+       writeRegion.Top = 0;
+       writeRegion.Left = 0;
+       writeRegion.Bottom = (SHORT) (p->SBI.dwSize.Y - 1);
+       writeRegion.Right = (SHORT) (p->SBI.dwSize.X - 1);
+       T(("... restoring entire buffer"));
+    }
+
+    bufferCoord.X = bufferCoord.Y = 0;
+
+    if (WriteConsoleOutput(TCB->hdl,
+                          p->save_screen,
+                          p->SBI.dwSize,
+                          bufferCoord,
+                          &writeRegion)) {
+       result = TRUE;
+       mvcur(-1, -1, LINES - 2, 0);
+    }
+    T(("... restore original screen contents %s", result ? "ok" : "err"));
+    return result;
+}
+
+static const char *
+wcon_name(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    (void) TCB;
+    return "win32console";
+}
+
 static int
-drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
+wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
 {
     int result = ERR;
     int y, nonempty, n, x0, x1, Width, Height;
@@ -339,7 +502,7 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
     AssertTCB();
     SetSP();
 
-    T((T_CALLED("win32con::drv_doupdate(%p)"), TCB));
+    T((T_CALLED("win32con::wcon_doupdate(%p)"), TCB));
     if (okConsoleHandle(TCB)) {
 
        Width = screen_columns(sp);
@@ -368,7 +531,7 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
                con_write(TCB, y, 0, empty, Width);
                memcpy(empty,
                       CurScreen(sp)->_line[y].text,
-                      Width * sizeof(empty[0]));
+                      (size_t) Width * sizeof(empty[0]));
            }
            CurScreen(sp)->_clear = FALSE;
            NewScreen(sp)->_clear = FALSE;
@@ -409,7 +572,7 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
                if (n > 0) {
                    memcpy(&CurScreen(sp)->_line[y].text[x0],
                           &NewScreen(sp)->_line[y].text[x0],
-                          n * sizeof(CurScreen(sp)->_line[y].text[x0]));
+                          (size_t) n * sizeof(CurScreen(sp)->_line[y].text[x0]));
                    con_write(TCB,
                              y,
                              x0,
@@ -439,9 +602,9 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
            CurScreen(sp)->_curx = NewScreen(sp)->_curx;
            CurScreen(sp)->_cury = NewScreen(sp)->_cury;
 
-           TCB->drv->hwcur(TCB,
-                           0, 0,
-                           CurScreen(sp)->_cury, CurScreen(sp)->_curx);
+           TCB->drv->td_hwcur(TCB,
+                              0, 0,
+                              CurScreen(sp)->_cury, CurScreen(sp)->_curx);
        }
        selectActiveHandle(TCB);
        result = OK;
@@ -450,58 +613,50 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
 }
 
 static bool
-drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
-             const char *tname,
-             int *errret GCC_UNUSED)
+wcon_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
+              const char *tname,
+              int *errret GCC_UNUSED)
 {
     bool code = FALSE;
 
-    T((T_CALLED("win32con::drv_CanHandle(%p)"), TCB));
+    T((T_CALLED("win32con::wcon_CanHandle(%p)"), TCB));
 
-    assert(TCB != 0);
-    assert(tname != 0);
+    assert((TCB != 0) && (tname != 0));
 
     TCB->magic = WINMAGIC;
-    if (*tname == 0 || *tname == 0 || *tname == '#') {
-       code = TRUE;
-    } else {
-       TERMINAL my_term;
-       int status;
 
-       code = FALSE;
-#if (USE_DATABASE || USE_TERMCAP)
-       status = _nc_setup_tinfo(tname, &my_term.type);
-#else
-       status = TGETENT_NO;
-#endif
-       if (status != TGETENT_YES) {
-           const TERMTYPE *fallback = _nc_fallback(tname);
-
-           if (fallback) {
-               my_term.type = *fallback;
-               status = TGETENT_YES;
-           } else if (!strcmp(tname, "unknown")) {
-               code = TRUE;
-           }
-       }
-       if (status == TGETENT_YES) {
-           if (generic_type || hard_copy)
-               code = TRUE;
+    if (tname == 0 || *tname == 0)
+       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)) {
+           code = TRUE;
        }
+    } else if (tname != 0 && stricmp(tname, "unknown") == 0) {
+       code = TRUE;
     }
 
-    if (code) {
-       if ((TCB->term.type.Booleans) == 0) {
-           _nc_init_entry(&(TCB->term.type));
-       }
+    /*
+     * 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));
     }
-
     returnBool(code);
 }
 
 static int
-drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
-               int beepFlag GCC_UNUSED)
+wcon_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
+                int beepFlag GCC_UNUSED)
 {
     SCREEN *sp;
     int res = ERR;
@@ -513,9 +668,9 @@ drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static int
-drv_print(TERMINAL_CONTROL_BLOCK * TCB,
-         char *data GCC_UNUSED,
-         int len GCC_UNUSED)
+wcon_print(TERMINAL_CONTROL_BLOCK * TCB,
+          char *data GCC_UNUSED,
+          int len GCC_UNUSED)
 {
     SCREEN *sp;
 
@@ -526,9 +681,9 @@ drv_print(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static int
-drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
-                 int fg GCC_UNUSED,
-                 int bg GCC_UNUSED)
+wcon_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
+                  int fg GCC_UNUSED,
+                  int bg GCC_UNUSED)
 {
     SCREEN *sp;
     int code = ERR;
@@ -539,24 +694,60 @@ drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
     return (code);
 }
 
+static bool
+get_SBI(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    bool rc = FALSE;
+    Properties *p = PropOf(TCB);
+    if (GetConsoleScreenBufferInfo(TCB->hdl, &(p->SBI))) {
+       T(("GetConsoleScreenBufferInfo"));
+       T(("... buffer(X:%d Y:%d)",
+          p->SBI.dwSize.X,
+          p->SBI.dwSize.Y));
+       T(("... window(X:%d Y:%d)",
+          p->SBI.dwMaximumWindowSize.X,
+          p->SBI.dwMaximumWindowSize.Y));
+       T(("... cursor(X:%d Y:%d)",
+          p->SBI.dwCursorPosition.X,
+          p->SBI.dwCursorPosition.Y));
+       T(("... display(Top:%d Bottom:%d Left:%d Right:%d)",
+          p->SBI.srWindow.Top,
+          p->SBI.srWindow.Bottom,
+          p->SBI.srWindow.Left,
+          p->SBI.srWindow.Right));
+       if (p->buffered) {
+           p->origin.X = 0;
+           p->origin.Y = 0;
+       } else {
+           p->origin.X = p->SBI.srWindow.Left;
+           p->origin.Y = p->SBI.srWindow.Top;
+       }
+       rc = TRUE;
+    } else {
+       T(("GetConsoleScreenBufferInfo ERR"));
+    }
+    return rc;
+}
+
 static void
-drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
-            int fore,
-            int color,
-            int (*outc) (SCREEN *, int) GCC_UNUSED)
+wcon_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
+             int fore,
+             int color,
+             int (*outc) (SCREEN *, int) GCC_UNUSED)
 {
     AssertTCB();
 
-    if (okConsoleHandle(TCB)) {
+    if (okConsoleHandle(TCB) &&
+       PropOf(TCB) != 0) {
        WORD a = MapColor(fore, color);
-       a = ((PropOf(TCB)->SBI.wAttributes) & (fore ? 0xfff8 : 0xff8f)) | a;
+       a |= (WORD) ((PropOf(TCB)->SBI.wAttributes) & (fore ? 0xfff8 : 0xff8f));
        SetConsoleTextAttribute(TCB->hdl, a);
-       GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
+       get_SBI(TCB);
     }
 }
 
 static bool
-drv_rescol(TERMINAL_CONTROL_BLOCK * TCB)
+wcon_rescol(TERMINAL_CONTROL_BLOCK * TCB)
 {
     bool res = FALSE;
 
@@ -564,14 +755,14 @@ drv_rescol(TERMINAL_CONTROL_BLOCK * TCB)
     if (okConsoleHandle(TCB)) {
        WORD a = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
        SetConsoleTextAttribute(TCB->hdl, a);
-       GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
+       get_SBI(TCB);
        res = TRUE;
     }
     return res;
 }
 
 static bool
-drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
+wcon_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
 {
     int result = FALSE;
     SCREEN *sp;
@@ -583,35 +774,43 @@ drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
 }
 
 static int
-drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
+wcon_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
 {
     int result = ERR;
 
     AssertTCB();
 
-    T((T_CALLED("win32con::drv_size(%p)"), TCB));
+    T((T_CALLED("win32con::wcon_size(%p)"), TCB));
 
     if (okConsoleHandle(TCB) &&
+       PropOf(TCB) != 0 &&
        Lines != NULL &&
        Cols != NULL) {
-       *Lines = (int) (PropOf(TCB)->SBI.dwSize.Y);
-       *Cols = (int) (PropOf(TCB)->SBI.dwSize.X);
+       if (PropOf(TCB)->buffered) {
+           *Lines = (int) (PropOf(TCB)->SBI.dwSize.Y);
+           *Cols = (int) (PropOf(TCB)->SBI.dwSize.X);
+       } else {
+           *Lines = (int) (PropOf(TCB)->SBI.srWindow.Bottom + 1 -
+                           PropOf(TCB)->SBI.srWindow.Top);
+           *Cols = (int) (PropOf(TCB)->SBI.srWindow.Right + 1 -
+                          PropOf(TCB)->SBI.srWindow.Left);
+       }
        result = OK;
     }
     returnCode(result);
 }
 
 static int
-drv_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
-           int l GCC_UNUSED,
-           int c GCC_UNUSED)
+wcon_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
+            int l GCC_UNUSED,
+            int c GCC_UNUSED)
 {
     AssertTCB();
     return ERR;
 }
 
 static int
-drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
+wcon_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
 {
     DWORD dwFlag = 0;
     tcflag_t iflag;
@@ -631,17 +830,17 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
        if (lflag & ICANON)
            dwFlag |= ENABLE_LINE_INPUT;
        else
-           dwFlag &= ~ENABLE_LINE_INPUT;
+           dwFlag &= (DWORD) (~ENABLE_LINE_INPUT);
 
        if (lflag & ECHO)
            dwFlag |= ENABLE_ECHO_INPUT;
        else
-           dwFlag &= ~ENABLE_ECHO_INPUT;
+           dwFlag &= (DWORD) (~ENABLE_ECHO_INPUT);
 
        if (iflag & BRKINT)
            dwFlag |= ENABLE_PROCESSED_INPUT;
        else
-           dwFlag &= ~ENABLE_PROCESSED_INPUT;
+           dwFlag &= (DWORD) (~ENABLE_PROCESSED_INPUT);
 
        dwFlag |= ENABLE_MOUSE_INPUT;
 
@@ -657,17 +856,17 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
        if (dwFlag & ENABLE_LINE_INPUT)
            lflag |= ICANON;
        else
-           lflag &= ~ICANON;
+           lflag &= (tcflag_t) (~ICANON);
 
        if (dwFlag & ENABLE_ECHO_INPUT)
            lflag |= ECHO;
        else
-           lflag &= ~ECHO;
+           lflag &= (tcflag_t) (~ECHO);
 
        if (dwFlag & ENABLE_PROCESSED_INPUT)
            iflag |= BRKINT;
        else
-           iflag &= ~BRKINT;
+           iflag &= (tcflag_t) (~BRKINT);
 
        TCB->term.Nttyb.c_iflag = iflag;
        TCB->term.Nttyb.c_lflag = lflag;
@@ -678,7 +877,7 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
 }
 
 static int
-drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
+wcon_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
 {
     SCREEN *sp;
     TERMINAL *_term = (TERMINAL *) TCB;
@@ -687,23 +886,23 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
     AssertTCB();
     sp = TCB->csp;
 
+    T((T_CALLED("win32con::wcon_mode(%p, prog=%d, def=%d)"), TCB, progFlag, defFlag));
     PropOf(TCB)->progMode = progFlag;
     PropOf(TCB)->lastOut = progFlag ? TCB->hdl : TCB->out;
     SetConsoleActiveScreenBuffer(PropOf(TCB)->lastOut);
 
     if (progFlag) /* prog mode */  {
        if (defFlag) {
-           if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
-               _term->Nttyb.c_oflag &= ~OFLAGS_TABS;
+           if ((wcon_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
+               _term->Nttyb.c_oflag &= (tcflag_t) (~OFLAGS_TABS);
                code = OK;
            }
        } else {
            /* reset_prog_mode */
-           if (drv_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
+           if (wcon_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
                if (sp) {
                    if (sp->_keypad_on)
                        _nc_keypad(sp, TRUE);
-                   NC_BUFFERED(sp, TRUE);
                }
                code = OK;
            }
@@ -711,7 +910,7 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
     } else {                   /* shell mode */
        if (defFlag) {
            /* def_shell_mode */
-           if (drv_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
+           if (wcon_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
                code = OK;
            }
        } else {
@@ -719,9 +918,12 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
            if (sp) {
                _nc_keypad(sp, FALSE);
                NCURSES_SP_NAME(_nc_flush) (sp);
-               NC_BUFFERED(sp, FALSE);
            }
-           code = drv_sgmode(TCB, TRUE, &(_term->Ottyb));
+           code = wcon_sgmode(TCB, TRUE, &(_term->Ottyb));
+           if (!PropOf(TCB)->buffered) {
+               if (!restore_original_screen(TCB))
+                   code = ERR;
+           }
        }
     }
 
@@ -729,12 +931,12 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
 }
 
 static void
-drv_screen_init(SCREEN *sp GCC_UNUSED)
+wcon_screen_init(SCREEN *sp GCC_UNUSED)
 {
 }
 
 static void
-drv_wrap(SCREEN *sp GCC_UNUSED)
+wcon_wrap(SCREEN *sp GCC_UNUSED)
 {
 }
 
@@ -782,9 +984,9 @@ MapKey(TERMINAL_CONTROL_BLOCK * TCB, WORD vKey)
 }
 
 static void
-drv_release(TERMINAL_CONTROL_BLOCK * TCB)
+wcon_release(TERMINAL_CONTROL_BLOCK * TCB)
 {
-    T((T_CALLED("win32con::drv_release(%p)"), TCB));
+    T((T_CALLED("win32con::wcon_release(%p)"), TCB));
 
     AssertTCB();
     if (TCB->prop)
@@ -793,12 +995,99 @@ drv_release(TERMINAL_CONTROL_BLOCK * TCB)
     returnVoid;
 }
 
+/*
+ * Attempt to save the screen contents.  PDCurses does this if
+ * PDC_RESTORE_SCREEN is set, giving the same visual appearance on restoration
+ * as if the library had allocated a console buffer.
+ */
+static bool
+save_original_screen(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    bool result = FALSE;
+    Properties *p = PropOf(TCB);
+    COORD bufferSize;
+    COORD bufferCoord;
+    SMALL_RECT readRegion;
+    size_t want;
+
+    bufferSize.X = p->SBI.dwSize.X;
+    bufferSize.Y = p->SBI.dwSize.Y;
+    want = (size_t) (bufferSize.X * bufferSize.Y);
+
+    if ((p->save_screen = malloc(want * sizeof(CHAR_INFO))) != 0) {
+       bufferCoord.X = bufferCoord.Y = 0;
+
+       readRegion.Top = 0;
+       readRegion.Left = 0;
+       readRegion.Bottom = (SHORT) (bufferSize.Y - 1);
+       readRegion.Right = (SHORT) (bufferSize.X - 1);
+
+       T(("... reading console buffer %dx%d into %d,%d - %d,%d at %d,%d",
+          bufferSize.Y, bufferSize.X,
+          readRegion.Top,
+          readRegion.Left,
+          readRegion.Bottom,
+          readRegion.Right,
+          bufferCoord.Y,
+          bufferCoord.X));
+
+       if (ReadConsoleOutput(TCB->hdl,
+                             p->save_screen,
+                             bufferSize,
+                             bufferCoord,
+                             &readRegion)) {
+           result = TRUE;
+       } else {
+           T((" error %#lx", (unsigned long) GetLastError()));
+           FreeAndNull(p->save_screen);
+
+           bufferSize.X = (SHORT) (p->SBI.srWindow.Right
+                                   - p->SBI.srWindow.Left + 1);
+           bufferSize.Y = (SHORT) (p->SBI.srWindow.Bottom
+                                   - p->SBI.srWindow.Top + 1);
+           want = (size_t) (bufferSize.X * bufferSize.Y);
+
+           if ((p->save_screen = malloc(want * sizeof(CHAR_INFO))) != 0) {
+               bufferCoord.X = bufferCoord.Y = 0;
+
+               readRegion.Top = p->SBI.srWindow.Top;
+               readRegion.Left = p->SBI.srWindow.Left;
+               readRegion.Bottom = p->SBI.srWindow.Bottom;
+               readRegion.Right = p->SBI.srWindow.Right;
+
+               T(("... reading console window %dx%d into %d,%d - %d,%d at %d,%d",
+                  bufferSize.Y, bufferSize.X,
+                  readRegion.Top,
+                  readRegion.Left,
+                  readRegion.Bottom,
+                  readRegion.Right,
+                  bufferCoord.Y,
+                  bufferCoord.X));
+
+               if (ReadConsoleOutput(TCB->hdl,
+                                     p->save_screen,
+                                     bufferSize,
+                                     bufferCoord,
+                                     &readRegion)) {
+                   result = TRUE;
+                   p->window_only = TRUE;
+               } else {
+                   T((" error %#lx", (unsigned long) GetLastError()));
+               }
+           }
+       }
+    }
+
+    T(("... save original screen contents %s", result ? "ok" : "err"));
+    return result;
+}
+
 static void
-drv_init(TERMINAL_CONTROL_BLOCK * TCB)
+wcon_init(TERMINAL_CONTROL_BLOCK * TCB)
 {
     DWORD num_buttons;
 
-    T((T_CALLED("win32con::drv_init(%p)"), TCB));
+    T((T_CALLED("win32con::wcon_init(%p)"), TCB));
 
     AssertTCB();
 
@@ -806,6 +1095,7 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
        BOOL b = AllocConsole();
        WORD a;
        int i;
+       bool buffered = TRUE;
 
        if (!b)
            b = AttachConsole(ATTACH_PARENT_PROCESS);
@@ -813,18 +1103,32 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
        TCB->inp = GetStdHandle(STD_INPUT_HANDLE);
        TCB->out = GetStdHandle(STD_OUTPUT_HANDLE);
 
-       if (getenv("NCGDB"))
+       if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) {
            TCB->hdl = TCB->out;
-       else
+           buffered = FALSE;
+       } else {
            TCB->hdl = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
                                                 0,
                                                 NULL,
                                                 CONSOLE_TEXTMODE_BUFFER,
                                                 NULL);
+       }
 
-       if (!InvalidConsoleHandle(TCB->hdl)) {
-           TCB->prop = typeCalloc(Properties, 1);
-           GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
+       if (InvalidConsoleHandle(TCB->hdl)) {
+           returnVoid;
+       } else if ((TCB->prop = typeCalloc(Properties, 1)) != 0) {
+           PropOf(TCB)->buffered = buffered;
+           PropOf(TCB)->window_only = FALSE;
+           if (!get_SBI(TCB)) {
+               FreeAndNull(TCB->prop);         /* force error in wcon_size */
+               returnVoid;
+           }
+           if (!buffered) {
+               if (!save_original_screen(TCB)) {
+                   FreeAndNull(TCB->prop);     /* force error in wcon_size */
+                   returnVoid;
+               }
+           }
        }
 
        TCB->info.initcolor = TRUE;
@@ -842,7 +1146,7 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
 
        if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
            T(("mouse has %ld buttons", num_buttons));
-           TCB->info.numbuttons = num_buttons;
+           TCB->info.numbuttons = (int) num_buttons;
        } else {
            TCB->info.numbuttons = 1;
        }
@@ -851,10 +1155,10 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
 
        for (i = 0; i < (N_INI + FKEYS); i++) {
            if (i < N_INI)
-               PropOf(TCB)->rmap[i] = PropOf(TCB)->map[i] = keylist[i];
+               PropOf(TCB)->rmap[i] = PropOf(TCB)->map[i] = (DWORD) keylist[i];
            else
                PropOf(TCB)->rmap[i] = PropOf(TCB)->map[i] =
-                   GenMap((VK_F1 + (i - N_INI)), (KEY_F(1) + (i - N_INI)));
+                   (DWORD) GenMap((VK_F1 + (i - N_INI)), (KEY_F(1) + (i - N_INI)));
        }
        qsort(PropOf(TCB)->map,
              (size_t) (MAPSIZE),
@@ -873,10 +1177,10 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
 }
 
 static void
-drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
-            int pair,
-            int f,
-            int b)
+wcon_initpair(TERMINAL_CONTROL_BLOCK * TCB,
+             int pair,
+             int f,
+             int b)
 {
     SCREEN *sp;
 
@@ -890,11 +1194,11 @@ drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static void
-drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
-             int color GCC_UNUSED,
-             int r GCC_UNUSED,
-             int g GCC_UNUSED,
-             int b GCC_UNUSED)
+wcon_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
+              int color GCC_UNUSED,
+              int r GCC_UNUSED,
+              int g GCC_UNUSED,
+              int b GCC_UNUSED)
 {
     SCREEN *sp;
 
@@ -903,11 +1207,11 @@ drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static void
-drv_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
+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;
@@ -917,7 +1221,7 @@ drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static void
-drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
+wcon_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
 {
     SCREEN *sp;
 
@@ -928,7 +1232,7 @@ drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
 }
 
 static int
-drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
+wcon_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
 {
     int rc = 0;
     SCREEN *sp;
@@ -939,26 +1243,27 @@ drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
     if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
        rc = TW_MOUSE;
     } else {
-       rc = TCBOf(sp)->drv->twait(TCBOf(sp),
-                                  TWAIT_MASK,
-                                  delay,
-                                  (int *) 0
-                                  EVENTLIST_2nd(evl));
+       rc = TCBOf(sp)->drv->td_twait(TCBOf(sp),
+                                     TWAIT_MASK,
+                                     delay,
+                                     (int *) 0
+                                     EVENTLIST_2nd(evl));
     }
 
     return rc;
 }
 
 static int
-drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
-         int yold GCC_UNUSED, int xold GCC_UNUSED,
-         int y, int x)
+wcon_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
+          int yold GCC_UNUSED, int xold GCC_UNUSED,
+          int y, int x)
 {
     int ret = ERR;
     if (okConsoleHandle(TCB)) {
+       Properties *p = PropOf(TCB);
        COORD loc;
        loc.X = (short) x;
-       loc.Y = (short) y;
+       loc.Y = (short) (y + AdjustY(p));
        SetConsoleCursorPosition(TCB->hdl, loc);
        ret = OK;
     }
@@ -966,9 +1271,9 @@ drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static void
-drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
-           int labnum GCC_UNUSED,
-           char *text GCC_UNUSED)
+wcon_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
+            int labnum GCC_UNUSED,
+            char *text GCC_UNUSED)
 {
     SCREEN *sp;
 
@@ -977,8 +1282,8 @@ drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static void
-drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
-                int OnFlag GCC_UNUSED)
+wcon_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
+                 int OnFlag GCC_UNUSED)
 {
     SCREEN *sp;
 
@@ -987,7 +1292,7 @@ drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
 }
 
 static chtype
-drv_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
+wcon_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
 {
     chtype res = A_NORMAL;
     res |= (A_BOLD | A_DIM | A_REVERSE | A_STANDOUT | A_COLOR);
@@ -995,7 +1300,7 @@ drv_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
 }
 
 static void
-drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
+wcon_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
 {
     SCREEN *sp;
 
@@ -1004,9 +1309,9 @@ drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
 }
 
 static void
-drv_initacs(TERMINAL_CONTROL_BLOCK * TCB,
-           chtype *real_map GCC_UNUSED,
-           chtype *fake_map GCC_UNUSED)
+wcon_initacs(TERMINAL_CONTROL_BLOCK * TCB,
+            chtype *real_map GCC_UNUSED,
+            chtype *fake_map GCC_UNUSED)
 {
 #define DATA(a,b) { a, b }
     static struct {
@@ -1044,7 +1349,7 @@ drv_initacs(TERMINAL_CONTROL_BLOCK * TCB,
     SetSP();
 
     for (n = 0; n < SIZEOF(table); ++n) {
-       real_map[table[n].acs_code] = table[n].use_code | A_ALTCHARSET;
+       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;
     }
@@ -1122,16 +1427,16 @@ decode_mouse(TERMINAL_CONTROL_BLOCK * TCB, int mask)
 }
 
 static int
-drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
-         int mode,
-         int milliseconds,
-         int *timeleft
-         EVENTLIST_2nd(_nc_eventlist * evl))
+wcon_twait(TERMINAL_CONTROL_BLOCK * TCB,
+          int mode,
+          int milliseconds,
+          int *timeleft
+          EVENTLIST_2nd(_nc_eventlist * evl))
 {
     SCREEN *sp;
     INPUT_RECORD inp_rec;
     BOOL b;
-    DWORD nRead = 0, rc = -1;
+    DWORD nRead = 0, rc = (DWORD) (-1);
     int code = 0;
     FILETIME fstart;
     FILETIME fend;
@@ -1153,7 +1458,7 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
 
     while (true) {
        GetSystemTimeAsFileTime(&fstart);
-       rc = WaitForSingleObject(TCB->inp, milliseconds);
+       rc = WaitForSingleObject(TCB->inp, (DWORD) milliseconds);
        GetSystemTimeAsFileTime(&fend);
        diff = (int) tdiff(fstart, fend);
        milliseconds = Adjust(milliseconds, diff);
@@ -1245,23 +1550,26 @@ handle_mouse(TERMINAL_CONTROL_BLOCK * TCB, MOUSE_EVENT_RECORD mer)
      * FIXME: implement continuous event-tracking.
      */
     if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
+       Properties *p = PropOf(TCB);
 
        memset(&work, 0, sizeof(work));
 
        if (sp->_drv_mouse_new_buttons) {
 
-           work.bstate |= decode_mouse(TCB, sp->_drv_mouse_new_buttons);
+           work.bstate |= (mmask_t) decode_mouse(TCB, sp->_drv_mouse_new_buttons);
 
        } else {
 
            /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
-           work.bstate |= (decode_mouse(TCB, sp->_drv_mouse_old_buttons) >> 1);
+           work.bstate |= (mmask_t) (decode_mouse(TCB,
+                                                  sp->_drv_mouse_old_buttons)
+                                     >> 1);
 
            result = TRUE;
        }
 
        work.x = mer.dwMousePosition.X;
-       work.y = mer.dwMousePosition.Y;
+       work.y = mer.dwMousePosition.Y - AdjustY(p);
 
        sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
        sp->_drv_mouse_tail += 1;
@@ -1271,7 +1579,7 @@ handle_mouse(TERMINAL_CONTROL_BLOCK * TCB, MOUSE_EVENT_RECORD mer)
 }
 
 static int
-drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
+wcon_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
 {
     SCREEN *sp;
     int n = 1;
@@ -1286,7 +1594,7 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
 
     memset(&inp_rec, 0, sizeof(inp_rec));
 
-    T((T_CALLED("win32con::drv_read(%p)"), TCB));
+    T((T_CALLED("win32con::wcon_read(%p)"), TCB));
     while ((b = ReadConsoleInput(TCB->inp, &inp_rec, 1, &nRead))) {
        if (b && nRead > 0) {
            if (inp_rec.EventType == KEY_EVENT) {
@@ -1319,15 +1627,15 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
 }
 
 static int
-drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
+wcon_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
 {
-    T((T_CALLED("win32con::drv_nap(%p, %d)"), TCB, ms));
-    Sleep(ms);
+    T((T_CALLED("win32con::wcon_nap(%p, %d)"), TCB, ms));
+    Sleep((DWORD) ms);
     returnCode(OK);
 }
 
 static bool
-drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
+wcon_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
 {
     SCREEN *sp;
     WORD nKey;
@@ -1340,7 +1648,7 @@ drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
 
     AssertTCB();
 
-    T((T_CALLED("win32con::drv_kyExist(%p, %d)"), TCB, keycode));
+    T((T_CALLED("win32con::wcon_kyExist(%p, %d)"), TCB, keycode));
     res = bsearch(&key,
                  PropOf(TCB)->rmap,
                  (size_t) (N_INI + FKEYS),
@@ -1356,7 +1664,7 @@ drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
 }
 
 static int
-drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
+wcon_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
 {
     SCREEN *sp;
     int code = ERR;
@@ -1364,7 +1672,7 @@ drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
     AssertTCB();
     sp = TCB->csp;
 
-    T((T_CALLED("win32con::drv_kpad(%p, %d)"), TCB, flag));
+    T((T_CALLED("win32con::wcon_kpad(%p, %d)"), TCB, flag));
     if (sp) {
        code = OK;
     }
@@ -1372,7 +1680,7 @@ drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
 }
 
 static int
-drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
+wcon_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
 {
     int code = ERR;
     SCREEN *sp;
@@ -1384,7 +1692,7 @@ drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
     AssertTCB();
     SetSP();
 
-    T((T_CALLED("win32con::drv_keyok(%p, %d, %d)"), TCB, keycode, flag));
+    T((T_CALLED("win32con::wcon_keyok(%p, %d, %d)"), TCB, keycode, flag));
     if (sp) {
        res = bsearch(&key,
                      PropOf(TCB)->rmap,
@@ -1405,38 +1713,39 @@ drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
 
 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
     FALSE,
-       drv_CanHandle,          /* CanHandle */
-       drv_init,               /* init */
-       drv_release,            /* release */
-       drv_size,               /* size */
-       drv_sgmode,             /* sgmode */
-       drv_conattr,            /* conattr */
-       drv_mvcur,              /* hwcur */
-       drv_mode,               /* mode */
-       drv_rescol,             /* rescol */
-       drv_rescolors,          /* rescolors */
-       drv_setcolor,           /* color */
-       drv_dobeepflash,        /* DoBeepFlash */
-       drv_initpair,           /* initpair */
-       drv_initcolor,          /* initcolor */
-       drv_do_color,           /* docolor */
-       drv_initmouse,          /* initmouse */
-       drv_testmouse,          /* testmouse */
-       drv_setfilter,          /* setfilter */
-       drv_hwlabel,            /* hwlabel */
-       drv_hwlabelOnOff,       /* hwlabelOnOff */
-       drv_doupdate,           /* update */
-       drv_defaultcolors,      /* defaultcolors */
-       drv_print,              /* print */
-       drv_size,               /* getsize */
-       drv_setsize,            /* setsize */
-       drv_initacs,            /* initacs */
-       drv_screen_init,        /* scinit */
-       drv_wrap,               /* scexit */
-       drv_twait,              /* twait */
-       drv_read,               /* read */
-       drv_nap,                /* nap */
-       drv_kpad,               /* kpad */
-       drv_keyok,              /* kyOk */
-       drv_kyExist             /* kyExist */
+       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 */
 };