1 /****************************************************************************
2 * Copyright (c) 1998-2012,2013 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 ****************************************************************************/
34 * TODO - GetMousePos(POINT * result) from ntconio.c
35 * TODO - implement nodelay
38 #include <curses.priv.h>
39 #define CUR my_term.type.
41 MODULE_ID("$Id: win_driver.c,v 1.18 2013/03/02 19:48:06 tom Exp $")
43 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
45 #define EXP_OPTIMIZE 0
47 #define okConsoleHandle(TCB) (TCB != 0 && !InvalidConsoleHandle(TCB->hdl))
49 #define AssertTCB() assert(TCB != 0 && (TCB->magic == WINMAGIC))
50 #define SetSP() assert(TCB->csp != 0); sp = TCB->csp; (void) sp
52 #define GenMap(vKey,key) MAKELONG(key, vKey)
54 static const LONG keylist[] =
56 GenMap(VK_PRIOR, KEY_PPAGE),
57 GenMap(VK_NEXT, KEY_NPAGE),
58 GenMap(VK_END, KEY_END),
59 GenMap(VK_HOME, KEY_HOME),
60 GenMap(VK_LEFT, KEY_LEFT),
61 GenMap(VK_UP, KEY_UP),
62 GenMap(VK_RIGHT, KEY_RIGHT),
63 GenMap(VK_DOWN, KEY_DOWN),
64 GenMap(VK_DELETE, KEY_DC),
65 GenMap(VK_INSERT, KEY_IC)
67 #define N_INI ((int)(sizeof(keylist)/sizeof(keylist[0])))
69 #define MAPSIZE (FKEYS + N_INI)
72 typedef struct props {
73 CONSOLE_SCREEN_BUFFER_INFO SBI;
81 #define PropOf(TCB) ((Properties*)TCB->prop)
84 _nc_mingw_ioctl(int fd GCC_UNUSED,
85 long int request GCC_UNUSED,
86 struct termios *arg GCC_UNUSED)
90 fprintf(stderr, "TERMINFO currently not supported on Windows.\n");
95 MapColor(bool fore, int color)
97 static const int _cmap[] =
98 {0, 4, 2, 6, 1, 5, 3, 7};
100 if (color < 0 || color > 7)
110 MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, attr_t ch)
119 if (p > 0 && p < NUMPAIRS && TCB != 0 && sp != 0) {
121 a = PropOf(TCB)->pairs[p];
122 res = (res & 0xff00) | a;
127 res = ((res & 0xff00) | (((res & 0x07) << 4) | ((res & 0x70) >> 4)));
130 res = ((res & 0xff00) | (((res & 0x07) << 4) | ((res & 0x70) >> 4))
131 | BACKGROUND_INTENSITY);
134 res |= FOREGROUND_INTENSITY;
137 res |= BACKGROUND_INTENSITY;
142 #if USE_WIDEC_SUPPORT
144 * TODO: support surrogate pairs
145 * TODO: support combining characters
147 * TODO: check wcwidth of base character, fill if needed for double-width
148 * TODO: _nc_wacs should be part of sp.
151 con_write16(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, cchar_t *str, int limit)
165 for (i = actual = 0; i < limit; i++) {
169 ci[actual].Char.UnicodeChar = CharOf(ch);
170 ci[actual].Attributes = MapAttr(TCB,
171 PropOf(TCB)->SBI.wAttributes,
173 if (AttrOf(ch) & A_ALTCHARSET) {
175 int which = CharOf(ch);
178 && CharOf(_nc_wacs[which]) != 0) {
179 ci[actual].Char.UnicodeChar = CharOf(_nc_wacs[which]);
181 ci[actual].Char.UnicodeChar = ' ';
190 siz.X = (short) actual;
193 rec.Left = (short) x;
195 rec.Right = (short) (x + limit - 1);
196 rec.Bottom = rec.Top;
198 return WriteConsoleOutputW(TCB->hdl, ci, siz, loc, &rec);
200 #define con_write(tcb, y, x, str, n) con_write16(tcb, y, x, str, n)
203 con_write8(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
216 for (i = 0; i < n; i++) {
218 ci[i].Char.AsciiChar = ChCharOf(ch);
219 ci[i].Attributes = MapAttr(TCB,
220 PropOf(TCB)->SBI.wAttributes,
222 if (ChAttrOf(ch) & A_ALTCHARSET) {
224 ci[i].Char.AsciiChar =
225 ChCharOf(NCURSES_SP_NAME(_nc_acs_char) (sp, ChCharOf(ch)));
234 rec.Left = (short) x;
236 rec.Right = (short) (x + n - 1);
237 rec.Bottom = rec.Top;
239 return WriteConsoleOutput(TCB->hdl, ci, siz, loc, &rec);
241 #define con_write(tcb, y, x, str, n) con_write8(tcb, y, x, str, n)
246 * Comparing new/current screens, determine the last column-index for a change
247 * beginning on the given row,col position. Unlike a serial terminal, there is
248 * no cost for "moving" the "cursor" on the line as we update it.
251 find_end_of_change(SCREEN *sp, int row, int col)
254 struct ldat *curdat = CurScreen(sp)->_line + row;
255 struct ldat *newdat = NewScreen(sp)->_line + row;
257 while (col <= newdat->lastchar) {
258 #if USE_WIDEC_SUPPORT
259 if (isWidecExt(curdat->text[col]) || isWidecExt(newdat->text[col])) {
261 } else if (memcmp(&curdat->text[col],
263 sizeof(curdat->text[0]))) {
269 if (curdat->text[col] != newdat->text[col]) {
281 * Given a row,col position at the end of a change-chunk, look for the
282 * beginning of the next change-chunk.
285 find_next_change(SCREEN *sp, int row, int col)
287 struct ldat *curdat = CurScreen(sp)->_line + row;
288 struct ldat *newdat = NewScreen(sp)->_line + row;
289 int result = newdat->lastchar + 1;
291 while (++col <= newdat->lastchar) {
292 #if USE_WIDEC_SUPPORT
293 if (isWidecExt(curdat->text[col]) != isWidecExt(newdat->text[col])) {
296 } else if (memcmp(&curdat->text[col],
298 sizeof(curdat->text[0]))) {
303 if (curdat->text[col] != newdat->text[col]) {
312 #define EndChange(first) \
313 find_end_of_change(sp, y, first)
314 #define NextChange(last) \
315 find_next_change(sp, y, last)
317 #endif /* EXP_OPTIMIZE */
319 #define MARK_NOCHANGE(win,row) \
320 win->_line[row].firstchar = _NOCHANGE; \
321 win->_line[row].lastchar = _NOCHANGE
324 selectActiveHandle(TERMINAL_CONTROL_BLOCK * TCB)
326 if (PropOf(TCB)->lastOut != TCB->hdl) {
327 PropOf(TCB)->lastOut = TCB->hdl;
328 SetConsoleActiveScreenBuffer(PropOf(TCB)->lastOut);
333 drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
336 int y, nonempty, n, x0, x1, Width, Height;
342 T((T_CALLED("win32con::drv_doupdate(%p)"), TCB));
343 if (okConsoleHandle(TCB)) {
345 Width = screen_columns(sp);
346 Height = screen_lines(sp);
347 nonempty = min(Height, NewScreen(sp)->_maxy + 1);
349 if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
351 #if USE_WIDEC_SUPPORT
352 cchar_t empty[Width];
358 for (x = 0; x < Width; x++)
359 setcchar(&empty[x], blank, 0, 0, 0);
363 for (x = 0; x < Width; x++)
367 for (y = 0; y < nonempty; y++) {
368 con_write(TCB, y, 0, empty, Width);
370 CurScreen(sp)->_line[y].text,
371 Width * sizeof(empty[0]));
373 CurScreen(sp)->_clear = FALSE;
374 NewScreen(sp)->_clear = FALSE;
375 touchwin(NewScreen(sp));
378 for (y = 0; y < nonempty; y++) {
379 x0 = NewScreen(sp)->_line[y].firstchar;
380 if (x0 != _NOCHANGE) {
383 int limit = NewScreen(sp)->_line[y].lastchar;
384 while ((x1 = EndChange(x0)) <= limit) {
385 while ((x2 = NextChange(x1)) <= limit && x2 <= (x1 + 2)) {
389 memcpy(&CurScreen(sp)->_line[y].text[x0],
390 &NewScreen(sp)->_line[y].text[x0],
391 n * sizeof(CurScreen(sp)->_line[y].text[x0]));
395 &CurScreen(sp)->_line[y].text[x0], n);
399 /* mark line changed successfully */
400 if (y <= NewScreen(sp)->_maxy) {
401 MARK_NOCHANGE(NewScreen(sp), y);
403 if (y <= CurScreen(sp)->_maxy) {
404 MARK_NOCHANGE(CurScreen(sp), y);
407 x1 = NewScreen(sp)->_line[y].lastchar;
410 memcpy(&CurScreen(sp)->_line[y].text[x0],
411 &NewScreen(sp)->_line[y].text[x0],
412 n * sizeof(CurScreen(sp)->_line[y].text[x0]));
416 &CurScreen(sp)->_line[y].text[x0], n);
418 /* mark line changed successfully */
419 if (y <= NewScreen(sp)->_maxy) {
420 MARK_NOCHANGE(NewScreen(sp), y);
422 if (y <= CurScreen(sp)->_maxy) {
423 MARK_NOCHANGE(CurScreen(sp), y);
430 /* put everything back in sync */
431 for (y = nonempty; y <= NewScreen(sp)->_maxy; y++) {
432 MARK_NOCHANGE(NewScreen(sp), y);
434 for (y = nonempty; y <= CurScreen(sp)->_maxy; y++) {
435 MARK_NOCHANGE(CurScreen(sp), y);
438 if (!NewScreen(sp)->_leaveok) {
439 CurScreen(sp)->_curx = NewScreen(sp)->_curx;
440 CurScreen(sp)->_cury = NewScreen(sp)->_cury;
444 CurScreen(sp)->_cury, CurScreen(sp)->_curx);
446 selectActiveHandle(TCB);
453 drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
455 int *errret GCC_UNUSED)
459 T((T_CALLED("win32con::drv_CanHandle(%p)"), TCB));
464 TCB->magic = WINMAGIC;
465 if (*tname == 0 || *tname == 0 || *tname == '#') {
472 #if (USE_DATABASE || USE_TERMCAP)
473 status = _nc_setup_tinfo(tname, &my_term.type);
477 if (status != TGETENT_YES) {
478 const TERMTYPE *fallback = _nc_fallback(tname);
481 my_term.type = *fallback;
482 status = TGETENT_YES;
483 } else if (!strcmp(tname, "unknown")) {
487 if (status == TGETENT_YES) {
488 if (generic_type || hard_copy)
494 if ((TCB->term.type.Booleans) == 0) {
495 _nc_init_entry(&(TCB->term.type));
503 drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
504 int beepFlag GCC_UNUSED)
516 drv_print(TERMINAL_CONTROL_BLOCK * TCB,
517 char *data GCC_UNUSED,
529 drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
543 drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
546 int (*outc) (SCREEN *, int) GCC_UNUSED)
550 if (okConsoleHandle(TCB)) {
551 WORD a = MapColor(fore, color);
552 a = ((PropOf(TCB)->SBI.wAttributes) & (fore ? 0xfff8 : 0xff8f)) | a;
553 SetConsoleTextAttribute(TCB->hdl, a);
554 GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
559 drv_rescol(TERMINAL_CONTROL_BLOCK * TCB)
564 if (okConsoleHandle(TCB)) {
565 WORD a = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
566 SetConsoleTextAttribute(TCB->hdl, a);
567 GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
574 drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
586 drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
592 T((T_CALLED("win32con::drv_size(%p)"), TCB));
594 if (okConsoleHandle(TCB) &&
597 *Lines = (int) (PropOf(TCB)->SBI.dwSize.Y);
598 *Cols = (int) (PropOf(TCB)->SBI.dwSize.X);
605 drv_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
614 drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf)
622 if (TCB == 0 || buf == NULL)
626 iflag = buf->c_iflag;
627 lflag = buf->c_lflag;
629 GetConsoleMode(TCB->inp, &dwFlag);
632 dwFlag |= ENABLE_LINE_INPUT;
634 dwFlag &= ~ENABLE_LINE_INPUT;
637 dwFlag |= ENABLE_ECHO_INPUT;
639 dwFlag &= ~ENABLE_ECHO_INPUT;
642 dwFlag |= ENABLE_PROCESSED_INPUT;
644 dwFlag &= ~ENABLE_PROCESSED_INPUT;
646 dwFlag |= ENABLE_MOUSE_INPUT;
648 buf->c_iflag = iflag;
649 buf->c_lflag = lflag;
650 SetConsoleMode(TCB->inp, dwFlag);
651 TCB->term.Nttyb = *buf;
653 iflag = TCB->term.Nttyb.c_iflag;
654 lflag = TCB->term.Nttyb.c_lflag;
655 GetConsoleMode(TCB->inp, &dwFlag);
657 if (dwFlag & ENABLE_LINE_INPUT)
662 if (dwFlag & ENABLE_ECHO_INPUT)
667 if (dwFlag & ENABLE_PROCESSED_INPUT)
672 TCB->term.Nttyb.c_iflag = iflag;
673 TCB->term.Nttyb.c_lflag = lflag;
675 *buf = TCB->term.Nttyb;
681 drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag)
684 TERMINAL *_term = (TERMINAL *) TCB;
690 PropOf(TCB)->progMode = progFlag;
691 PropOf(TCB)->lastOut = progFlag ? TCB->hdl : TCB->out;
692 SetConsoleActiveScreenBuffer(PropOf(TCB)->lastOut);
694 if (progFlag) /* prog mode */ {
696 if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
697 _term->Nttyb.c_oflag &= ~OFLAGS_TABS;
701 /* reset_prog_mode */
702 if (drv_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
705 _nc_keypad(sp, TRUE);
706 NC_BUFFERED(sp, TRUE);
711 } else { /* shell mode */
714 if (drv_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
718 /* reset_shell_mode */
720 _nc_keypad(sp, FALSE);
721 NCURSES_SP_NAME(_nc_flush) (sp);
722 NC_BUFFERED(sp, FALSE);
724 code = drv_sgmode(TCB, TRUE, &(_term->Ottyb));
732 drv_screen_init(SCREEN *sp GCC_UNUSED)
737 drv_wrap(SCREEN *sp GCC_UNUSED)
742 rkeycompare(const void *el1, const void *el2)
744 WORD key1 = (LOWORD((*((const LONG *) el1)))) & 0x7fff;
745 WORD key2 = (LOWORD((*((const LONG *) el2)))) & 0x7fff;
747 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
751 keycompare(const void *el1, const void *el2)
753 WORD key1 = HIWORD((*((const LONG *) el1)));
754 WORD key2 = HIWORD((*((const LONG *) el2)));
756 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
760 MapKey(TERMINAL_CONTROL_BLOCK * TCB, WORD vKey)
764 LONG key = GenMap(vKey, 0);
771 (size_t) (N_INI + FKEYS),
775 key = *((LONG *) res);
777 code = (int) (nKey & 0x7fff);
785 drv_release(TERMINAL_CONTROL_BLOCK * TCB)
787 T((T_CALLED("win32con::drv_release(%p)"), TCB));
797 drv_init(TERMINAL_CONTROL_BLOCK * TCB)
801 T((T_CALLED("win32con::drv_init(%p)"), TCB));
806 BOOL b = AllocConsole();
811 b = AttachConsole(ATTACH_PARENT_PROCESS);
813 TCB->inp = GetStdHandle(STD_INPUT_HANDLE);
814 TCB->out = GetStdHandle(STD_OUTPUT_HANDLE);
819 TCB->hdl = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
822 CONSOLE_TEXTMODE_BUFFER,
825 if (!InvalidConsoleHandle(TCB->hdl)) {
826 TCB->prop = typeCalloc(Properties, 1);
827 GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
830 TCB->info.initcolor = TRUE;
831 TCB->info.canchange = FALSE;
832 TCB->info.hascolor = TRUE;
833 TCB->info.caninit = TRUE;
835 TCB->info.maxpairs = NUMPAIRS;
836 TCB->info.maxcolors = 8;
837 TCB->info.numlabels = 0;
838 TCB->info.labelwidth = 0;
839 TCB->info.labelheight = 0;
840 TCB->info.nocolorvideo = 1;
841 TCB->info.tabsize = 8;
843 if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
844 T(("mouse has %ld buttons", num_buttons));
845 TCB->info.numbuttons = num_buttons;
847 TCB->info.numbuttons = 1;
850 TCB->info.defaultPalette = _nc_cga_palette;
852 for (i = 0; i < (N_INI + FKEYS); i++) {
854 PropOf(TCB)->rmap[i] = PropOf(TCB)->map[i] = keylist[i];
856 PropOf(TCB)->rmap[i] = PropOf(TCB)->map[i] =
857 GenMap((VK_F1 + (i - N_INI)), (KEY_F(1) + (i - N_INI)));
859 qsort(PropOf(TCB)->map,
863 qsort(PropOf(TCB)->rmap,
868 a = MapColor(true, COLOR_WHITE) | MapColor(false, COLOR_BLACK);
869 for (i = 0; i < NUMPAIRS; i++)
870 PropOf(TCB)->pairs[i] = a;
876 drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
886 if ((pair > 0) && (pair < NUMPAIRS) && (f >= 0) && (f < 8)
887 && (b >= 0) && (b < 8)) {
888 PropOf(TCB)->pairs[pair] = MapColor(true, f) | MapColor(false, b);
893 drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
894 int color GCC_UNUSED,
906 drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,
907 int old_pair GCC_UNUSED,
909 int reverse GCC_UNUSED,
910 int (*outc) (SCREEN *, int) GCC_UNUSED
920 drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
927 sp->_mouse_type = M_TERM_DRIVER;
931 drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
939 if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
942 rc = TCBOf(sp)->drv->twait(TCBOf(sp),
953 drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
954 int yold GCC_UNUSED, int xold GCC_UNUSED,
958 if (okConsoleHandle(TCB)) {
962 SetConsoleCursorPosition(TCB->hdl, loc);
969 drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
970 int labnum GCC_UNUSED,
971 char *text GCC_UNUSED)
980 drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
981 int OnFlag GCC_UNUSED)
990 drv_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
992 chtype res = A_NORMAL;
993 res |= (A_BOLD | A_DIM | A_REVERSE | A_STANDOUT | A_COLOR);
998 drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
1007 drv_initacs(TERMINAL_CONTROL_BLOCK * TCB,
1008 chtype *real_map GCC_UNUSED,
1009 chtype *fake_map GCC_UNUSED)
1011 #define DATA(a,b) { a, b }
1016 DATA('a', 0xb1), /* ACS_CKBOARD */
1017 DATA('f', 0xf8), /* ACS_DEGREE */
1018 DATA('g', 0xf1), /* ACS_PLMINUS */
1019 DATA('j', 0xd9), /* ACS_LRCORNER */
1020 DATA('l', 0xda), /* ACS_ULCORNER */
1021 DATA('k', 0xbf), /* ACS_URCORNER */
1022 DATA('m', 0xc0), /* ACS_LLCORNER */
1023 DATA('n', 0xc5), /* ACS_PLUS */
1024 DATA('q', 0xc4), /* ACS_HLINE */
1025 DATA('t', 0xc3), /* ACS_LTEE */
1026 DATA('u', 0xb4), /* ACS_RTEE */
1027 DATA('v', 0xc1), /* ACS_BTEE */
1028 DATA('w', 0xc2), /* ACS_TTEE */
1029 DATA('x', 0xb3), /* ACS_VLINE */
1030 DATA('y', 0xf3), /* ACS_LEQUAL */
1031 DATA('z', 0xf2), /* ACS_GEQUAL */
1032 DATA('0', 0xdb), /* ACS_BLOCK */
1033 DATA('{', 0xe3), /* ACS_PI */
1034 DATA('}', 0x9c), /* ACS_STERLING */
1035 DATA(',', 0xae), /* ACS_LARROW */
1036 DATA('+', 0xaf), /* ACS_RARROW */
1037 DATA('~', 0xf9), /* ACS_BULLET */
1046 for (n = 0; n < SIZEOF(table); ++n) {
1047 real_map[table[n].acs_code] = table[n].use_code | A_ALTCHARSET;
1049 sp->_screen_acs_map[table[n].acs_code] = TRUE;
1054 tdiff(FILETIME fstart, FILETIME fend)
1056 ULARGE_INTEGER ustart;
1057 ULARGE_INTEGER uend;
1060 ustart.LowPart = fstart.dwLowDateTime;
1061 ustart.HighPart = fstart.dwHighDateTime;
1062 uend.LowPart = fend.dwLowDateTime;
1063 uend.HighPart = fend.dwHighDateTime;
1065 diff = (uend.QuadPart - ustart.QuadPart) / 10000;
1070 Adjust(int milliseconds, int diff)
1072 if (milliseconds == INFINITY)
1073 return milliseconds;
1074 milliseconds -= diff;
1075 if (milliseconds < 0)
1077 return milliseconds;
1080 #define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \
1081 FROM_LEFT_2ND_BUTTON_PRESSED | \
1082 FROM_LEFT_3RD_BUTTON_PRESSED | \
1083 FROM_LEFT_4TH_BUTTON_PRESSED | \
1084 RIGHTMOST_BUTTON_PRESSED)
1087 decode_mouse(TERMINAL_CONTROL_BLOCK * TCB, int mask)
1095 if (mask & FROM_LEFT_1ST_BUTTON_PRESSED)
1096 result |= BUTTON1_PRESSED;
1097 if (mask & FROM_LEFT_2ND_BUTTON_PRESSED)
1098 result |= BUTTON2_PRESSED;
1099 if (mask & FROM_LEFT_3RD_BUTTON_PRESSED)
1100 result |= BUTTON3_PRESSED;
1101 if (mask & FROM_LEFT_4TH_BUTTON_PRESSED)
1102 result |= BUTTON4_PRESSED;
1104 if (mask & RIGHTMOST_BUTTON_PRESSED) {
1105 switch (TCB->info.numbuttons) {
1107 result |= BUTTON1_PRESSED;
1110 result |= BUTTON2_PRESSED;
1113 result |= BUTTON3_PRESSED;
1116 result |= BUTTON4_PRESSED;
1125 drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
1129 EVENTLIST_2nd(_nc_eventlist * evl))
1132 INPUT_RECORD inp_rec;
1134 DWORD nRead = 0, rc = -1;
1139 bool isImmed = (milliseconds == 0);
1141 #define CONSUME() ReadConsoleInput(TCB->inp,&inp_rec,1,&nRead)
1146 TR(TRACE_IEVENT, ("start twait: %d milliseconds, mode: %d",
1147 milliseconds, mode));
1149 if (milliseconds < 0)
1150 milliseconds = INFINITY;
1152 memset(&inp_rec, 0, sizeof(inp_rec));
1155 GetSystemTimeAsFileTime(&fstart);
1156 rc = WaitForSingleObject(TCB->inp, milliseconds);
1157 GetSystemTimeAsFileTime(&fend);
1158 diff = (int) tdiff(fstart, fend);
1159 milliseconds = Adjust(milliseconds, diff);
1161 if (!isImmed && milliseconds == 0)
1164 if (rc == WAIT_OBJECT_0) {
1166 b = GetNumberOfConsoleInputEvents(TCB->inp, &nRead);
1167 if (b && nRead > 0) {
1168 b = PeekConsoleInput(TCB->inp, &inp_rec, 1, &nRead);
1169 if (b && nRead > 0) {
1170 switch (inp_rec.EventType) {
1172 if (mode & TW_INPUT) {
1173 WORD vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
1174 char ch = inp_rec.Event.KeyEvent.uChar.AsciiChar;
1176 if (inp_rec.Event.KeyEvent.bKeyDown) {
1178 int nKey = MapKey(TCB, vk);
1179 if ((nKey < 0) || FALSE == sp->_keypad_on) {
1192 if (decode_mouse(TCB,
1193 (inp_rec.Event.MouseEvent.dwButtonState
1194 & BUTTON_MASK)) == 0) {
1196 } else if (mode & TW_MOUSE) {
1202 selectActiveHandle(TCB);
1210 if (rc != WAIT_TIMEOUT) {
1221 TR(TRACE_IEVENT, ("end twait: returned %d (%d), remaining time %d msec",
1222 code, errno, milliseconds));
1225 *timeleft = milliseconds;
1231 handle_mouse(TERMINAL_CONTROL_BLOCK * TCB, MOUSE_EVENT_RECORD mer)
1235 bool result = FALSE;
1240 sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons;
1241 sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK;
1244 * We're only interested if the button is pressed or released.
1245 * FIXME: implement continuous event-tracking.
1247 if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
1249 memset(&work, 0, sizeof(work));
1251 if (sp->_drv_mouse_new_buttons) {
1253 work.bstate |= decode_mouse(TCB, sp->_drv_mouse_new_buttons);
1257 /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
1258 work.bstate |= (decode_mouse(TCB, sp->_drv_mouse_old_buttons) >> 1);
1263 work.x = mer.dwMousePosition.X;
1264 work.y = mer.dwMousePosition.Y;
1266 sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
1267 sp->_drv_mouse_tail += 1;
1274 drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
1278 INPUT_RECORD inp_rec;
1287 memset(&inp_rec, 0, sizeof(inp_rec));
1289 T((T_CALLED("win32con::drv_read(%p)"), TCB));
1290 while ((b = ReadConsoleInput(TCB->inp, &inp_rec, 1, &nRead))) {
1291 if (b && nRead > 0) {
1292 if (inp_rec.EventType == KEY_EVENT) {
1293 if (!inp_rec.Event.KeyEvent.bKeyDown)
1295 *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
1296 vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
1298 if (sp->_keypad_on) {
1299 *buf = MapKey(TCB, vk);
1306 } else { /* *buf != 0 */
1309 } else if (inp_rec.EventType == MOUSE_EVENT) {
1310 if (handle_mouse(TCB, inp_rec.Event.MouseEvent)) {
1322 drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
1324 T((T_CALLED("win32con::drv_nap(%p, %d)"), TCB, ms));
1330 drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
1336 LONG key = GenMap(0, (WORD) keycode);
1343 T((T_CALLED("win32con::drv_kyExist(%p, %d)"), TCB, keycode));
1346 (size_t) (N_INI + FKEYS),
1350 key = *((LONG *) res);
1352 if (!(nKey & 0x8000))
1359 drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag GCC_UNUSED)
1367 T((T_CALLED("win32con::drv_kpad(%p, %d)"), TCB, flag));
1375 drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, int flag)
1382 LONG key = GenMap(0, (WORD) keycode);
1387 T((T_CALLED("win32con::drv_keyok(%p, %d, %d)"), TCB, keycode, flag));
1391 (size_t) (N_INI + FKEYS),
1395 key = *((LONG *) res);
1397 nKey = (LOWORD(key)) & 0x7fff;
1400 *(LONG *) res = GenMap(vKey, nKey);
1406 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
1408 drv_CanHandle, /* CanHandle */
1409 drv_init, /* init */
1410 drv_release, /* release */
1411 drv_size, /* size */
1412 drv_sgmode, /* sgmode */
1413 drv_conattr, /* conattr */
1414 drv_mvcur, /* hwcur */
1415 drv_mode, /* mode */
1416 drv_rescol, /* rescol */
1417 drv_rescolors, /* rescolors */
1418 drv_setcolor, /* color */
1419 drv_dobeepflash, /* DoBeepFlash */
1420 drv_initpair, /* initpair */
1421 drv_initcolor, /* initcolor */
1422 drv_do_color, /* docolor */
1423 drv_initmouse, /* initmouse */
1424 drv_testmouse, /* testmouse */
1425 drv_setfilter, /* setfilter */
1426 drv_hwlabel, /* hwlabel */
1427 drv_hwlabelOnOff, /* hwlabelOnOff */
1428 drv_doupdate, /* update */
1429 drv_defaultcolors, /* defaultcolors */
1430 drv_print, /* print */
1431 drv_size, /* getsize */
1432 drv_setsize, /* setsize */
1433 drv_initacs, /* initacs */
1434 drv_screen_init, /* scinit */
1435 drv_wrap, /* scexit */
1436 drv_twait, /* twait */
1437 drv_read, /* read */
1439 drv_kpad, /* kpad */
1440 drv_keyok, /* kyOk */
1441 drv_kyExist /* kyExist */