1 /****************************************************************************
2 * Copyright (c) 1998-2013,2014 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Juergen Pfeifer *
31 * and: Thomas E. Dickey *
32 ****************************************************************************/
35 * TODO - GetMousePos(POINT * result) from ntconio.c
36 * TODO - implement nodelay
37 * TODO - improve screen-repainting performance, using implied wraparound to reduce write's
38 * TODO - make it optional whether screen is restored or not when non-buffered
41 #include <curses.priv.h>
52 #define PSAPI_VERSION 2
55 #define CUR my_term.type.
57 MODULE_ID("$Id: win_driver.c,v 1.52 2014/10/25 00:24:24 tom Exp $")
60 # error We need GCC to compile for MinGW
63 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
65 #define EXP_OPTIMIZE 0
67 #define array_length(a) (sizeof(a)/sizeof(a[0]))
69 #define okConsoleHandle(TCB) (TCB != 0 && CON.hdl != INVALID_HANDLE_VALUE)
71 #define AssertTCB() assert(TCB != 0 && (TCB->magic == WINMAGIC))
72 #define SetSP() assert(TCB->csp != 0); sp = TCB->csp; (void) sp
74 #define GenMap(vKey,key) MAKELONG(key, vKey)
76 #define AdjustY() (CON.buffered ? 0 : (int) CON.SBI.srWindow.Top)
79 #define write_screen WriteConsoleOutputW
80 #define read_screen ReadConsoleOutputW
82 #define write_screen WriteConsoleOutput
83 #define read_screen ReadConsoleOutput
86 static const LONG keylist[] =
88 GenMap(VK_PRIOR, KEY_PPAGE),
89 GenMap(VK_NEXT, KEY_NPAGE),
90 GenMap(VK_END, KEY_END),
91 GenMap(VK_HOME, KEY_HOME),
92 GenMap(VK_LEFT, KEY_LEFT),
93 GenMap(VK_UP, KEY_UP),
94 GenMap(VK_RIGHT, KEY_RIGHT),
95 GenMap(VK_DOWN, KEY_DOWN),
96 GenMap(VK_DELETE, KEY_DC),
97 GenMap(VK_INSERT, KEY_IC)
99 #define N_INI ((int)array_length(keylist))
101 #define MAPSIZE (FKEYS + N_INI)
104 /* A process can only have a single console, so it's save
105 to maintain all the information about it in a single
114 BOOL isTermInfoConsole;
122 WORD pairs[NUMPAIRS];
124 CHAR_INFO *save_screen;
126 SMALL_RECT save_region;
127 CONSOLE_SCREEN_BUFFER_INFO SBI;
128 CONSOLE_SCREEN_BUFFER_INFO save_SBI;
129 CONSOLE_CURSOR_INFO save_CI;
132 static BOOL console_initialized = FALSE;
135 MapColor(bool fore, int color)
137 static const int _cmap[] =
138 {0, 4, 2, 6, 1, 5, 3, 7};
140 if (color < 0 || color > 7)
149 #define RevAttr(attr) \
150 (WORD) (((attr) & 0xff00) | \
151 ((((attr) & 0x07) << 4) | \
152 (((attr) & 0x70) >> 4)))
155 MapAttr(WORD res, attr_t ch)
161 if (p > 0 && p < NUMPAIRS) {
164 res = (WORD) ((res & 0xff00) | a);
168 if (ch & A_REVERSE) {
172 if (ch & A_STANDOUT) {
173 res = RevAttr(res) | BACKGROUND_INTENSITY;
177 res |= FOREGROUND_INTENSITY;
180 res |= BACKGROUND_INTENSITY;
185 #if 0 /* def TRACE */
187 dump_screen(const char *fn, int ln)
189 int max_cells = (CON.SBI.dwSize.Y * (1 + CON.SBI.dwSize.X)) + 1;
190 char output[max_cells];
191 CHAR_INFO save_screen[max_cells];
193 SMALL_RECT save_region;
196 T(("dump_screen %s@%d", fn, ln));
198 save_region.Top = CON.SBI.srWindow.Top;
199 save_region.Left = CON.SBI.srWindow.Left;
200 save_region.Bottom = CON.SBI.srWindow.Bottom;
201 save_region.Right = CON.SBI.srWindow.Right;
203 save_size.X = (SHORT) (save_region.Right - save_region.Left + 1);
204 save_size.Y = (SHORT) (save_region.Bottom - save_region.Top + 1);
206 bufferCoord.X = bufferCoord.Y = 0;
208 if (read_screen(CON.hdl,
217 for (i = save_region.Top; i <= save_region.Bottom; ++i) {
218 for (j = save_region.Left; j <= save_region.Right; ++j) {
219 output[k++] = save_screen[ij++].Char.AsciiChar;
225 T(("DUMP: %d,%d - %d,%d",
235 #define dump_screen(fn,ln) /* nothing */
238 #if USE_WIDEC_SUPPORT
240 * TODO: support surrogate pairs
241 * TODO: support combining characters
243 * TODO: _nc_wacs should be part of sp.
246 con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
259 for (i = actual = 0; i < limit; i++) {
263 ci[actual].Char.UnicodeChar = CharOf(ch);
264 ci[actual].Attributes = MapAttr(CON.SBI.wAttributes,
266 if (AttrOf(ch) & A_ALTCHARSET) {
268 int which = CharOf(ch);
271 && CharOf(_nc_wacs[which]) != 0) {
272 ci[actual].Char.UnicodeChar = CharOf(_nc_wacs[which]);
274 ci[actual].Char.UnicodeChar = ' ';
283 siz.X = (SHORT) actual;
286 rec.Left = (SHORT) x;
287 rec.Top = (SHORT) (y + AdjustY());
288 rec.Right = (SHORT) (x + limit - 1);
289 rec.Bottom = rec.Top;
291 return write_screen(CON.hdl, ci, siz, loc, &rec);
293 #define con_write(tcb, y, x, str, n) con_write16(tcb, y, x, str, n)
296 con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
308 for (i = 0; i < n; i++) {
310 ci[i].Char.AsciiChar = ChCharOf(ch);
311 ci[i].Attributes = MapAttr(CON.SBI.wAttributes,
313 if (ChAttrOf(ch) & A_ALTCHARSET) {
315 ci[i].Char.AsciiChar =
316 ChCharOf(NCURSES_SP_NAME(_nc_acs_char) (sp, ChCharOf(ch)));
325 rec.Left = (short) x;
327 rec.Right = (short) (x + n - 1);
328 rec.Bottom = rec.Top;
330 return write_screen(CON.hdl, ci, siz, loc, &rec);
332 #define con_write(tcb, y, x, str, n) con_write8(tcb, y, x, str, n)
337 * Comparing new/current screens, determine the last column-index for a change
338 * beginning on the given row,col position. Unlike a serial terminal, there is
339 * no cost for "moving" the "cursor" on the line as we update it.
342 find_end_of_change(SCREEN *sp, int row, int col)
345 struct ldat *curdat = CurScreen(sp)->_line + row;
346 struct ldat *newdat = NewScreen(sp)->_line + row;
348 while (col <= newdat->lastchar) {
349 #if USE_WIDEC_SUPPORT
350 if (isWidecExt(curdat->text[col]) || isWidecExt(newdat->text[col])) {
352 } else if (memcmp(&curdat->text[col],
354 sizeof(curdat->text[0]))) {
360 if (curdat->text[col] != newdat->text[col]) {
372 * Given a row,col position at the end of a change-chunk, look for the
373 * beginning of the next change-chunk.
376 find_next_change(SCREEN *sp, int row, int col)
378 struct ldat *curdat = CurScreen(sp)->_line + row;
379 struct ldat *newdat = NewScreen(sp)->_line + row;
380 int result = newdat->lastchar + 1;
382 while (++col <= newdat->lastchar) {
383 #if USE_WIDEC_SUPPORT
384 if (isWidecExt(curdat->text[col]) != isWidecExt(newdat->text[col])) {
387 } else if (memcmp(&curdat->text[col],
389 sizeof(curdat->text[0]))) {
394 if (curdat->text[col] != newdat->text[col]) {
403 #define EndChange(first) \
404 find_end_of_change(sp, y, first)
405 #define NextChange(last) \
406 find_next_change(sp, y, last)
408 #endif /* EXP_OPTIMIZE */
410 #define MARK_NOCHANGE(win,row) \
411 win->_line[row].firstchar = _NOCHANGE; \
412 win->_line[row].lastchar = _NOCHANGE
415 selectActiveHandle(void)
417 if (CON.lastOut != CON.hdl) {
418 CON.lastOut = CON.hdl;
419 SetConsoleActiveScreenBuffer(CON.lastOut);
424 restore_original_screen(void)
428 SMALL_RECT save_region = CON.save_region;
430 T(("... restoring %s", CON.window_only ? "window" : "entire buffer"));
432 bufferCoord.X = (SHORT) (CON.window_only ? CON.SBI.srWindow.Left : 0);
433 bufferCoord.Y = (SHORT) (CON.window_only ? CON.SBI.srWindow.Top : 0);
435 if (write_screen(CON.hdl,
441 mvcur(-1, -1, LINES - 2, 0);
442 T(("... restore original screen contents ok %dx%d (%d,%d - %d,%d)",
450 T(("... restore original screen contents err"));
456 wcon_name(TERMINAL_CONTROL_BLOCK * TCB)
459 return "win32console";
463 wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
466 int y, nonempty, n, x0, x1, Width, Height;
472 T((T_CALLED("win32con::wcon_doupdate(%p)"), TCB));
473 if (okConsoleHandle(TCB)) {
475 Width = screen_columns(sp);
476 Height = screen_lines(sp);
477 nonempty = min(Height, NewScreen(sp)->_maxy + 1);
479 T(("... %dx%d clear cur:%d new:%d",
481 CurScreen(sp)->_clear,
482 NewScreen(sp)->_clear));
484 if (SP_PARM->_endwin) {
486 T(("coming back from shell mode"));
487 NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_ARG);
489 NCURSES_SP_NAME(_nc_mvcur_resume) (NCURSES_SP_ARG);
490 NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_ARG);
491 SP_PARM->_mouse_resume(SP_PARM);
493 SP_PARM->_endwin = FALSE;
496 if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
498 #if USE_WIDEC_SUPPORT
499 cchar_t empty[Width];
505 for (x = 0; x < Width; x++)
506 setcchar(&empty[x], blank, 0, 0, 0);
510 for (x = 0; x < Width; x++)
514 for (y = 0; y < nonempty; y++) {
515 con_write(TCB, y, 0, empty, Width);
517 CurScreen(sp)->_line[y].text,
518 (size_t) Width * sizeof(empty[0]));
520 CurScreen(sp)->_clear = FALSE;
521 NewScreen(sp)->_clear = FALSE;
522 touchwin(NewScreen(sp));
523 T(("... cleared %dx%d lines @%d of screen", nonempty, Width,
527 for (y = 0; y < nonempty; y++) {
528 x0 = NewScreen(sp)->_line[y].firstchar;
529 if (x0 != _NOCHANGE) {
532 int limit = NewScreen(sp)->_line[y].lastchar;
533 while ((x1 = EndChange(x0)) <= limit) {
534 while ((x2 = NextChange(x1)) <= limit && x2 <= (x1 + 2)) {
538 memcpy(&CurScreen(sp)->_line[y].text[x0],
539 &NewScreen(sp)->_line[y].text[x0],
540 n * sizeof(CurScreen(sp)->_line[y].text[x0]));
544 &CurScreen(sp)->_line[y].text[x0], n);
548 /* mark line changed successfully */
549 if (y <= NewScreen(sp)->_maxy) {
550 MARK_NOCHANGE(NewScreen(sp), y);
552 if (y <= CurScreen(sp)->_maxy) {
553 MARK_NOCHANGE(CurScreen(sp), y);
556 x1 = NewScreen(sp)->_line[y].lastchar;
559 memcpy(&CurScreen(sp)->_line[y].text[x0],
560 &NewScreen(sp)->_line[y].text[x0],
561 (size_t) n * sizeof(CurScreen(sp)->_line[y].text[x0]));
565 &CurScreen(sp)->_line[y].text[x0], n);
567 /* mark line changed successfully */
568 if (y <= NewScreen(sp)->_maxy) {
569 MARK_NOCHANGE(NewScreen(sp), y);
571 if (y <= CurScreen(sp)->_maxy) {
572 MARK_NOCHANGE(CurScreen(sp), y);
579 /* put everything back in sync */
580 for (y = nonempty; y <= NewScreen(sp)->_maxy; y++) {
581 MARK_NOCHANGE(NewScreen(sp), y);
583 for (y = nonempty; y <= CurScreen(sp)->_maxy; y++) {
584 MARK_NOCHANGE(CurScreen(sp), y);
587 if (!NewScreen(sp)->_leaveok) {
588 CurScreen(sp)->_curx = NewScreen(sp)->_curx;
589 CurScreen(sp)->_cury = NewScreen(sp)->_cury;
591 TCB->drv->td_hwcur(TCB,
593 CurScreen(sp)->_cury, CurScreen(sp)->_curx);
595 selectActiveHandle();
602 wcon_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
604 int *errret GCC_UNUSED)
608 T((T_CALLED("win32con::wcon_CanHandle(%p)"), TCB));
610 assert((TCB != 0) && (tname != 0));
612 TCB->magic = WINMAGIC;
614 if (tname == 0 || *tname == 0)
616 else if (tname != 0 && *tname == '#') {
618 * Use "#" (a character which cannot begin a terminal's name) to
619 * select specific driver from the table.
621 * In principle, we could have more than one non-terminfo driver,
624 size_t n = strlen(tname + 1);
626 && ((strncmp(tname + 1, "win32console", n) == 0)
627 || (strncmp(tname + 1, "win32con", n) == 0))) {
630 } else if (tname != 0 && stricmp(tname, "unknown") == 0) {
635 * This is intentional, to avoid unnecessary breakage of applications
636 * using <term.h> symbols.
638 if (code && (TCB->term.type.Booleans == 0)) {
639 _nc_init_termtype(&(TCB->term.type));
643 if (_nc_mingw_isconsole(0))
644 CON.isTermInfoConsole = TRUE;
650 wcon_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
656 int high = (CON.SBI.srWindow.Bottom - CON.SBI.srWindow.Top + 1);
657 int wide = (CON.SBI.srWindow.Right - CON.SBI.srWindow.Left + 1);
658 int max_cells = (high * wide);
661 CHAR_INFO this_screen[max_cells];
662 CHAR_INFO that_screen[max_cells];
664 SMALL_RECT this_region;
671 this_region.Top = CON.SBI.srWindow.Top;
672 this_region.Left = CON.SBI.srWindow.Left;
673 this_region.Bottom = CON.SBI.srWindow.Bottom;
674 this_region.Right = CON.SBI.srWindow.Right;
676 this_size.X = (SHORT) wide;
677 this_size.Y = (SHORT) high;
679 bufferCoord.X = this_region.Left;
680 bufferCoord.Y = this_region.Top;
689 memcpy(that_screen, this_screen, sizeof(that_screen));
691 for (i = 0; i < max_cells; i++) {
692 that_screen[i].Attributes = RevAttr(that_screen[i].Attributes);
695 write_screen(CON.hdl, that_screen, this_size, bufferCoord, &this_region);
697 write_screen(CON.hdl, this_screen, this_size, bufferCoord, &this_region);
700 MessageBeep(MB_ICONWARNING); /* MB_OK might be better */
706 wcon_print(TERMINAL_CONTROL_BLOCK * TCB,
707 char *data GCC_UNUSED,
719 wcon_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
736 if (GetConsoleScreenBufferInfo(CON.hdl, &(CON.SBI))) {
737 T(("GetConsoleScreenBufferInfo"));
738 T(("... buffer(X:%d Y:%d)",
741 T(("... window(X:%d Y:%d)",
742 CON.SBI.dwMaximumWindowSize.X,
743 CON.SBI.dwMaximumWindowSize.Y));
744 T(("... cursor(X:%d Y:%d)",
745 CON.SBI.dwCursorPosition.X,
746 CON.SBI.dwCursorPosition.Y));
747 T(("... display(Top:%d Bottom:%d Left:%d Right:%d)",
748 CON.SBI.srWindow.Top,
749 CON.SBI.srWindow.Bottom,
750 CON.SBI.srWindow.Left,
751 CON.SBI.srWindow.Right));
756 CON.origin.X = CON.SBI.srWindow.Left;
757 CON.origin.Y = CON.SBI.srWindow.Top;
761 T(("GetConsoleScreenBufferInfo ERR"));
767 wcon_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
770 int (*outc) (SCREEN *, int) GCC_UNUSED)
774 if (okConsoleHandle(TCB)) {
775 WORD a = MapColor(fore, color);
776 a |= (WORD) ((CON.SBI.wAttributes) & (fore ? 0xfff8 : 0xff8f));
777 SetConsoleTextAttribute(CON.hdl, a);
783 wcon_rescol(TERMINAL_CONTROL_BLOCK * TCB)
788 if (okConsoleHandle(TCB)) {
789 WORD a = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
790 SetConsoleTextAttribute(CON.hdl, a);
798 wcon_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
810 wcon_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
816 T((T_CALLED("win32con::wcon_size(%p)"), TCB));
818 if (okConsoleHandle(TCB) &&
822 *Lines = (int) (CON.SBI.dwSize.Y);
823 *Cols = (int) (CON.SBI.dwSize.X);
825 *Lines = (int) (CON.SBI.srWindow.Bottom + 1 -
826 CON.SBI.srWindow.Top);
827 *Cols = (int) (CON.SBI.srWindow.Right + 1 -
828 CON.SBI.srWindow.Left);
836 wcon_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
845 wcon_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
853 if (TCB == 0 || buf == NULL)
857 iflag = buf->c_iflag;
858 lflag = buf->c_lflag;
860 GetConsoleMode(CON.inp, &dwFlag);
863 dwFlag |= ENABLE_LINE_INPUT;
865 dwFlag &= (DWORD) (~ENABLE_LINE_INPUT);
868 dwFlag |= ENABLE_ECHO_INPUT;
870 dwFlag &= (DWORD) (~ENABLE_ECHO_INPUT);
873 dwFlag |= ENABLE_PROCESSED_INPUT;
875 dwFlag &= (DWORD) (~ENABLE_PROCESSED_INPUT);
877 dwFlag |= ENABLE_MOUSE_INPUT;
879 buf->c_iflag = iflag;
880 buf->c_lflag = lflag;
881 SetConsoleMode(CON.inp, dwFlag);
882 TCB->term.Nttyb = *buf;
884 iflag = TCB->term.Nttyb.c_iflag;
885 lflag = TCB->term.Nttyb.c_lflag;
886 GetConsoleMode(CON.inp, &dwFlag);
888 if (dwFlag & ENABLE_LINE_INPUT)
891 lflag &= (tcflag_t) (~ICANON);
893 if (dwFlag & ENABLE_ECHO_INPUT)
896 lflag &= (tcflag_t) (~ECHO);
898 if (dwFlag & ENABLE_PROCESSED_INPUT)
901 iflag &= (tcflag_t) (~BRKINT);
903 TCB->term.Nttyb.c_iflag = iflag;
904 TCB->term.Nttyb.c_lflag = lflag;
906 *buf = TCB->term.Nttyb;
915 * In "normal" mode, reset the buffer- and window-sizes back to their original values.
918 set_scrollback(bool normal, CONSOLE_SCREEN_BUFFER_INFO * info)
922 bool changed = FALSE;
924 T((T_CALLED("win32con::set_scrollback(%s)"),
929 T(("... SBI.srWindow %d,%d .. %d,%d",
932 info->srWindow.Bottom,
933 info->srWindow.Right));
934 T(("... SBI.dwSize %dx%d",
939 rect = info->srWindow;
940 coord = info->dwSize;
941 if (memcmp(info, &CON.SBI, sizeof(*info)) != 0) {
946 int high = info->srWindow.Bottom - info->srWindow.Top + 1;
947 int wide = info->srWindow.Right - info->srWindow.Left + 1;
949 if (high < MIN_HIGH) {
950 T(("... height %d < %d", high, MIN_HIGH));
954 if (wide < MIN_WIDE) {
955 T(("... width %d < %d", wide, MIN_WIDE));
962 rect.Right = (SHORT) (wide - 1);
963 rect.Bottom = (SHORT) (high - 1);
965 coord.X = (SHORT) wide;
966 coord.Y = (SHORT) high;
968 if (info->dwSize.Y != high ||
969 info->dwSize.X != wide ||
970 info->srWindow.Top != 0 ||
971 info->srWindow.Left != 0) {
978 T(("... coord %d,%d", coord.Y, coord.X));
979 T(("... rect %d,%d - %d,%d",
981 rect.Bottom, rect.Right));
982 SetConsoleScreenBufferSize(CON.hdl, coord); /* dwSize */
983 SetConsoleWindowInfo(CON.hdl, TRUE, &rect); /* srWindow */
990 wcon_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
993 TERMINAL *_term = (TERMINAL *) TCB;
999 T((T_CALLED("win32con::wcon_mode(%p, prog=%d, def=%d)"), TCB, progFlag, defFlag));
1000 CON.progMode = progFlag;
1001 CON.lastOut = progFlag ? CON.hdl : CON.out;
1002 SetConsoleActiveScreenBuffer(CON.lastOut);
1004 if (progFlag) /* prog mode */ {
1006 if ((wcon_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
1007 _term->Nttyb.c_oflag &= (tcflag_t) (~OFLAGS_TABS);
1011 /* reset_prog_mode */
1012 if (wcon_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
1015 _nc_keypad(sp, TRUE);
1017 if (!CON.buffered) {
1018 set_scrollback(FALSE, &CON.SBI);
1023 T(("... buffered:%d, clear:%d", CON.buffered, CurScreen(sp)->_clear));
1024 } else { /* shell mode */
1026 /* def_shell_mode */
1027 if (wcon_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
1031 /* reset_shell_mode */
1033 _nc_keypad(sp, FALSE);
1034 NCURSES_SP_NAME(_nc_flush) (sp);
1036 code = wcon_sgmode(TCB, TRUE, &(_term->Ottyb));
1037 if (!CON.buffered) {
1038 set_scrollback(TRUE, &CON.save_SBI);
1039 if (!restore_original_screen())
1042 SetConsoleCursorInfo(CON.hdl, &CON.save_CI);
1050 wcon_screen_init(SCREEN *sp GCC_UNUSED)
1055 wcon_wrap(SCREEN *sp GCC_UNUSED)
1060 rkeycompare(const void *el1, const void *el2)
1062 WORD key1 = (LOWORD((*((const LONG *) el1)))) & 0x7fff;
1063 WORD key2 = (LOWORD((*((const LONG *) el2)))) & 0x7fff;
1065 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
1069 keycompare(const void *el1, const void *el2)
1071 WORD key1 = HIWORD((*((const LONG *) el1)));
1072 WORD key2 = HIWORD((*((const LONG *) el2)));
1074 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
1082 LONG key = GenMap(vKey, 0);
1087 (size_t) (N_INI + FKEYS),
1091 key = *((LONG *) res);
1093 code = (int) (nKey & 0x7fff);
1101 wcon_release(TERMINAL_CONTROL_BLOCK * TCB)
1103 T((T_CALLED("win32con::wcon_release(%p)"), TCB));
1113 read_screen_data(void)
1115 bool result = FALSE;
1119 CON.save_size.X = (SHORT) (CON.save_region.Right
1120 - CON.save_region.Left + 1);
1121 CON.save_size.Y = (SHORT) (CON.save_region.Bottom
1122 - CON.save_region.Top + 1);
1124 want = (size_t) (CON.save_size.X * CON.save_size.Y);
1126 if ((CON.save_screen = malloc(want * sizeof(CHAR_INFO))) != 0) {
1127 bufferCoord.X = (SHORT) (CON.window_only ? CON.SBI.srWindow.Left : 0);
1128 bufferCoord.Y = (SHORT) (CON.window_only ? CON.SBI.srWindow.Top : 0);
1130 T(("... reading console %s %dx%d into %d,%d - %d,%d at %d,%d",
1131 CON.window_only ? "window" : "buffer",
1132 CON.save_size.Y, CON.save_size.X,
1133 CON.save_region.Top,
1134 CON.save_region.Left,
1135 CON.save_region.Bottom,
1136 CON.save_region.Right,
1140 if (read_screen(CON.hdl,
1144 &CON.save_region)) {
1147 T((" error %#lx", (unsigned long) GetLastError()));
1148 FreeAndNull(CON.save_screen);
1156 * Attempt to save the screen contents. PDCurses does this if
1157 * PDC_RESTORE_SCREEN is set, giving the same visual appearance on
1158 * restoration as if the library had allocated a console buffer. MSDN
1159 * says that the data which can be read is limited to 64Kb (and may be
1163 save_original_screen(void)
1165 bool result = FALSE;
1167 CON.save_region.Top = 0;
1168 CON.save_region.Left = 0;
1169 CON.save_region.Bottom = (SHORT) (CON.SBI.dwSize.Y - 1);
1170 CON.save_region.Right = (SHORT) (CON.SBI.dwSize.X - 1);
1172 if (read_screen_data()) {
1176 CON.save_region.Top = CON.SBI.srWindow.Top;
1177 CON.save_region.Left = CON.SBI.srWindow.Left;
1178 CON.save_region.Bottom = CON.SBI.srWindow.Bottom;
1179 CON.save_region.Right = CON.SBI.srWindow.Right;
1181 CON.window_only = TRUE;
1183 if (read_screen_data()) {
1188 T(("... save original screen contents %s", result ? "ok" : "err"));
1193 wcon_init(TERMINAL_CONTROL_BLOCK * TCB)
1195 T((T_CALLED("win32con::wcon_init(%p)"), TCB));
1200 if (CON.hdl == INVALID_HANDLE_VALUE) {
1204 TCB->info.initcolor = TRUE;
1205 TCB->info.canchange = FALSE;
1206 TCB->info.hascolor = TRUE;
1207 TCB->info.caninit = TRUE;
1209 TCB->info.maxpairs = NUMPAIRS;
1210 TCB->info.maxcolors = 8;
1211 TCB->info.numlabels = 0;
1212 TCB->info.labelwidth = 0;
1213 TCB->info.labelheight = 0;
1214 TCB->info.nocolorvideo = 1;
1215 TCB->info.tabsize = 8;
1217 TCB->info.numbuttons = CON.numButtons;
1218 TCB->info.defaultPalette = _nc_cga_palette;
1225 wcon_initpair(TERMINAL_CONTROL_BLOCK * TCB,
1235 if ((pair > 0) && (pair < NUMPAIRS) && (f >= 0) && (f < 8)
1236 && (b >= 0) && (b < 8)) {
1237 CON.pairs[pair] = MapColor(true, f) | MapColor(false, b);
1242 wcon_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
1243 int color GCC_UNUSED,
1255 wcon_do_color(TERMINAL_CONTROL_BLOCK * TCB,
1256 int old_pair GCC_UNUSED,
1257 int pair GCC_UNUSED,
1258 int reverse GCC_UNUSED,
1259 int (*outc) (SCREEN *, int) GCC_UNUSED
1269 wcon_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
1276 sp->_mouse_type = M_TERM_DRIVER;
1280 wcon_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
1288 if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
1291 rc = TCBOf(sp)->drv->td_twait(TCBOf(sp),
1295 EVENTLIST_2nd(evl));
1302 wcon_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
1303 int yold GCC_UNUSED, int xold GCC_UNUSED,
1307 if (okConsoleHandle(TCB)) {
1310 loc.Y = (short) (y + AdjustY());
1311 SetConsoleCursorPosition(CON.hdl, loc);
1318 wcon_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
1319 int labnum GCC_UNUSED,
1320 char *text GCC_UNUSED)
1329 wcon_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
1330 int OnFlag GCC_UNUSED)
1339 wcon_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
1341 chtype res = A_NORMAL;
1342 res |= (A_BOLD | A_DIM | A_REVERSE | A_STANDOUT | A_COLOR);
1347 wcon_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
1356 wcon_initacs(TERMINAL_CONTROL_BLOCK * TCB,
1357 chtype *real_map GCC_UNUSED,
1358 chtype *fake_map GCC_UNUSED)
1360 #define DATA(a,b) { a, b }
1365 DATA('a', 0xb1), /* ACS_CKBOARD */
1366 DATA('f', 0xf8), /* ACS_DEGREE */
1367 DATA('g', 0xf1), /* ACS_PLMINUS */
1368 DATA('j', 0xd9), /* ACS_LRCORNER */
1369 DATA('l', 0xda), /* ACS_ULCORNER */
1370 DATA('k', 0xbf), /* ACS_URCORNER */
1371 DATA('m', 0xc0), /* ACS_LLCORNER */
1372 DATA('n', 0xc5), /* ACS_PLUS */
1373 DATA('q', 0xc4), /* ACS_HLINE */
1374 DATA('t', 0xc3), /* ACS_LTEE */
1375 DATA('u', 0xb4), /* ACS_RTEE */
1376 DATA('v', 0xc1), /* ACS_BTEE */
1377 DATA('w', 0xc2), /* ACS_TTEE */
1378 DATA('x', 0xb3), /* ACS_VLINE */
1379 DATA('y', 0xf3), /* ACS_LEQUAL */
1380 DATA('z', 0xf2), /* ACS_GEQUAL */
1381 DATA('0', 0xdb), /* ACS_BLOCK */
1382 DATA('{', 0xe3), /* ACS_PI */
1383 DATA('}', 0x9c), /* ACS_STERLING */
1384 DATA(',', 0xae), /* ACS_LARROW */
1385 DATA('+', 0xaf), /* ACS_RARROW */
1386 DATA('~', 0xf9), /* ACS_BULLET */
1395 for (n = 0; n < SIZEOF(table); ++n) {
1396 real_map[table[n].acs_code] = (chtype) table[n].use_code | A_ALTCHARSET;
1398 sp->_screen_acs_map[table[n].acs_code] = TRUE;
1403 tdiff(FILETIME fstart, FILETIME fend)
1405 ULARGE_INTEGER ustart;
1406 ULARGE_INTEGER uend;
1409 ustart.LowPart = fstart.dwLowDateTime;
1410 ustart.HighPart = fstart.dwHighDateTime;
1411 uend.LowPart = fend.dwLowDateTime;
1412 uend.HighPart = fend.dwHighDateTime;
1414 diff = (uend.QuadPart - ustart.QuadPart) / 10000;
1419 Adjust(int milliseconds, int diff)
1421 if (milliseconds != INFINITY) {
1422 milliseconds -= diff;
1423 if (milliseconds < 0)
1426 return milliseconds;
1429 #define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \
1430 FROM_LEFT_2ND_BUTTON_PRESSED | \
1431 FROM_LEFT_3RD_BUTTON_PRESSED | \
1432 FROM_LEFT_4TH_BUTTON_PRESSED | \
1433 RIGHTMOST_BUTTON_PRESSED)
1436 decode_mouse(SCREEN *sp, int mask)
1441 assert(sp && console_initialized);
1443 if (mask & FROM_LEFT_1ST_BUTTON_PRESSED)
1444 result |= BUTTON1_PRESSED;
1445 if (mask & FROM_LEFT_2ND_BUTTON_PRESSED)
1446 result |= BUTTON2_PRESSED;
1447 if (mask & FROM_LEFT_3RD_BUTTON_PRESSED)
1448 result |= BUTTON3_PRESSED;
1449 if (mask & FROM_LEFT_4TH_BUTTON_PRESSED)
1450 result |= BUTTON4_PRESSED;
1452 if (mask & RIGHTMOST_BUTTON_PRESSED) {
1453 switch (CON.numButtons) {
1455 result |= BUTTON1_PRESSED;
1458 result |= BUTTON2_PRESSED;
1461 result |= BUTTON3_PRESSED;
1464 result |= BUTTON4_PRESSED;
1479 EVENTLIST_2nd(_nc_eventlist * evl))
1481 INPUT_RECORD inp_rec;
1483 DWORD nRead = 0, rc = (DWORD) (-1);
1488 bool isImmed = (milliseconds == 0);
1490 #define CONSUME() ReadConsoleInput(fd,&inp_rec,1,&nRead)
1494 TR(TRACE_IEVENT, ("start twait: %d milliseconds, mode: %d",
1495 milliseconds, mode));
1497 if (milliseconds < 0)
1498 milliseconds = INFINITY;
1500 memset(&inp_rec, 0, sizeof(inp_rec));
1503 GetSystemTimeAsFileTime(&fstart);
1504 rc = WaitForSingleObject(fd, (DWORD) milliseconds);
1505 GetSystemTimeAsFileTime(&fend);
1506 diff = (int) tdiff(fstart, fend);
1507 milliseconds = Adjust(milliseconds, diff);
1509 if (!isImmed && milliseconds <= 0)
1512 if (rc == WAIT_OBJECT_0) {
1514 b = GetNumberOfConsoleInputEvents(fd, &nRead);
1515 if (b && nRead > 0) {
1516 b = PeekConsoleInput(fd, &inp_rec, 1, &nRead);
1517 if (b && nRead > 0) {
1518 switch (inp_rec.EventType) {
1520 if (mode & TW_INPUT) {
1521 WORD vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
1522 char ch = inp_rec.Event.KeyEvent.uChar.AsciiChar;
1524 if (inp_rec.Event.KeyEvent.bKeyDown) {
1526 int nKey = MapKey(vk);
1527 if ((nKey < 0) || FALSE == sp->_keypad_on) {
1540 if (decode_mouse(sp,
1541 (inp_rec.Event.MouseEvent.dwButtonState
1542 & BUTTON_MASK)) == 0) {
1544 } else if (mode & TW_MOUSE) {
1549 /* e.g., FOCUS_EVENT */
1552 selectActiveHandle();
1560 if (rc != WAIT_TIMEOUT) {
1571 TR(TRACE_IEVENT, ("end twait: returned %d (%d), remaining time %d msec",
1572 code, errno, milliseconds));
1575 *timeleft = milliseconds;
1581 wcon_twait(TERMINAL_CONTROL_BLOCK * TCB,
1585 EVENTLIST_2nd(_nc_eventlist * evl))
1593 code = console_twait(sp,
1597 timeleft EVENTLIST_2nd(_nc_eventlist * evl));
1602 handle_mouse(SCREEN *sp, MOUSE_EVENT_RECORD mer)
1605 bool result = FALSE;
1609 sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons;
1610 sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK;
1613 * We're only interested if the button is pressed or released.
1614 * FIXME: implement continuous event-tracking.
1616 if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
1618 memset(&work, 0, sizeof(work));
1620 if (sp->_drv_mouse_new_buttons) {
1622 work.bstate |= (mmask_t) decode_mouse(sp, sp->_drv_mouse_new_buttons);
1626 /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
1627 work.bstate |= (mmask_t) (decode_mouse(sp,
1628 sp->_drv_mouse_old_buttons)
1634 work.x = mer.dwMousePosition.X;
1635 work.y = mer.dwMousePosition.Y - AdjustY();
1637 sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
1638 sp->_drv_mouse_tail += 1;
1645 wcon_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
1654 T((T_CALLED("win32con::wcon_read(%p)"), TCB));
1655 n = _nc_mingw_console_read(sp, CON.inp, buf);
1660 wcon_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
1662 T((T_CALLED("win32con::wcon_nap(%p, %d)"), TCB, ms));
1668 wcon_cursorSet(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int mode)
1671 CONSOLE_CURSOR_INFO this_CI = CON.save_CI;
1672 T((T_CALLED("win32con:wcon_cursorSet(%d)"), mode));
1675 this_CI.bVisible = FALSE;
1680 this_CI.dwSize = 100;
1683 SetConsoleCursorInfo(CON.hdl, &this_CI);
1688 wcon_kyExist(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int keycode)
1693 LONG key = GenMap(0, (WORD) keycode);
1695 T((T_CALLED("win32con::wcon_kyExist(%d)"), keycode));
1698 (size_t) (N_INI + FKEYS),
1702 key = *((LONG *) res);
1704 if (!(nKey & 0x8000))
1711 wcon_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
1719 T((T_CALLED("win32con::wcon_kpad(%p, %d)"), TCB, flag));
1727 wcon_keyok(TERMINAL_CONTROL_BLOCK * TCB,
1736 LONG key = GenMap(0, (WORD) keycode);
1738 T((T_CALLED("win32con::wcon_keyok(%p, %d, %d)"), TCB, keycode, flag));
1746 (size_t) (N_INI + FKEYS),
1750 key = *((LONG *) res);
1752 nKey = (LOWORD(key)) & 0x7fff;
1755 *(LONG *) res = GenMap(vKey, nKey);
1761 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
1763 wcon_name, /* Name */
1764 wcon_CanHandle, /* CanHandle */
1765 wcon_init, /* init */
1766 wcon_release, /* release */
1767 wcon_size, /* size */
1768 wcon_sgmode, /* sgmode */
1769 wcon_conattr, /* conattr */
1770 wcon_mvcur, /* hwcur */
1771 wcon_mode, /* mode */
1772 wcon_rescol, /* rescol */
1773 wcon_rescolors, /* rescolors */
1774 wcon_setcolor, /* color */
1775 wcon_dobeepflash, /* DoBeepFlash */
1776 wcon_initpair, /* initpair */
1777 wcon_initcolor, /* initcolor */
1778 wcon_do_color, /* docolor */
1779 wcon_initmouse, /* initmouse */
1780 wcon_testmouse, /* testmouse */
1781 wcon_setfilter, /* setfilter */
1782 wcon_hwlabel, /* hwlabel */
1783 wcon_hwlabelOnOff, /* hwlabelOnOff */
1784 wcon_doupdate, /* update */
1785 wcon_defaultcolors, /* defaultcolors */
1786 wcon_print, /* print */
1787 wcon_size, /* getsize */
1788 wcon_setsize, /* setsize */
1789 wcon_initacs, /* initacs */
1790 wcon_screen_init, /* scinit */
1791 wcon_wrap, /* scexit */
1792 wcon_twait, /* twait */
1793 wcon_read, /* read */
1795 wcon_kpad, /* kpad */
1796 wcon_keyok, /* kyOk */
1797 wcon_kyExist, /* kyExist */
1798 wcon_cursorSet /* cursorSet */
1801 /* --------------------------------------------------------- */
1806 intptr_t value = _get_osfhandle(fd);
1807 return (HANDLE) value;
1810 #if WINVER >= 0x0600
1811 /* This function tests, whether or not the ncurses application
1812 is running as a descendant of MSYS2/cygwin mintty terminal
1813 application. mintty doesn't use Windows Console for it's screen
1814 I/O, so the native Windows _isatty doesn't recognize it as
1815 character device. But we can discover we are at the end of an
1816 Pipe and can query to server side of the pipe, looking whether
1817 or not this is mintty.
1820 _ismintty(int fd, LPHANDLE pMinTTY)
1822 HANDLE handle = get_handle(fd);
1826 T((T_CALLED("win32con::_ismintty(%d, %p)"), fd, pMinTTY));
1828 if (handle != INVALID_HANDLE_VALUE) {
1829 dw = GetFileType(handle);
1830 if (dw == FILE_TYPE_PIPE) {
1831 if (GetNamedPipeInfo(handle, 0, 0, 0, 0)) {
1834 if (GetNamedPipeServerProcessId(handle, &pPid)) {
1835 TCHAR buf[MAX_PATH];
1837 /* These security attributes may allow us to
1838 create a remote thread in mintty to manipulate
1839 the terminal state remotely */
1840 HANDLE pHandle = OpenProcess(
1841 PROCESS_CREATE_THREAD
1842 | PROCESS_QUERY_INFORMATION
1843 | PROCESS_VM_OPERATION
1849 *pMinTTY = INVALID_HANDLE_VALUE;
1850 if (pHandle != INVALID_HANDLE_VALUE) {
1851 if ((len = GetProcessImageFileName(
1855 array_length(buf)))) {
1856 TCHAR *pos = _tcsrchr(buf, _T('\\'));
1859 if (_tcsnicmp(pos, _TEXT("mintty.exe"), 10)
1876 /* Borrowed from ansicon project.
1877 Check whether or not an I/O handle is associated with
1881 IsConsoleHandle(HANDLE hdl)
1886 if (!GetConsoleMode(hdl, &dwFlag)) {
1887 result = (int) WriteConsoleA(hdl, NULL, 0, &dwFlag, NULL);
1889 result = (int) (dwFlag & ENABLE_PROCESSED_OUTPUT);
1894 /* Our replacement for the systems _isatty to include also
1895 a test for mintty. This is called from the NC_ISATTY macro
1896 defined in curses.priv.h
1899 _nc_mingw_isatty(int fd)
1904 #define SysISATTY(fd) _isatty(fd)
1906 #define SysISATTY(fd) isatty(fd)
1908 if (SysISATTY(fd)) {
1911 #if WINVER >= 0x0600
1912 result = _ismintty(fd, NULL);
1918 /* This is used when running in terminfo mode to discover,
1919 whether or not the "terminal" is actually a Windows
1920 Console. It's the responsibilty of the console to deal
1921 with the terminal escape sequences that are sent by
1925 _nc_mingw_isconsole(int fd)
1927 HANDLE hdl = get_handle(fd);
1930 T((T_CALLED("win32con::_nc_mingw_isconsole(%d)"), fd));
1932 code = (int) IsConsoleHandle(hdl);
1937 #define TC_PROLOGUE(fd) \
1939 TERMINAL *term = 0; \
1941 if (_nc_screen_chain == 0) \
1943 for (each_screen(sp)) { \
1944 if (sp->_term && (sp->_term->Filedes == fd)) { \
1952 _nc_mingw_tcsetattr(
1954 int optional_action GCC_UNUSED,
1955 const struct termios *arg)
1959 if (_nc_mingw_isconsole(fd)) {
1961 HANDLE ofd = get_handle(fd);
1962 if (ofd != INVALID_HANDLE_VALUE) {
1964 if (arg->c_lflag & ICANON)
1965 dwFlag |= ENABLE_LINE_INPUT;
1967 dwFlag = dwFlag & (DWORD) (~ENABLE_LINE_INPUT);
1969 if (arg->c_lflag & ECHO)
1970 dwFlag = dwFlag | ENABLE_ECHO_INPUT;
1972 dwFlag = dwFlag & (DWORD) (~ENABLE_ECHO_INPUT);
1974 if (arg->c_iflag & BRKINT)
1975 dwFlag |= ENABLE_PROCESSED_INPUT;
1977 dwFlag = dwFlag & (DWORD) (~ENABLE_PROCESSED_INPUT);
1979 dwFlag |= ENABLE_MOUSE_INPUT;
1980 SetConsoleMode(ofd, dwFlag);
1991 _nc_mingw_tcgetattr(int fd, struct termios *arg)
1995 if (_nc_mingw_isconsole(fd)) {
2003 _nc_mingw_tcflush(int fd, int queue)
2008 if (_nc_mingw_isconsole(fd)) {
2009 if (queue == TCIFLUSH) {
2010 BOOL b = FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
2012 return (int) GetLastError();
2019 _nc_mingw_testmouse(
2028 if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
2031 rc = console_twait(sp,
2036 EVENTLIST_2nd(evl));
2042 _nc_mingw_console_read(
2048 INPUT_RECORD inp_rec;
2056 memset(&inp_rec, 0, sizeof(inp_rec));
2058 T((T_CALLED("_nc_mingw_console_read(%p)"), sp));
2060 while ((b = ReadConsoleInput(fd, &inp_rec, 1, &nRead))) {
2061 if (b && nRead > 0) {
2062 if (inp_rec.EventType == KEY_EVENT) {
2063 if (!inp_rec.Event.KeyEvent.bKeyDown)
2065 *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
2066 vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
2068 if (sp->_keypad_on) {
2076 } else { /* *buf != 0 */
2079 } else if (inp_rec.EventType == MOUSE_EVENT) {
2080 if (handle_mouse(sp,
2081 inp_rec.Event.MouseEvent)) {
2093 __attribute__((constructor))
2094 void _enter_console(void)
2096 if (!console_initialized) {
2100 BOOL buffered = TRUE;
2104 if (_nc_mingw_isatty(0)) {
2105 CON.isMinTTY = TRUE;
2108 for (i = 0; i < (N_INI + FKEYS); i++) {
2110 CON.rmap[i] = CON.map[i] =
2113 CON.rmap[i] = CON.map[i] =
2114 (DWORD) GenMap((VK_F1 + (i - N_INI)),
2115 (KEY_F(1) + (i - N_INI)));
2126 if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
2127 CON.numButtons = (int) num_buttons;
2132 a = MapColor(true, COLOR_WHITE) | MapColor(false, COLOR_BLACK);
2133 for (i = 0; i < NUMPAIRS; i++)
2136 CON.inp = GetStdHandle(STD_INPUT_HANDLE);
2137 CON.out = GetStdHandle(STD_OUTPUT_HANDLE);
2142 b = AttachConsole(ATTACH_PARENT_PROCESS);
2144 if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) {
2145 T(("... will not buffer console"));
2149 T(("... creating console buffer"));
2150 CON.hdl = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
2153 CONSOLE_TEXTMODE_BUFFER,
2157 if (CON.hdl != INVALID_HANDLE_VALUE) {
2158 CON.buffered = buffered;
2160 CON.save_SBI = CON.SBI;
2162 save_original_screen();
2163 set_scrollback(FALSE, &CON.SBI);
2165 GetConsoleCursorInfo(CON.hdl, &CON.save_CI);
2166 T(("... initial cursor is %svisible, %d%%",
2167 (CON.save_CI.bVisible ? "" : "not-"),
2168 (int) CON.save_CI.dwSize));
2171 console_initialized = TRUE;