X-Git-Url: http://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Fwin32con%2Fwin_driver.c;h=c664d92387cc85a9608b7dd3dcbe37006c923cd3;hp=afc1a16815b7ccb83a4bbb8f4ba3bd0650271ba4;hb=1ced97640ad94ecc6292b917d0f29725c762739c;hpb=cdbe3d3df7ca08989c4aaead5164309466e519eb diff --git a/ncurses/win32con/win_driver.c b/ncurses/win32con/win_driver.c index afc1a168..c664d923 100644 --- a/ncurses/win32con/win_driver.c +++ b/ncurses/win32con/win_driver.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2012 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 * @@ -33,20 +33,27 @@ /* * TODO - GetMousePos(POINT * result) from ntconio.c * TODO - implement nodelay + * TODO - when $NCGDB is set, implement non-buffered output, like PDCurses */ #include #define CUR my_term.type. -MODULE_ID("$Id: win_driver.c,v 1.13 2012/09/03 16:20:24 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; (void) sp +#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), @@ -68,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) @@ -143,50 +154,52 @@ MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, attr_t ch) * TODO: _nc_wacs should be part of sp. */ static BOOL -con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int n) +con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit) { - CHAR_INFO ci[n]; + 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(); - if (TCB == 0 || InvalidConsoleHandle(TCB->hdl)) - return FALSE; - SetSP(); - for (i = 0; i < n; i++) { + for (i = actual = 0; i < limit; i++) { ch = str[i]; - ci[i].Char.UnicodeChar = CharOf(ch); - ci[i].Attributes = MapAttr(TCB, - PropOf(TCB)->SBI.wAttributes, - AttrOf(ch)); + 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[i].Char.UnicodeChar = CharOf(_nc_wacs[which]); + ci[actual].Char.UnicodeChar = CharOf(_nc_wacs[which]); } else { - ci[i].Char.UnicodeChar = ' '; + ci[actual].Char.UnicodeChar = ' '; } } } + ++actual; } loc.X = (short) 0; loc.Y = (short) 0; - siz.X = (short) n; + siz.X = (short) actual; siz.Y = 1; rec.Left = (short) x; - rec.Top = (short) y; - rec.Right = (short) (x + n - 1); + rec.Top = (SHORT) (y + AdjustY(p)); + rec.Right = (short) (x + limit - 1); rec.Bottom = rec.Top; return WriteConsoleOutputW(TCB->hdl, ci, siz, loc, &rec); @@ -205,9 +218,6 @@ con_write8(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++) { @@ -219,7 +229,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))); } } @@ -238,65 +248,160 @@ con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n) #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)) { + + Width = screen_columns(sp); + Height = screen_lines(sp); + nonempty = min(Height, NewScreen(sp)->_maxy + 1); - if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) { - int 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 (x = 0; x < Width; x++) - setcchar(&empty[x], blank, 0, 0, 0); + cchar_t empty[Width]; + wchar_t blank[2] = + { + L' ', L'\0' + }; + + for (x = 0; x < Width; x++) + setcchar(&empty[x], blank, 0, 0, 0); #else - chtype empty[Width]; + chtype empty[Width]; - for (x = 0; x < Width; x++) - empty[x] = ' '; + 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, - Width * sizeof(empty[0])); + 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(CurScreen(sp)->_line[y].text[x0])); - con_write(TCB, - y, - x0, - &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) { @@ -305,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 @@ -340,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; @@ -370,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)); } } @@ -417,6 +546,41 @@ 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, @@ -425,11 +589,12 @@ drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB, { 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); } } @@ -439,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; @@ -463,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 @@ -503,17 +682,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; @@ -529,17 +708,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; @@ -560,12 +739,13 @@ drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int 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 { @@ -664,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) { @@ -677,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); @@ -684,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; @@ -713,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; } @@ -722,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))); @@ -826,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; } @@ -915,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; } @@ -1002,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; @@ -1024,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); @@ -1070,8 +1351,7 @@ drv_twait(TERMINAL_CONTROL_BLOCK * TCB, } continue; default: - SetConsoleActiveScreenBuffer(!PropOf(TCB)->progMode ? - TCB->hdl : TCB->out); + selectActiveHandle(TCB); continue; } } @@ -1117,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; @@ -1193,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 @@ -1211,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), @@ -1222,7 +1507,7 @@ drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode) if (!(nKey & 0x8000)) found = TRUE; } - return found; + returnCode(found); } static int @@ -1234,10 +1519,11 @@ drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int 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 @@ -1253,6 +1539,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)); if (sp) { res = bsearch(&key, PropOf(TCB)->rmap, @@ -1268,7 +1555,7 @@ drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag) *(LONG *) res = GenMap(vKey, nKey); } } - return code; + returnCode(code); } NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {