]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - ncurses/win32con/win_driver.c
ncurses 5.9 - patch 20140412
[ncurses.git] / ncurses / win32con / win_driver.c
index 6437796f09f0b948b9b7d8c16a3d3894eaa4a395..f819fd8c9433bb4b17bb26e42b9d695cfa31fb73 100644 (file)
 
 /****************************************************************************
  *  Author: Juergen Pfeifer                                                 *
+ *     and: Thomas E. Dickey                                                *
  ****************************************************************************/
 
 /*
  * TODO - GetMousePos(POINT * result) from ntconio.c
  * TODO - implement nodelay
- * TODO - when $NCGDB is set, implement non-buffered output, like PDCurses
  */
 
 #include <curses.priv.h>
 #define CUR my_term.type.
 
-MODULE_ID("$Id: win_driver.c,v 1.23 2014/02/15 23:21:44 tom Exp $")
+MODULE_ID("$Id: win_driver.c,v 1.31 2014/04/13 00:16:07 tom Exp $")
 
 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
 
@@ -52,7 +52,7 @@ MODULE_ID("$Id: win_driver.c,v 1.23 2014/02/15 23:21:44 tom Exp $")
 
 #define GenMap(vKey,key) MAKELONG(key, vKey)
 
-#define AdjustY(p) ((p)->buffered ? 0 : (p)->SBI.srWindow.Top)
+#define AdjustY(p) ((p)->buffered ? 0 : (int) (p)->SBI.srWindow.Top)
 
 static const LONG keylist[] =
 {
@@ -79,7 +79,8 @@ typedef struct props {
     DWORD map[MAPSIZE];
     DWORD rmap[MAPSIZE];
     WORD pairs[NUMPAIRS];
-    bool buffered;
+    bool buffered;             /* normally allocate console-buffer */
+    bool window_only;          /* ..if not, we save buffer or window-only */
     COORD origin;
     CHAR_INFO *save_screen;
 } Properties;
@@ -125,16 +126,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;
@@ -198,7 +205,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 + AdjustY(p);
+    rec.Top = (SHORT) (y + AdjustY(p));
     rec.Right = (short) (x + limit - 1);
     rec.Bottom = rec.Top;
 
@@ -336,6 +343,49 @@ 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 *
+drv_name(TERMINAL_CONTROL_BLOCK * TCB)
+{
+    (void) TCB;
+    return "win32console";
+}
+
 static int
 drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
 {
@@ -375,7 +425,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;
@@ -416,7 +466,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,
@@ -446,9 +496,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;
@@ -465,44 +515,36 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
 
     T((T_CALLED("win32con::drv_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 (NCURSES_USE_DATABASE || NCURSES_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_termtype(&(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);
 }
 
@@ -592,7 +634,7 @@ drv_setcolor(TERMINAL_CONTROL_BLOCK * 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);
        get_SBI(TCB);
     }
@@ -682,17 +724,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;
 
@@ -708,17 +750,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;
@@ -738,6 +780,7 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
     AssertTCB();
     sp = TCB->csp;
 
+    T((T_CALLED("win32con::drv_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);
@@ -745,7 +788,7 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
     if (progFlag) /* prog mode */  {
        if (defFlag) {
            if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
-               _term->Nttyb.c_oflag &= ~OFLAGS_TABS;
+               _term->Nttyb.c_oflag &= (tcflag_t) (~OFLAGS_TABS);
                code = OK;
            }
        } else {
@@ -754,7 +797,6 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
                if (sp) {
                    if (sp->_keypad_on)
                        _nc_keypad(sp, TRUE);
-                   NC_BUFFERED(sp, TRUE);
                }
                code = OK;
            }
@@ -770,9 +812,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));
+           if (!PropOf(TCB)->buffered) {
+               if (!restore_original_screen(TCB))
+                   code = ERR;
+           }
        }
     }
 
@@ -861,15 +906,15 @@ save_original_screen(TERMINAL_CONTROL_BLOCK * TCB)
 
     bufferSize.X = p->SBI.dwSize.X;
     bufferSize.Y = p->SBI.dwSize.Y;
-    want = bufferSize.X * bufferSize.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 = bufferSize.Y - 1;
-       readRegion.Right = bufferSize.X - 1;
+       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,
@@ -890,9 +935,11 @@ save_original_screen(TERMINAL_CONTROL_BLOCK * TCB)
            T((" error %#lx", (unsigned long) GetLastError()));
            FreeAndNull(p->save_screen);
 
-           bufferSize.X = p->SBI.srWindow.Right - p->SBI.srWindow.Left + 1;
-           bufferSize.Y = p->SBI.srWindow.Bottom - p->SBI.srWindow.Top + 1;
-           want = bufferSize.X * bufferSize.Y;
+           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;
@@ -917,6 +964,7 @@ save_original_screen(TERMINAL_CONTROL_BLOCK * TCB)
                                      bufferCoord,
                                      &readRegion)) {
                    result = TRUE;
+                   p->window_only = TRUE;
                } else {
                    T((" error %#lx", (unsigned long) GetLastError()));
                }
@@ -949,7 +997,7 @@ 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;
            buffered = FALSE;
        } else {
@@ -964,6 +1012,7 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
            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 drv_size */
                returnVoid;
@@ -991,7 +1040,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;
        }
@@ -1000,10 +1049,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),
@@ -1088,11 +1137,11 @@ 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;
@@ -1108,7 +1157,7 @@ drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
        Properties *p = PropOf(TCB);
        COORD loc;
        loc.X = (short) x;
-       loc.Y = (short) y + AdjustY(p);
+       loc.Y = (short) (y + AdjustY(p));
        SetConsoleCursorPosition(TCB->hdl, loc);
        ret = OK;
     }
@@ -1194,7 +1243,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;
     }
@@ -1281,7 +1330,7 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
     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;
@@ -1303,7 +1352,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);
@@ -1401,12 +1450,14 @@ handle_mouse(TERMINAL_CONTROL_BLOCK * TCB, MOUSE_EVENT_RECORD mer)
 
        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;
        }
@@ -1473,7 +1524,7 @@ static int
 drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
 {
     T((T_CALLED("win32con::drv_nap(%p, %d)"), TCB, ms));
-    Sleep(ms);
+    Sleep((DWORD) ms);
     returnCode(OK);
 }
 
@@ -1556,6 +1607,7 @@ drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
 
 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
     FALSE,
+       drv_name,               /* Name */
        drv_CanHandle,          /* CanHandle */
        drv_init,               /* init */
        drv_release,            /* release */