aboutsummaryrefslogtreecommitdiff
path: root/ncurses/win32con
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2014-03-01 00:40:26 +0000
committerXin LI <delphij@FreeBSD.org>2014-03-01 00:40:26 +0000
commitcea297eb34d2361e79529034397465068ae34ecd (patch)
treefbc3775582ebd1e6f026931751cfab6c588b643c /ncurses/win32con
parent6826a395a618014c4541ff6a654be0d3afb392a1 (diff)
downloadsrc-cea297eb34d2361e79529034397465068ae34ecd.tar.gz
src-cea297eb34d2361e79529034397465068ae34ecd.zip
Vendor import of ncurses 5.9 20140222 snapshot.vendor/ncurses/5.9-20140222
Notes
Notes: svn path=/vendor/ncurses/dist/; revision=262639 svn path=/vendor/ncurses/5.9-20140222/; revision=262640; tag=vendor/ncurses/5.9-20140222
Diffstat (limited to 'ncurses/win32con')
-rw-r--r--ncurses/win32con/win_driver.c590
1 files changed, 473 insertions, 117 deletions
diff --git a/ncurses/win32con/win_driver.c b/ncurses/win32con/win_driver.c
index c214639cd4df..c664d92387cc 100644
--- a/ncurses/win32con/win_driver.c
+++ b/ncurses/win32con/win_driver.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * Copyright (c) 1998-2009,2010 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,26 +28,32 @@
/****************************************************************************
* Author: Juergen Pfeifer *
- * *
****************************************************************************/
/*
* 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.10 2010/12/25 19:28:21 tom Exp $")
+MODULE_ID("$Id: win_driver.c,v 1.24 2014/02/23 01:23:29 tom Exp $")
#define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
-#define AssertTCB() assert(TCB!=0 && TCB->magic==WINMAGIC)
-#define SetSP() assert(TCB->csp!=0); sp = TCB->csp
+#define EXP_OPTIMIZE 0
+
+#define okConsoleHandle(TCB) (TCB != 0 && !InvalidConsoleHandle(TCB->hdl))
+
+#define AssertTCB() assert(TCB != 0 && (TCB->magic == WINMAGIC))
+#define SetSP() assert(TCB->csp != 0); sp = TCB->csp; (void) sp
#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),
@@ -69,9 +75,13 @@ static const LONG keylist[] =
typedef struct props {
CONSOLE_SCREEN_BUFFER_INFO SBI;
bool progMode;
+ TERM_HANDLE lastOut;
DWORD map[MAPSIZE];
DWORD rmap[MAPSIZE];
WORD pairs[NUMPAIRS];
+ bool buffered;
+ COORD origin;
+ CHAR_INFO *save_screen;
} Properties;
#define PropOf(TCB) ((Properties*)TCB->prop)
@@ -103,7 +113,7 @@ MapColor(bool fore, int color)
}
static WORD
-MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, chtype ch)
+MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, attr_t ch)
{
if (ch & A_COLOR) {
int p;
@@ -135,8 +145,69 @@ MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, chtype ch)
return res;
}
+#if USE_WIDEC_SUPPORT
+/*
+ * TODO: support surrogate pairs
+ * TODO: support combining characters
+ * TODO: support acsc
+ * TODO: check wcwidth of base character, fill if needed for double-width
+ * 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[limit];
+ COORD loc, siz;
+ SMALL_RECT rec;
+ int i;
+ cchar_t ch;
+ SCREEN *sp;
+ Properties *p = PropOf(TCB);
+
+ 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(TCB,
+ PropOf(TCB)->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(p));
+ rec.Right = (short) (x + limit - 1);
+ rec.Bottom = rec.Top;
+
+ return WriteConsoleOutputW(TCB->hdl, ci, siz, loc, &rec);
+}
+#define con_write(tcb, y, x, str, n) con_write16(tcb, y, x, str, n)
+#else
static BOOL
-con_write(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
+con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
{
CHAR_INFO ci[n];
COORD loc, siz;
@@ -147,9 +218,6 @@ con_write(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
AssertTCB();
- if (TCB == 0 || InvalidConsoleHandle(TCB->hdl))
- return FALSE;
-
SetSP();
for (i = 0; i < n; i++) {
@@ -161,7 +229,7 @@ con_write(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)));
}
}
@@ -177,55 +245,163 @@ con_write(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
return WriteConsoleOutput(TCB->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 void
+selectActiveHandle(TERMINAL_CONTROL_BLOCK * TCB)
+{
+ if (PropOf(TCB)->lastOut != TCB->hdl) {
+ PropOf(TCB)->lastOut = TCB->hdl;
+ SetConsoleActiveScreenBuffer(PropOf(TCB)->lastOut);
+ }
+}
+
static int
drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
{
+ int result = ERR;
int y, nonempty, n, x0, x1, Width, Height;
SCREEN *sp;
AssertTCB();
SetSP();
- Width = screen_columns(sp);
- Height = screen_lines(sp);
- nonempty = min(Height, NewScreen(sp)->_maxy + 1);
+ T((T_CALLED("win32con::drv_doupdate(%p)"), TCB));
+ if (okConsoleHandle(TCB)) {
- if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
- int x;
- chtype empty[Width];
+ Width = screen_columns(sp);
+ Height = screen_lines(sp);
+ nonempty = min(Height, NewScreen(sp)->_maxy + 1);
- for (x = 0; x < Width; x++)
- empty[x] = ' ';
+ if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
+ int x;
+#if USE_WIDEC_SUPPORT
+ cchar_t empty[Width];
+ wchar_t blank[2] =
+ {
+ L' ', L'\0'
+ };
- for (y = 0; y < nonempty; y++) {
- con_write(TCB, y, 0, empty, Width);
- memcpy(empty,
- CurScreen(sp)->_line[y].text,
- Width * sizeof(chtype));
+ for (x = 0; x < Width; x++)
+ setcchar(&empty[x], blank, 0, 0, 0);
+#else
+ chtype empty[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));
}
- CurScreen(sp)->_clear = FALSE;
- NewScreen(sp)->_clear = FALSE;
- touchwin(NewScreen(sp));
- }
- for (y = 0; y < nonempty; y++) {
- x0 = NewScreen(sp)->_line[y].firstchar;
- if (x0 != _NOCHANGE) {
- 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,
- n * sizeof(chtype));
- con_write(TCB,
- y,
- x0,
- ((chtype *) CurScreen(sp)->_line[y].text) + x0, n);
+ 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) {
@@ -234,26 +410,50 @@ drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
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);
- }
+ /* 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;
+ if (!NewScreen(sp)->_leaveok) {
+ 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->hwcur(TCB,
+ 0, 0,
+ CurScreen(sp)->_cury, CurScreen(sp)->_curx);
+ }
+ selectActiveHandle(TCB);
+ result = OK;
}
- SetConsoleActiveScreenBuffer(TCB->hdl);
- return OK;
+ returnCode(result);
}
static bool
@@ -269,14 +469,14 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
assert(tname != 0);
TCB->magic = WINMAGIC;
- if (*tname == 0 || *tname == 0) {
+ if (*tname == 0 || *tname == 0 || *tname == '#') {
code = TRUE;
} else {
TERMINAL my_term;
int status;
code = FALSE;
-#if (USE_DATABASE || USE_TERMCAP)
+#if (NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP)
status = _nc_setup_tinfo(tname, &my_term.type);
#else
status = TGETENT_NO;
@@ -299,7 +499,7 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
if (code) {
if ((TCB->term.type.Booleans) == 0) {
- _nc_init_entry(&(TCB->term.type));
+ _nc_init_termtype(&(TCB->term.type));
}
}
@@ -308,7 +508,7 @@ drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
static int
drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
- bool beepFlag GCC_UNUSED)
+ int beepFlag GCC_UNUSED)
{
SCREEN *sp;
int res = ERR;
@@ -346,19 +546,55 @@ 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,
- bool fore,
+ int fore,
int color,
int (*outc) (SCREEN *, int) GCC_UNUSED)
{
AssertTCB();
- if (TCB && !InvalidConsoleHandle(TCB->hdl)) {
+ 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);
}
}
@@ -368,10 +604,10 @@ drv_rescol(TERMINAL_CONTROL_BLOCK * TCB)
bool res = FALSE;
AssertTCB();
- if (TCB && !InvalidConsoleHandle(TCB->hdl)) {
+ 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;
@@ -392,14 +628,28 @@ drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
static int
drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
{
+ int result = ERR;
+
AssertTCB();
- if (TCB == NULL || Lines == NULL || Cols == NULL || InvalidConsoleHandle(TCB->hdl))
- return ERR;
+ T((T_CALLED("win32con::drv_size(%p)"), TCB));
- *Lines = (int) (PropOf(TCB)->SBI.dwSize.Y);
- *Cols = (int) (PropOf(TCB)->SBI.dwSize.X);
- return OK;
+ if (okConsoleHandle(TCB) &&
+ PropOf(TCB) != 0 &&
+ Lines != NULL &&
+ Cols != NULL) {
+ 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
@@ -412,7 +662,7 @@ drv_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
}
static int
-drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf)
+drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
{
DWORD dwFlag = 0;
tcflag_t iflag;
@@ -432,17 +682,17 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool 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;
@@ -458,17 +708,17 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool 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;
@@ -479,7 +729,7 @@ drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf)
}
static int
-drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag)
+drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
{
SCREEN *sp;
TERMINAL *_term = (TERMINAL *) TCB;
@@ -489,12 +739,13 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag)
sp = TCB->csp;
PropOf(TCB)->progMode = progFlag;
- SetConsoleActiveScreenBuffer(progFlag ? TCB->hdl : TCB->out);
+ 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;
+ _term->Nttyb.c_oflag &= (tcflag_t) (~OFLAGS_TABS);
code = OK;
}
} else {
@@ -593,6 +844,92 @@ 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;
+ } 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)
{
@@ -606,6 +943,7 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
BOOL b = AllocConsole();
WORD a;
int i;
+ bool buffered = TRUE;
if (!b)
b = AttachConsole(ATTACH_PARENT_PROCESS);
@@ -613,18 +951,31 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
TCB->inp = GetStdHandle(STD_INPUT_HANDLE);
TCB->out = GetStdHandle(STD_OUTPUT_HANDLE);
- if (getenv("NCGDB"))
+ if (getenv("NCGDB")) {
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;
+ if (!get_SBI(TCB)) {
+ FreeAndNull(TCB->prop); /* force error in drv_size */
+ returnVoid;
+ }
+ if (!buffered) {
+ if (!save_original_screen(TCB)) {
+ FreeAndNull(TCB->prop); /* force error in drv_size */
+ returnVoid;
+ }
+ }
}
TCB->info.initcolor = TRUE;
@@ -642,7 +993,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;
}
@@ -651,7 +1002,7 @@ 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)));
@@ -674,9 +1025,9 @@ drv_init(TERMINAL_CONTROL_BLOCK * TCB)
static void
drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
- short pair,
- short f,
- short b)
+ int pair,
+ int f,
+ int b)
{
SCREEN *sp;
@@ -691,10 +1042,10 @@ drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
static void
drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
- short color GCC_UNUSED,
- short r GCC_UNUSED,
- short g GCC_UNUSED,
- short b GCC_UNUSED)
+ int color GCC_UNUSED,
+ int r GCC_UNUSED,
+ int g GCC_UNUSED,
+ int b GCC_UNUSED)
{
SCREEN *sp;
@@ -704,9 +1055,9 @@ drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
static void
drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,
- short old_pair GCC_UNUSED,
- short pair GCC_UNUSED,
- bool reverse GCC_UNUSED,
+ int old_pair GCC_UNUSED,
+ int pair GCC_UNUSED,
+ int reverse GCC_UNUSED,
int (*outc) (SCREEN *, int) GCC_UNUSED
)
{
@@ -755,10 +1106,11 @@ drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
int y, int x)
{
int ret = ERR;
- if (TCB && !InvalidConsoleHandle(TCB->hdl)) {
+ 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;
}
@@ -778,7 +1130,7 @@ drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
static void
drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
- bool OnFlag GCC_UNUSED)
+ int OnFlag GCC_UNUSED)
{
SCREEN *sp;
@@ -844,7 +1196,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;
}
@@ -931,7 +1283,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;
@@ -953,7 +1305,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);
@@ -999,8 +1351,7 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
}
continue;
default:
- SetConsoleActiveScreenBuffer(!PropOf(TCB)->progMode ?
- TCB->hdl : TCB->out);
+ selectActiveHandle(TCB);
continue;
}
}
@@ -1046,23 +1397,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;
@@ -1080,7 +1434,6 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
BOOL b;
DWORD nRead;
WORD vk;
- WORD sc;
AssertTCB();
assert(buf);
@@ -1096,7 +1449,6 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
continue;
*buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
- sc = inp_rec.Event.KeyEvent.wVirtualScanCode;
if (*buf == 0) {
if (sp->_keypad_on) {
*buf = MapKey(TCB, vk);
@@ -1124,8 +1476,9 @@ drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
static int
drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
{
- Sleep(ms);
- return OK;
+ T((T_CALLED("win32con::drv_nap(%p, %d)"), TCB, ms));
+ Sleep((DWORD) ms);
+ returnCode(OK);
}
static bool
@@ -1142,6 +1495,7 @@ drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
AssertTCB();
+ T((T_CALLED("win32con::drv_kyExist(%p, %d)"), TCB, keycode));
res = bsearch(&key,
PropOf(TCB)->rmap,
(size_t) (N_INI + FKEYS),
@@ -1153,11 +1507,11 @@ drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
if (!(nKey & 0x8000))
found = TRUE;
}
- return found;
+ returnCode(found);
}
static int
-drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, bool flag GCC_UNUSED)
+drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
{
SCREEN *sp;
int code = ERR;
@@ -1165,14 +1519,15 @@ drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, bool flag GCC_UNUSED)
AssertTCB();
sp = TCB->csp;
+ T((T_CALLED("win32con::drv_kpad(%p, %d)"), TCB, flag));
if (sp) {
code = OK;
}
- return code;
+ returnCode(code);
}
static int
-drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, bool flag)
+drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
{
int code = ERR;
SCREEN *sp;
@@ -1184,6 +1539,7 @@ drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, bool flag)
AssertTCB();
SetSP();
+ T((T_CALLED("win32con::drv_keyok(%p, %d, %d)"), TCB, keycode, flag));
if (sp) {
res = bsearch(&key,
PropOf(TCB)->rmap,
@@ -1199,7 +1555,7 @@ drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, bool flag)
*(LONG *) res = GenMap(vKey, nKey);
}
}
- return code;
+ returnCode(code);
}
NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {