/****************************************************************************
- * 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 *
/****************************************************************************
* Author: Juergen Pfeifer *
+ * and: Thomas E. Dickey *
****************************************************************************/
/*
#include <curses.priv.h>
#define CUR my_term.type.
-MODULE_ID("$Id: win_driver.c,v 1.19 2013/05/25 20:16:46 tom Exp $")
+MODULE_ID("$Id: win_driver.c,v 1.28 2014/03/08 21:44:53 tom Exp $")
#define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
#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),
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 (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;
int i;
cchar_t ch;
SCREEN *sp;
+ Properties *p = PropOf(TCB);
AssertTCB();
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;
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)));
}
}
}
}
+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 int
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;
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,
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;
if (code) {
if ((TCB->term.type.Booleans) == 0) {
- _nc_init_entry(&(TCB->term.type));
+ _nc_init_termtype(&(TCB->term.type));
}
}
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,
{
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);
}
}
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;
T((T_CALLED("win32con::drv_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);
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;
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;
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);
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 {
if (sp) {
if (sp->_keypad_on)
_nc_keypad(sp, TRUE);
- NC_BUFFERED(sp, TRUE);
}
code = OK;
}
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;
+ }
}
}
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)
{
BOOL b = AllocConsole();
WORD a;
int i;
+ bool buffered = TRUE;
if (!b)
b = AttachConsole(ATTACH_PARENT_PROCESS);
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 drv_size */
+ returnVoid;
+ }
+ if (!buffered) {
+ if (!save_original_screen(TCB)) {
+ FreeAndNull(TCB->prop); /* force error in drv_size */
+ returnVoid;
+ }
+ }
}
TCB->info.initcolor = TRUE;
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;
}
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),
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;
{
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;
}
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;
}
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;
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);
* 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;
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);
}