1 /****************************************************************************
2 * Copyright (c) 1998-2014,2015 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.54 2015/01/10 23:13: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 static const LONG ansi_keys[] =
101 GenMap(VK_PRIOR, 'I'),
102 GenMap(VK_NEXT, 'Q'),
104 GenMap(VK_HOME, 'H'),
105 GenMap(VK_LEFT, 'K'),
107 GenMap(VK_RIGHT, 'M'),
108 GenMap(VK_DOWN, 'P'),
109 GenMap(VK_DELETE, 'S'),
110 GenMap(VK_INSERT, 'R')
112 #define N_INI ((int)array_length(keylist))
114 #define MAPSIZE (FKEYS + N_INI)
117 /* A process can only have a single console, so it's safe
118 to maintain all the information about it in a single
127 BOOL isTermInfoConsole;
133 DWORD ansi_map[MAPSIZE];
136 WORD pairs[NUMPAIRS];
138 CHAR_INFO *save_screen;
140 SMALL_RECT save_region;
141 CONSOLE_SCREEN_BUFFER_INFO SBI;
142 CONSOLE_SCREEN_BUFFER_INFO save_SBI;
143 CONSOLE_CURSOR_INFO save_CI;
146 static BOOL console_initialized = FALSE;
149 MapColor(bool fore, int color)
151 static const int _cmap[] =
152 {0, 4, 2, 6, 1, 5, 3, 7};
154 if (color < 0 || color > 7)
163 #define RevAttr(attr) \
164 (WORD) (((attr) & 0xff00) | \
165 ((((attr) & 0x07) << 4) | \
166 (((attr) & 0x70) >> 4)))
169 MapAttr(WORD res, attr_t ch)
175 if (p > 0 && p < NUMPAIRS) {
178 res = (WORD) ((res & 0xff00) | a);
182 if (ch & A_REVERSE) {
186 if (ch & A_STANDOUT) {
187 res = RevAttr(res) | BACKGROUND_INTENSITY;
191 res |= FOREGROUND_INTENSITY;
194 res |= BACKGROUND_INTENSITY;
199 #if 0 /* def TRACE */
201 dump_screen(const char *fn, int ln)
203 int max_cells = (CON.SBI.dwSize.Y * (1 + CON.SBI.dwSize.X)) + 1;
204 char output[max_cells];
205 CHAR_INFO save_screen[max_cells];
207 SMALL_RECT save_region;
210 T(("dump_screen %s@%d", fn, ln));
212 save_region.Top = CON.SBI.srWindow.Top;
213 save_region.Left = CON.SBI.srWindow.Left;
214 save_region.Bottom = CON.SBI.srWindow.Bottom;
215 save_region.Right = CON.SBI.srWindow.Right;
217 save_size.X = (SHORT) (save_region.Right - save_region.Left + 1);
218 save_size.Y = (SHORT) (save_region.Bottom - save_region.Top + 1);
220 bufferCoord.X = bufferCoord.Y = 0;
222 if (read_screen(CON.hdl,
231 for (i = save_region.Top; i <= save_region.Bottom; ++i) {
232 for (j = save_region.Left; j <= save_region.Right; ++j) {
233 output[k++] = save_screen[ij++].Char.AsciiChar;
239 T(("DUMP: %d,%d - %d,%d",
249 #define dump_screen(fn,ln) /* nothing */
252 #if USE_WIDEC_SUPPORT
254 * TODO: support surrogate pairs
255 * TODO: support combining characters
257 * TODO: _nc_wacs should be part of sp.
260 con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
273 for (i = actual = 0; i < limit; i++) {
277 ci[actual].Char.UnicodeChar = CharOf(ch);
278 ci[actual].Attributes = MapAttr(CON.SBI.wAttributes,
280 if (AttrOf(ch) & A_ALTCHARSET) {
282 int which = CharOf(ch);
285 && CharOf(_nc_wacs[which]) != 0) {
286 ci[actual].Char.UnicodeChar = CharOf(_nc_wacs[which]);
288 ci[actual].Char.UnicodeChar = ' ';
297 siz.X = (SHORT) actual;
300 rec.Left = (SHORT) x;
301 rec.Top = (SHORT) (y + AdjustY());
302 rec.Right = (SHORT) (x + limit - 1);
303 rec.Bottom = rec.Top;
305 return write_screen(CON.hdl, ci, siz, loc, &rec);
307 #define con_write(tcb, y, x, str, n) con_write16(tcb, y, x, str, n)
310 con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
322 for (i = 0; i < n; i++) {
324 ci[i].Char.AsciiChar = ChCharOf(ch);
325 ci[i].Attributes = MapAttr(CON.SBI.wAttributes,
327 if (ChAttrOf(ch) & A_ALTCHARSET) {
329 ci[i].Char.AsciiChar =
330 ChCharOf(NCURSES_SP_NAME(_nc_acs_char) (sp, ChCharOf(ch)));
339 rec.Left = (short) x;
341 rec.Right = (short) (x + n - 1);
342 rec.Bottom = rec.Top;
344 return write_screen(CON.hdl, ci, siz, loc, &rec);
346 #define con_write(tcb, y, x, str, n) con_write8(tcb, y, x, str, n)
351 * Comparing new/current screens, determine the last column-index for a change
352 * beginning on the given row,col position. Unlike a serial terminal, there is
353 * no cost for "moving" the "cursor" on the line as we update it.
356 find_end_of_change(SCREEN *sp, int row, int col)
359 struct ldat *curdat = CurScreen(sp)->_line + row;
360 struct ldat *newdat = NewScreen(sp)->_line + row;
362 while (col <= newdat->lastchar) {
363 #if USE_WIDEC_SUPPORT
364 if (isWidecExt(curdat->text[col]) || isWidecExt(newdat->text[col])) {
366 } else if (memcmp(&curdat->text[col],
368 sizeof(curdat->text[0]))) {
374 if (curdat->text[col] != newdat->text[col]) {
386 * Given a row,col position at the end of a change-chunk, look for the
387 * beginning of the next change-chunk.
390 find_next_change(SCREEN *sp, int row, int col)
392 struct ldat *curdat = CurScreen(sp)->_line + row;
393 struct ldat *newdat = NewScreen(sp)->_line + row;
394 int result = newdat->lastchar + 1;
396 while (++col <= newdat->lastchar) {
397 #if USE_WIDEC_SUPPORT
398 if (isWidecExt(curdat->text[col]) != isWidecExt(newdat->text[col])) {
401 } else if (memcmp(&curdat->text[col],
403 sizeof(curdat->text[0]))) {
408 if (curdat->text[col] != newdat->text[col]) {
417 #define EndChange(first) \
418 find_end_of_change(sp, y, first)
419 #define NextChange(last) \
420 find_next_change(sp, y, last)
422 #endif /* EXP_OPTIMIZE */
424 #define MARK_NOCHANGE(win,row) \
425 win->_line[row].firstchar = _NOCHANGE; \
426 win->_line[row].lastchar = _NOCHANGE
429 selectActiveHandle(void)
431 if (CON.lastOut != CON.hdl) {
432 CON.lastOut = CON.hdl;
433 SetConsoleActiveScreenBuffer(CON.lastOut);
438 restore_original_screen(void)
442 SMALL_RECT save_region = CON.save_region;
444 T(("... restoring %s", CON.window_only ? "window" : "entire buffer"));
446 bufferCoord.X = (SHORT) (CON.window_only ? CON.SBI.srWindow.Left : 0);
447 bufferCoord.Y = (SHORT) (CON.window_only ? CON.SBI.srWindow.Top : 0);
449 if (write_screen(CON.hdl,
455 mvcur(-1, -1, LINES - 2, 0);
456 T(("... restore original screen contents ok %dx%d (%d,%d - %d,%d)",
464 T(("... restore original screen contents err"));
470 wcon_name(TERMINAL_CONTROL_BLOCK * TCB)
473 return "win32console";
477 wcon_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
480 int y, nonempty, n, x0, x1, Width, Height;
486 T((T_CALLED("win32con::wcon_doupdate(%p)"), TCB));
487 if (okConsoleHandle(TCB)) {
489 Width = screen_columns(sp);
490 Height = screen_lines(sp);
491 nonempty = min(Height, NewScreen(sp)->_maxy + 1);
493 T(("... %dx%d clear cur:%d new:%d",
495 CurScreen(sp)->_clear,
496 NewScreen(sp)->_clear));
498 if (SP_PARM->_endwin) {
500 T(("coming back from shell mode"));
501 NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_ARG);
503 NCURSES_SP_NAME(_nc_mvcur_resume) (NCURSES_SP_ARG);
504 NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_ARG);
505 SP_PARM->_mouse_resume(SP_PARM);
507 SP_PARM->_endwin = FALSE;
510 if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
512 #if USE_WIDEC_SUPPORT
513 cchar_t empty[Width];
519 for (x = 0; x < Width; x++)
520 setcchar(&empty[x], blank, 0, 0, 0);
524 for (x = 0; x < Width; x++)
528 for (y = 0; y < nonempty; y++) {
529 con_write(TCB, y, 0, empty, Width);
531 CurScreen(sp)->_line[y].text,
532 (size_t) Width * sizeof(empty[0]));
534 CurScreen(sp)->_clear = FALSE;
535 NewScreen(sp)->_clear = FALSE;
536 touchwin(NewScreen(sp));
537 T(("... cleared %dx%d lines @%d of screen", nonempty, Width,
541 for (y = 0; y < nonempty; y++) {
542 x0 = NewScreen(sp)->_line[y].firstchar;
543 if (x0 != _NOCHANGE) {
546 int limit = NewScreen(sp)->_line[y].lastchar;
547 while ((x1 = EndChange(x0)) <= limit) {
548 while ((x2 = NextChange(x1)) <= limit && x2 <= (x1 + 2)) {
552 memcpy(&CurScreen(sp)->_line[y].text[x0],
553 &NewScreen(sp)->_line[y].text[x0],
554 n * sizeof(CurScreen(sp)->_line[y].text[x0]));
558 &CurScreen(sp)->_line[y].text[x0], n);
562 /* mark line changed successfully */
563 if (y <= NewScreen(sp)->_maxy) {
564 MARK_NOCHANGE(NewScreen(sp), y);
566 if (y <= CurScreen(sp)->_maxy) {
567 MARK_NOCHANGE(CurScreen(sp), y);
570 x1 = NewScreen(sp)->_line[y].lastchar;
573 memcpy(&CurScreen(sp)->_line[y].text[x0],
574 &NewScreen(sp)->_line[y].text[x0],
575 (size_t) n * sizeof(CurScreen(sp)->_line[y].text[x0]));
579 &CurScreen(sp)->_line[y].text[x0], n);
581 /* mark line changed successfully */
582 if (y <= NewScreen(sp)->_maxy) {
583 MARK_NOCHANGE(NewScreen(sp), y);
585 if (y <= CurScreen(sp)->_maxy) {
586 MARK_NOCHANGE(CurScreen(sp), y);
593 /* put everything back in sync */
594 for (y = nonempty; y <= NewScreen(sp)->_maxy; y++) {
595 MARK_NOCHANGE(NewScreen(sp), y);
597 for (y = nonempty; y <= CurScreen(sp)->_maxy; y++) {
598 MARK_NOCHANGE(CurScreen(sp), y);
601 if (!NewScreen(sp)->_leaveok) {
602 CurScreen(sp)->_curx = NewScreen(sp)->_curx;
603 CurScreen(sp)->_cury = NewScreen(sp)->_cury;
605 TCB->drv->td_hwcur(TCB,
607 CurScreen(sp)->_cury, CurScreen(sp)->_curx);
609 selectActiveHandle();
616 wcon_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
618 int *errret GCC_UNUSED)
622 T((T_CALLED("win32con::wcon_CanHandle(%p)"), TCB));
624 assert((TCB != 0) && (tname != 0));
626 TCB->magic = WINMAGIC;
628 if (tname == 0 || *tname == 0)
630 else if (tname != 0 && *tname == '#') {
632 * Use "#" (a character which cannot begin a terminal's name) to
633 * select specific driver from the table.
635 * In principle, we could have more than one non-terminfo driver,
638 size_t n = strlen(tname + 1);
640 && ((strncmp(tname + 1, "win32console", n) == 0)
641 || (strncmp(tname + 1, "win32con", n) == 0))) {
644 } else if (tname != 0 && stricmp(tname, "unknown") == 0) {
649 * This is intentional, to avoid unnecessary breakage of applications
650 * using <term.h> symbols.
652 if (code && (TCB->term.type.Booleans == 0)) {
653 _nc_init_termtype(&(TCB->term.type));
657 if (_nc_mingw_isconsole(0))
658 CON.isTermInfoConsole = TRUE;
664 wcon_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
670 int high = (CON.SBI.srWindow.Bottom - CON.SBI.srWindow.Top + 1);
671 int wide = (CON.SBI.srWindow.Right - CON.SBI.srWindow.Left + 1);
672 int max_cells = (high * wide);
675 CHAR_INFO this_screen[max_cells];
676 CHAR_INFO that_screen[max_cells];
678 SMALL_RECT this_region;
685 this_region.Top = CON.SBI.srWindow.Top;
686 this_region.Left = CON.SBI.srWindow.Left;
687 this_region.Bottom = CON.SBI.srWindow.Bottom;
688 this_region.Right = CON.SBI.srWindow.Right;
690 this_size.X = (SHORT) wide;
691 this_size.Y = (SHORT) high;
693 bufferCoord.X = this_region.Left;
694 bufferCoord.Y = this_region.Top;
703 memcpy(that_screen, this_screen, sizeof(that_screen));
705 for (i = 0; i < max_cells; i++) {
706 that_screen[i].Attributes = RevAttr(that_screen[i].Attributes);
709 write_screen(CON.hdl, that_screen, this_size, bufferCoord, &this_region);
711 write_screen(CON.hdl, this_screen, this_size, bufferCoord, &this_region);
714 MessageBeep(MB_ICONWARNING); /* MB_OK might be better */
720 wcon_print(TERMINAL_CONTROL_BLOCK * TCB,
721 char *data GCC_UNUSED,
733 wcon_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
750 if (GetConsoleScreenBufferInfo(CON.hdl, &(CON.SBI))) {
751 T(("GetConsoleScreenBufferInfo"));
752 T(("... buffer(X:%d Y:%d)",
755 T(("... window(X:%d Y:%d)",
756 CON.SBI.dwMaximumWindowSize.X,
757 CON.SBI.dwMaximumWindowSize.Y));
758 T(("... cursor(X:%d Y:%d)",
759 CON.SBI.dwCursorPosition.X,
760 CON.SBI.dwCursorPosition.Y));
761 T(("... display(Top:%d Bottom:%d Left:%d Right:%d)",
762 CON.SBI.srWindow.Top,
763 CON.SBI.srWindow.Bottom,
764 CON.SBI.srWindow.Left,
765 CON.SBI.srWindow.Right));
770 CON.origin.X = CON.SBI.srWindow.Left;
771 CON.origin.Y = CON.SBI.srWindow.Top;
775 T(("GetConsoleScreenBufferInfo ERR"));
781 wcon_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
784 int (*outc) (SCREEN *, int) GCC_UNUSED)
788 if (okConsoleHandle(TCB)) {
789 WORD a = MapColor(fore, color);
790 a |= (WORD) ((CON.SBI.wAttributes) & (fore ? 0xfff8 : 0xff8f));
791 SetConsoleTextAttribute(CON.hdl, a);
797 wcon_rescol(TERMINAL_CONTROL_BLOCK * TCB)
802 if (okConsoleHandle(TCB)) {
803 WORD a = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
804 SetConsoleTextAttribute(CON.hdl, a);
812 wcon_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
824 wcon_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
830 T((T_CALLED("win32con::wcon_size(%p)"), TCB));
832 if (okConsoleHandle(TCB) &&
836 *Lines = (int) (CON.SBI.dwSize.Y);
837 *Cols = (int) (CON.SBI.dwSize.X);
839 *Lines = (int) (CON.SBI.srWindow.Bottom + 1 -
840 CON.SBI.srWindow.Top);
841 *Cols = (int) (CON.SBI.srWindow.Right + 1 -
842 CON.SBI.srWindow.Left);
850 wcon_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
859 wcon_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
867 if (TCB == 0 || buf == NULL)
871 iflag = buf->c_iflag;
872 lflag = buf->c_lflag;
874 GetConsoleMode(CON.inp, &dwFlag);
877 dwFlag |= ENABLE_LINE_INPUT;
879 dwFlag &= (DWORD) (~ENABLE_LINE_INPUT);
882 dwFlag |= ENABLE_ECHO_INPUT;
884 dwFlag &= (DWORD) (~ENABLE_ECHO_INPUT);
887 dwFlag |= ENABLE_PROCESSED_INPUT;
889 dwFlag &= (DWORD) (~ENABLE_PROCESSED_INPUT);
891 dwFlag |= ENABLE_MOUSE_INPUT;
893 buf->c_iflag = iflag;
894 buf->c_lflag = lflag;
895 SetConsoleMode(CON.inp, dwFlag);
896 TCB->term.Nttyb = *buf;
898 iflag = TCB->term.Nttyb.c_iflag;
899 lflag = TCB->term.Nttyb.c_lflag;
900 GetConsoleMode(CON.inp, &dwFlag);
902 if (dwFlag & ENABLE_LINE_INPUT)
905 lflag &= (tcflag_t) (~ICANON);
907 if (dwFlag & ENABLE_ECHO_INPUT)
910 lflag &= (tcflag_t) (~ECHO);
912 if (dwFlag & ENABLE_PROCESSED_INPUT)
915 iflag &= (tcflag_t) (~BRKINT);
917 TCB->term.Nttyb.c_iflag = iflag;
918 TCB->term.Nttyb.c_lflag = lflag;
920 *buf = TCB->term.Nttyb;
929 * In "normal" mode, reset the buffer- and window-sizes back to their original values.
932 set_scrollback(bool normal, CONSOLE_SCREEN_BUFFER_INFO * info)
936 bool changed = FALSE;
938 T((T_CALLED("win32con::set_scrollback(%s)"),
943 T(("... SBI.srWindow %d,%d .. %d,%d",
946 info->srWindow.Bottom,
947 info->srWindow.Right));
948 T(("... SBI.dwSize %dx%d",
953 rect = info->srWindow;
954 coord = info->dwSize;
955 if (memcmp(info, &CON.SBI, sizeof(*info)) != 0) {
960 int high = info->srWindow.Bottom - info->srWindow.Top + 1;
961 int wide = info->srWindow.Right - info->srWindow.Left + 1;
963 if (high < MIN_HIGH) {
964 T(("... height %d < %d", high, MIN_HIGH));
968 if (wide < MIN_WIDE) {
969 T(("... width %d < %d", wide, MIN_WIDE));
976 rect.Right = (SHORT) (wide - 1);
977 rect.Bottom = (SHORT) (high - 1);
979 coord.X = (SHORT) wide;
980 coord.Y = (SHORT) high;
982 if (info->dwSize.Y != high ||
983 info->dwSize.X != wide ||
984 info->srWindow.Top != 0 ||
985 info->srWindow.Left != 0) {
992 T(("... coord %d,%d", coord.Y, coord.X));
993 T(("... rect %d,%d - %d,%d",
995 rect.Bottom, rect.Right));
996 SetConsoleScreenBufferSize(CON.hdl, coord); /* dwSize */
997 SetConsoleWindowInfo(CON.hdl, TRUE, &rect); /* srWindow */
1004 wcon_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
1007 TERMINAL *_term = (TERMINAL *) TCB;
1013 T((T_CALLED("win32con::wcon_mode(%p, prog=%d, def=%d)"), TCB, progFlag, defFlag));
1014 CON.progMode = progFlag;
1015 CON.lastOut = progFlag ? CON.hdl : CON.out;
1016 SetConsoleActiveScreenBuffer(CON.lastOut);
1018 if (progFlag) /* prog mode */ {
1020 if ((wcon_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
1021 _term->Nttyb.c_oflag &= (tcflag_t) (~OFLAGS_TABS);
1025 /* reset_prog_mode */
1026 if (wcon_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
1029 _nc_keypad(sp, TRUE);
1031 if (!CON.buffered) {
1032 set_scrollback(FALSE, &CON.SBI);
1037 T(("... buffered:%d, clear:%d", CON.buffered, CurScreen(sp)->_clear));
1038 } else { /* shell mode */
1040 /* def_shell_mode */
1041 if (wcon_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
1045 /* reset_shell_mode */
1047 _nc_keypad(sp, FALSE);
1048 NCURSES_SP_NAME(_nc_flush) (sp);
1050 code = wcon_sgmode(TCB, TRUE, &(_term->Ottyb));
1051 if (!CON.buffered) {
1052 set_scrollback(TRUE, &CON.save_SBI);
1053 if (!restore_original_screen())
1056 SetConsoleCursorInfo(CON.hdl, &CON.save_CI);
1064 wcon_screen_init(SCREEN *sp GCC_UNUSED)
1069 wcon_wrap(SCREEN *sp GCC_UNUSED)
1074 rkeycompare(const void *el1, const void *el2)
1076 WORD key1 = (LOWORD((*((const LONG *) el1)))) & 0x7fff;
1077 WORD key2 = (LOWORD((*((const LONG *) el2)))) & 0x7fff;
1079 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
1083 keycompare(const void *el1, const void *el2)
1085 WORD key1 = HIWORD((*((const LONG *) el1)));
1086 WORD key2 = HIWORD((*((const LONG *) el2)));
1088 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
1096 LONG key = GenMap(vKey, 0);
1101 (size_t) (N_INI + FKEYS),
1105 key = *((LONG *) res);
1107 code = (int) (nKey & 0x7fff);
1119 LONG key = GenMap(vKey, 0);
1124 (size_t) (N_INI + FKEYS),
1128 key = *((LONG *) res);
1130 code = (int) (nKey & 0x7fff);
1138 wcon_release(TERMINAL_CONTROL_BLOCK * TCB)
1140 T((T_CALLED("win32con::wcon_release(%p)"), TCB));
1150 read_screen_data(void)
1152 bool result = FALSE;
1156 CON.save_size.X = (SHORT) (CON.save_region.Right
1157 - CON.save_region.Left + 1);
1158 CON.save_size.Y = (SHORT) (CON.save_region.Bottom
1159 - CON.save_region.Top + 1);
1161 want = (size_t) (CON.save_size.X * CON.save_size.Y);
1163 if ((CON.save_screen = malloc(want * sizeof(CHAR_INFO))) != 0) {
1164 bufferCoord.X = (SHORT) (CON.window_only ? CON.SBI.srWindow.Left : 0);
1165 bufferCoord.Y = (SHORT) (CON.window_only ? CON.SBI.srWindow.Top : 0);
1167 T(("... reading console %s %dx%d into %d,%d - %d,%d at %d,%d",
1168 CON.window_only ? "window" : "buffer",
1169 CON.save_size.Y, CON.save_size.X,
1170 CON.save_region.Top,
1171 CON.save_region.Left,
1172 CON.save_region.Bottom,
1173 CON.save_region.Right,
1177 if (read_screen(CON.hdl,
1181 &CON.save_region)) {
1184 T((" error %#lx", (unsigned long) GetLastError()));
1185 FreeAndNull(CON.save_screen);
1193 * Attempt to save the screen contents. PDCurses does this if
1194 * PDC_RESTORE_SCREEN is set, giving the same visual appearance on
1195 * restoration as if the library had allocated a console buffer. MSDN
1196 * says that the data which can be read is limited to 64Kb (and may be
1200 save_original_screen(void)
1202 bool result = FALSE;
1204 CON.save_region.Top = 0;
1205 CON.save_region.Left = 0;
1206 CON.save_region.Bottom = (SHORT) (CON.SBI.dwSize.Y - 1);
1207 CON.save_region.Right = (SHORT) (CON.SBI.dwSize.X - 1);
1209 if (read_screen_data()) {
1213 CON.save_region.Top = CON.SBI.srWindow.Top;
1214 CON.save_region.Left = CON.SBI.srWindow.Left;
1215 CON.save_region.Bottom = CON.SBI.srWindow.Bottom;
1216 CON.save_region.Right = CON.SBI.srWindow.Right;
1218 CON.window_only = TRUE;
1220 if (read_screen_data()) {
1225 T(("... save original screen contents %s", result ? "ok" : "err"));
1230 wcon_init(TERMINAL_CONTROL_BLOCK * TCB)
1232 T((T_CALLED("win32con::wcon_init(%p)"), TCB));
1237 if (CON.hdl == INVALID_HANDLE_VALUE) {
1241 TCB->info.initcolor = TRUE;
1242 TCB->info.canchange = FALSE;
1243 TCB->info.hascolor = TRUE;
1244 TCB->info.caninit = TRUE;
1246 TCB->info.maxpairs = NUMPAIRS;
1247 TCB->info.maxcolors = 8;
1248 TCB->info.numlabels = 0;
1249 TCB->info.labelwidth = 0;
1250 TCB->info.labelheight = 0;
1251 TCB->info.nocolorvideo = 1;
1252 TCB->info.tabsize = 8;
1254 TCB->info.numbuttons = CON.numButtons;
1255 TCB->info.defaultPalette = _nc_cga_palette;
1262 wcon_initpair(TERMINAL_CONTROL_BLOCK * TCB,
1272 if ((pair > 0) && (pair < NUMPAIRS) && (f >= 0) && (f < 8)
1273 && (b >= 0) && (b < 8)) {
1274 CON.pairs[pair] = MapColor(true, f) | MapColor(false, b);
1279 wcon_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
1280 int color GCC_UNUSED,
1292 wcon_do_color(TERMINAL_CONTROL_BLOCK * TCB,
1293 int old_pair GCC_UNUSED,
1294 int pair GCC_UNUSED,
1295 int reverse GCC_UNUSED,
1296 int (*outc) (SCREEN *, int) GCC_UNUSED
1306 wcon_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
1313 sp->_mouse_type = M_TERM_DRIVER;
1317 wcon_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
1325 if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
1328 rc = TCBOf(sp)->drv->td_twait(TCBOf(sp),
1332 EVENTLIST_2nd(evl));
1339 wcon_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
1340 int yold GCC_UNUSED, int xold GCC_UNUSED,
1344 if (okConsoleHandle(TCB)) {
1347 loc.Y = (short) (y + AdjustY());
1348 SetConsoleCursorPosition(CON.hdl, loc);
1355 wcon_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
1356 int labnum GCC_UNUSED,
1357 char *text GCC_UNUSED)
1366 wcon_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
1367 int OnFlag GCC_UNUSED)
1376 wcon_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
1378 chtype res = A_NORMAL;
1379 res |= (A_BOLD | A_DIM | A_REVERSE | A_STANDOUT | A_COLOR);
1384 wcon_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
1393 wcon_initacs(TERMINAL_CONTROL_BLOCK * TCB,
1394 chtype *real_map GCC_UNUSED,
1395 chtype *fake_map GCC_UNUSED)
1397 #define DATA(a,b) { a, b }
1402 DATA('a', 0xb1), /* ACS_CKBOARD */
1403 DATA('f', 0xf8), /* ACS_DEGREE */
1404 DATA('g', 0xf1), /* ACS_PLMINUS */
1405 DATA('j', 0xd9), /* ACS_LRCORNER */
1406 DATA('l', 0xda), /* ACS_ULCORNER */
1407 DATA('k', 0xbf), /* ACS_URCORNER */
1408 DATA('m', 0xc0), /* ACS_LLCORNER */
1409 DATA('n', 0xc5), /* ACS_PLUS */
1410 DATA('q', 0xc4), /* ACS_HLINE */
1411 DATA('t', 0xc3), /* ACS_LTEE */
1412 DATA('u', 0xb4), /* ACS_RTEE */
1413 DATA('v', 0xc1), /* ACS_BTEE */
1414 DATA('w', 0xc2), /* ACS_TTEE */
1415 DATA('x', 0xb3), /* ACS_VLINE */
1416 DATA('y', 0xf3), /* ACS_LEQUAL */
1417 DATA('z', 0xf2), /* ACS_GEQUAL */
1418 DATA('0', 0xdb), /* ACS_BLOCK */
1419 DATA('{', 0xe3), /* ACS_PI */
1420 DATA('}', 0x9c), /* ACS_STERLING */
1421 DATA(',', 0xae), /* ACS_LARROW */
1422 DATA('+', 0xaf), /* ACS_RARROW */
1423 DATA('~', 0xf9), /* ACS_BULLET */
1432 for (n = 0; n < SIZEOF(table); ++n) {
1433 real_map[table[n].acs_code] = (chtype) table[n].use_code | A_ALTCHARSET;
1435 sp->_screen_acs_map[table[n].acs_code] = TRUE;
1440 tdiff(FILETIME fstart, FILETIME fend)
1442 ULARGE_INTEGER ustart;
1443 ULARGE_INTEGER uend;
1446 ustart.LowPart = fstart.dwLowDateTime;
1447 ustart.HighPart = fstart.dwHighDateTime;
1448 uend.LowPart = fend.dwLowDateTime;
1449 uend.HighPart = fend.dwHighDateTime;
1451 diff = (uend.QuadPart - ustart.QuadPart) / 10000;
1456 Adjust(int milliseconds, int diff)
1458 if (milliseconds != INFINITY) {
1459 milliseconds -= diff;
1460 if (milliseconds < 0)
1463 return milliseconds;
1466 #define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \
1467 FROM_LEFT_2ND_BUTTON_PRESSED | \
1468 FROM_LEFT_3RD_BUTTON_PRESSED | \
1469 FROM_LEFT_4TH_BUTTON_PRESSED | \
1470 RIGHTMOST_BUTTON_PRESSED)
1473 decode_mouse(SCREEN *sp, int mask)
1478 assert(sp && console_initialized);
1480 if (mask & FROM_LEFT_1ST_BUTTON_PRESSED)
1481 result |= BUTTON1_PRESSED;
1482 if (mask & FROM_LEFT_2ND_BUTTON_PRESSED)
1483 result |= BUTTON2_PRESSED;
1484 if (mask & FROM_LEFT_3RD_BUTTON_PRESSED)
1485 result |= BUTTON3_PRESSED;
1486 if (mask & FROM_LEFT_4TH_BUTTON_PRESSED)
1487 result |= BUTTON4_PRESSED;
1489 if (mask & RIGHTMOST_BUTTON_PRESSED) {
1490 switch (CON.numButtons) {
1492 result |= BUTTON1_PRESSED;
1495 result |= BUTTON2_PRESSED;
1498 result |= BUTTON3_PRESSED;
1501 result |= BUTTON4_PRESSED;
1516 EVENTLIST_2nd(_nc_eventlist * evl))
1518 INPUT_RECORD inp_rec;
1520 DWORD nRead = 0, rc = (DWORD) (-1);
1525 bool isImmed = (milliseconds == 0);
1527 #define CONSUME() ReadConsoleInput(fd,&inp_rec,1,&nRead)
1531 TR(TRACE_IEVENT, ("start twait: %d milliseconds, mode: %d",
1532 milliseconds, mode));
1534 if (milliseconds < 0)
1535 milliseconds = INFINITY;
1537 memset(&inp_rec, 0, sizeof(inp_rec));
1540 GetSystemTimeAsFileTime(&fstart);
1541 rc = WaitForSingleObject(fd, (DWORD) milliseconds);
1542 GetSystemTimeAsFileTime(&fend);
1543 diff = (int) tdiff(fstart, fend);
1544 milliseconds = Adjust(milliseconds, diff);
1546 if (!isImmed && milliseconds <= 0)
1549 if (rc == WAIT_OBJECT_0) {
1551 b = GetNumberOfConsoleInputEvents(fd, &nRead);
1552 if (b && nRead > 0) {
1553 b = PeekConsoleInput(fd, &inp_rec, 1, &nRead);
1554 if (b && nRead > 0) {
1555 switch (inp_rec.EventType) {
1557 if (mode & TW_INPUT) {
1558 WORD vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
1559 char ch = inp_rec.Event.KeyEvent.uChar.AsciiChar;
1561 if (inp_rec.Event.KeyEvent.bKeyDown) {
1563 int nKey = MapKey(vk);
1577 if (decode_mouse(sp,
1578 (inp_rec.Event.MouseEvent.dwButtonState
1579 & BUTTON_MASK)) == 0) {
1581 } else if (mode & TW_MOUSE) {
1586 /* e.g., FOCUS_EVENT */
1589 selectActiveHandle();
1597 if (rc != WAIT_TIMEOUT) {
1608 TR(TRACE_IEVENT, ("end twait: returned %d (%d), remaining time %d msec",
1609 code, errno, milliseconds));
1612 *timeleft = milliseconds;
1618 wcon_twait(TERMINAL_CONTROL_BLOCK * TCB,
1622 EVENTLIST_2nd(_nc_eventlist * evl))
1630 code = console_twait(sp,
1634 timeleft EVENTLIST_2nd(_nc_eventlist * evl));
1639 handle_mouse(SCREEN *sp, MOUSE_EVENT_RECORD mer)
1642 bool result = FALSE;
1646 sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons;
1647 sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK;
1650 * We're only interested if the button is pressed or released.
1651 * FIXME: implement continuous event-tracking.
1653 if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
1655 memset(&work, 0, sizeof(work));
1657 if (sp->_drv_mouse_new_buttons) {
1659 work.bstate |= (mmask_t) decode_mouse(sp, sp->_drv_mouse_new_buttons);
1663 /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
1664 work.bstate |= (mmask_t) (decode_mouse(sp,
1665 sp->_drv_mouse_old_buttons)
1671 work.x = mer.dwMousePosition.X;
1672 work.y = mer.dwMousePosition.Y - AdjustY();
1674 sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
1675 sp->_drv_mouse_tail += 1;
1682 wcon_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
1691 T((T_CALLED("win32con::wcon_read(%p)"), TCB));
1692 n = _nc_mingw_console_read(sp, CON.inp, buf);
1697 wcon_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
1699 T((T_CALLED("win32con::wcon_nap(%p, %d)"), TCB, ms));
1705 wcon_cursorSet(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int mode)
1708 CONSOLE_CURSOR_INFO this_CI = CON.save_CI;
1709 T((T_CALLED("win32con:wcon_cursorSet(%d)"), mode));
1712 this_CI.bVisible = FALSE;
1717 this_CI.dwSize = 100;
1720 SetConsoleCursorInfo(CON.hdl, &this_CI);
1725 wcon_kyExist(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int keycode)
1730 LONG key = GenMap(0, (WORD) keycode);
1732 T((T_CALLED("win32con::wcon_kyExist(%d)"), keycode));
1735 (size_t) (N_INI + FKEYS),
1739 key = *((LONG *) res);
1741 if (!(nKey & 0x8000))
1748 wcon_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
1756 T((T_CALLED("win32con::wcon_kpad(%p, %d)"), TCB, flag));
1764 wcon_keyok(TERMINAL_CONTROL_BLOCK * TCB,
1773 LONG key = GenMap(0, (WORD) keycode);
1775 T((T_CALLED("win32con::wcon_keyok(%p, %d, %d)"), TCB, keycode, flag));
1783 (size_t) (N_INI + FKEYS),
1787 key = *((LONG *) res);
1789 nKey = (LOWORD(key)) & 0x7fff;
1792 *(LONG *) res = GenMap(vKey, nKey);
1798 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
1800 wcon_name, /* Name */
1801 wcon_CanHandle, /* CanHandle */
1802 wcon_init, /* init */
1803 wcon_release, /* release */
1804 wcon_size, /* size */
1805 wcon_sgmode, /* sgmode */
1806 wcon_conattr, /* conattr */
1807 wcon_mvcur, /* hwcur */
1808 wcon_mode, /* mode */
1809 wcon_rescol, /* rescol */
1810 wcon_rescolors, /* rescolors */
1811 wcon_setcolor, /* color */
1812 wcon_dobeepflash, /* DoBeepFlash */
1813 wcon_initpair, /* initpair */
1814 wcon_initcolor, /* initcolor */
1815 wcon_do_color, /* docolor */
1816 wcon_initmouse, /* initmouse */
1817 wcon_testmouse, /* testmouse */
1818 wcon_setfilter, /* setfilter */
1819 wcon_hwlabel, /* hwlabel */
1820 wcon_hwlabelOnOff, /* hwlabelOnOff */
1821 wcon_doupdate, /* update */
1822 wcon_defaultcolors, /* defaultcolors */
1823 wcon_print, /* print */
1824 wcon_size, /* getsize */
1825 wcon_setsize, /* setsize */
1826 wcon_initacs, /* initacs */
1827 wcon_screen_init, /* scinit */
1828 wcon_wrap, /* scexit */
1829 wcon_twait, /* twait */
1830 wcon_read, /* read */
1832 wcon_kpad, /* kpad */
1833 wcon_keyok, /* kyOk */
1834 wcon_kyExist, /* kyExist */
1835 wcon_cursorSet /* cursorSet */
1838 /* --------------------------------------------------------- */
1843 intptr_t value = _get_osfhandle(fd);
1844 return (HANDLE) value;
1847 #if WINVER >= 0x0600
1848 /* This function tests, whether or not the ncurses application
1849 is running as a descendant of MSYS2/cygwin mintty terminal
1850 application. mintty doesn't use Windows Console for it's screen
1851 I/O, so the native Windows _isatty doesn't recognize it as
1852 character device. But we can discover we are at the end of an
1853 Pipe and can query to server side of the pipe, looking whether
1854 or not this is mintty.
1857 _ismintty(int fd, LPHANDLE pMinTTY)
1859 HANDLE handle = get_handle(fd);
1863 T((T_CALLED("win32con::_ismintty(%d, %p)"), fd, pMinTTY));
1865 if (handle != INVALID_HANDLE_VALUE) {
1866 dw = GetFileType(handle);
1867 if (dw == FILE_TYPE_PIPE) {
1868 if (GetNamedPipeInfo(handle, 0, 0, 0, 0)) {
1871 if (GetNamedPipeServerProcessId(handle, &pPid)) {
1872 TCHAR buf[MAX_PATH];
1874 /* These security attributes may allow us to
1875 create a remote thread in mintty to manipulate
1876 the terminal state remotely */
1877 HANDLE pHandle = OpenProcess(
1878 PROCESS_CREATE_THREAD
1879 | PROCESS_QUERY_INFORMATION
1880 | PROCESS_VM_OPERATION
1886 *pMinTTY = INVALID_HANDLE_VALUE;
1887 if (pHandle != INVALID_HANDLE_VALUE) {
1888 if ((len = GetProcessImageFileName(
1892 array_length(buf)))) {
1893 TCHAR *pos = _tcsrchr(buf, _T('\\'));
1896 if (_tcsnicmp(pos, _TEXT("mintty.exe"), 10)
1913 /* Borrowed from ansicon project.
1914 Check whether or not an I/O handle is associated with
1918 IsConsoleHandle(HANDLE hdl)
1923 if (!GetConsoleMode(hdl, &dwFlag)) {
1924 result = (int) WriteConsoleA(hdl, NULL, 0, &dwFlag, NULL);
1926 result = (int) (dwFlag & ENABLE_PROCESSED_OUTPUT);
1931 /* Our replacement for the systems _isatty to include also
1932 a test for mintty. This is called from the NC_ISATTY macro
1933 defined in curses.priv.h
1936 _nc_mingw_isatty(int fd)
1941 #define SysISATTY(fd) _isatty(fd)
1943 #define SysISATTY(fd) isatty(fd)
1945 if (SysISATTY(fd)) {
1948 #if WINVER >= 0x0600
1949 result = _ismintty(fd, NULL);
1955 /* This is used when running in terminfo mode to discover,
1956 whether or not the "terminal" is actually a Windows
1957 Console. It's the responsibilty of the console to deal
1958 with the terminal escape sequences that are sent by
1962 _nc_mingw_isconsole(int fd)
1964 HANDLE hdl = get_handle(fd);
1967 T((T_CALLED("win32con::_nc_mingw_isconsole(%d)"), fd));
1969 code = (int) IsConsoleHandle(hdl);
1974 #define TC_PROLOGUE(fd) \
1976 TERMINAL *term = 0; \
1978 if (_nc_screen_chain == 0) \
1980 for (each_screen(sp)) { \
1981 if (sp->_term && (sp->_term->Filedes == fd)) { \
1989 _nc_mingw_tcsetattr(
1991 int optional_action GCC_UNUSED,
1992 const struct termios *arg)
1996 if (_nc_mingw_isconsole(fd)) {
1998 HANDLE ofd = get_handle(fd);
1999 if (ofd != INVALID_HANDLE_VALUE) {
2001 if (arg->c_lflag & ICANON)
2002 dwFlag |= ENABLE_LINE_INPUT;
2004 dwFlag = dwFlag & (DWORD) (~ENABLE_LINE_INPUT);
2006 if (arg->c_lflag & ECHO)
2007 dwFlag = dwFlag | ENABLE_ECHO_INPUT;
2009 dwFlag = dwFlag & (DWORD) (~ENABLE_ECHO_INPUT);
2011 if (arg->c_iflag & BRKINT)
2012 dwFlag |= ENABLE_PROCESSED_INPUT;
2014 dwFlag = dwFlag & (DWORD) (~ENABLE_PROCESSED_INPUT);
2016 dwFlag |= ENABLE_MOUSE_INPUT;
2017 SetConsoleMode(ofd, dwFlag);
2028 _nc_mingw_tcgetattr(int fd, struct termios *arg)
2032 if (_nc_mingw_isconsole(fd)) {
2040 _nc_mingw_tcflush(int fd, int queue)
2045 if (_nc_mingw_isconsole(fd)) {
2046 if (queue == TCIFLUSH) {
2047 BOOL b = FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
2049 return (int) GetLastError();
2056 _nc_mingw_testmouse(
2065 if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
2068 rc = console_twait(sp,
2073 EVENTLIST_2nd(evl));
2079 _nc_mingw_console_read(
2085 INPUT_RECORD inp_rec;
2093 memset(&inp_rec, 0, sizeof(inp_rec));
2095 T((T_CALLED("_nc_mingw_console_read(%p)"), sp));
2097 while ((b = ReadConsoleInput(fd, &inp_rec, 1, &nRead))) {
2098 if (b && nRead > 0) {
2099 if (inp_rec.EventType == KEY_EVENT) {
2100 if (!inp_rec.Event.KeyEvent.bKeyDown)
2102 *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
2103 vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
2105 * There are 24 virtual function-keys, and typically
2106 * 12 function-keys on a keyboard. Use the shift-modifier
2107 * to provide the remaining 12 keys.
2109 if (vk >= VK_F1 && vk <= VK_F12) {
2110 if (inp_rec.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) {
2111 vk = (WORD) (vk + 12);
2115 int key = MapKey(vk);
2118 if (sp->_keypad_on) {
2126 } else if (inp_rec.EventType == MOUSE_EVENT) {
2127 if (handle_mouse(sp,
2128 inp_rec.Event.MouseEvent)) {
2140 __attribute__((constructor))
2141 void _enter_console(void)
2143 if (!console_initialized) {
2147 BOOL buffered = TRUE;
2151 if (_nc_mingw_isatty(0)) {
2152 CON.isMinTTY = TRUE;
2155 for (i = 0; i < (N_INI + FKEYS); i++) {
2157 CON.rmap[i] = CON.map[i] =
2159 CON.ansi_map[i] = (DWORD) ansi_keys[i];
2161 CON.rmap[i] = CON.map[i] =
2162 (DWORD) GenMap((VK_F1 + (i - N_INI)),
2163 (KEY_F(1) + (i - N_INI)));
2165 (DWORD) GenMap((VK_F1 + (i - N_INI)),
2166 (';' + (i - N_INI)));
2182 if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
2183 CON.numButtons = (int) num_buttons;
2188 a = MapColor(true, COLOR_WHITE) | MapColor(false, COLOR_BLACK);
2189 for (i = 0; i < NUMPAIRS; i++)
2192 CON.inp = GetStdHandle(STD_INPUT_HANDLE);
2193 CON.out = GetStdHandle(STD_OUTPUT_HANDLE);
2198 b = AttachConsole(ATTACH_PARENT_PROCESS);
2200 if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) {
2201 T(("... will not buffer console"));
2205 T(("... creating console buffer"));
2206 CON.hdl = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
2209 CONSOLE_TEXTMODE_BUFFER,
2213 if (CON.hdl != INVALID_HANDLE_VALUE) {
2214 CON.buffered = buffered;
2216 CON.save_SBI = CON.SBI;
2218 save_original_screen();
2219 set_scrollback(FALSE, &CON.SBI);
2221 GetConsoleCursorInfo(CON.hdl, &CON.save_CI);
2222 T(("... initial cursor is %svisible, %d%%",
2223 (CON.save_CI.bVisible ? "" : "not-"),
2224 (int) CON.save_CI.dwSize));
2227 console_initialized = TRUE;