missing ncurses sources
[tomato.git] / release / src / router / libncurses / ncurses / win32con / win_driver.c
blobc214639cd4df29e8025646f9af44a276a54ee39b
1 /****************************************************************************
2 * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. *
3 * *
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: *
11 * *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
14 * *
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. *
22 * *
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 *
26 * authorization. *
27 ****************************************************************************/
29 /****************************************************************************
30 * Author: Juergen Pfeifer *
31 * *
32 ****************************************************************************/
35 * TODO - GetMousePos(POINT * result) from ntconio.c
36 * TODO - implement nodelay
39 #include <curses.priv.h>
40 #define CUR my_term.type.
42 MODULE_ID("$Id: win_driver.c,v 1.10 2010/12/25 19:28:21 tom Exp $")
44 #define WINMAGIC NCDRV_MAGIC(NCDRV_WINCONSOLE)
46 #define AssertTCB() assert(TCB!=0 && TCB->magic==WINMAGIC)
47 #define SetSP() assert(TCB->csp!=0); sp = TCB->csp
49 #define GenMap(vKey,key) MAKELONG(key, vKey)
51 static const LONG keylist[] =
53 GenMap(VK_PRIOR, KEY_PPAGE),
54 GenMap(VK_NEXT, KEY_NPAGE),
55 GenMap(VK_END, KEY_END),
56 GenMap(VK_HOME, KEY_HOME),
57 GenMap(VK_LEFT, KEY_LEFT),
58 GenMap(VK_UP, KEY_UP),
59 GenMap(VK_RIGHT, KEY_RIGHT),
60 GenMap(VK_DOWN, KEY_DOWN),
61 GenMap(VK_DELETE, KEY_DC),
62 GenMap(VK_INSERT, KEY_IC)
64 #define N_INI ((int)(sizeof(keylist)/sizeof(keylist[0])))
65 #define FKEYS 24
66 #define MAPSIZE (FKEYS + N_INI)
67 #define NUMPAIRS 64
69 typedef struct props {
70 CONSOLE_SCREEN_BUFFER_INFO SBI;
71 bool progMode;
72 DWORD map[MAPSIZE];
73 DWORD rmap[MAPSIZE];
74 WORD pairs[NUMPAIRS];
75 } Properties;
77 #define PropOf(TCB) ((Properties*)TCB->prop)
79 int
80 _nc_mingw_ioctl(int fd GCC_UNUSED,
81 long int request GCC_UNUSED,
82 struct termios *arg GCC_UNUSED)
84 return 0;
85 endwin();
86 fprintf(stderr, "TERMINFO currently not supported on Windows.\n");
87 exit(1);
90 static WORD
91 MapColor(bool fore, int color)
93 static const int _cmap[] =
94 {0, 4, 2, 6, 1, 5, 3, 7};
95 int a;
96 if (color < 0 || color > 7)
97 a = fore ? 7 : 0;
98 else
99 a = _cmap[color];
100 if (!fore)
101 a = a << 4;
102 return (WORD) a;
105 static WORD
106 MapAttr(TERMINAL_CONTROL_BLOCK * TCB, WORD res, chtype ch)
108 if (ch & A_COLOR) {
109 int p;
110 SCREEN *sp;
112 AssertTCB();
113 SetSP();
114 p = PairNumber(ch);
115 if (p > 0 && p < NUMPAIRS && TCB != 0 && sp != 0) {
116 WORD a;
117 a = PropOf(TCB)->pairs[p];
118 res = (res & 0xff00) | a;
122 if (ch & A_REVERSE)
123 res = ((res & 0xff00) | (((res & 0x07) << 4) | ((res & 0x70) >> 4)));
125 if (ch & A_STANDOUT)
126 res = ((res & 0xff00) | (((res & 0x07) << 4) | ((res & 0x70) >> 4))
127 | BACKGROUND_INTENSITY);
129 if (ch & A_BOLD)
130 res |= FOREGROUND_INTENSITY;
132 if (ch & A_DIM)
133 res |= BACKGROUND_INTENSITY;
135 return res;
138 static BOOL
139 con_write(TERMINAL_CONTROL_BLOCK * TCB, int y, int x, chtype *str, int n)
141 CHAR_INFO ci[n];
142 COORD loc, siz;
143 SMALL_RECT rec;
144 int i;
145 chtype ch;
146 SCREEN *sp;
148 AssertTCB();
150 if (TCB == 0 || InvalidConsoleHandle(TCB->hdl))
151 return FALSE;
153 SetSP();
155 for (i = 0; i < n; i++) {
156 ch = str[i];
157 ci[i].Char.AsciiChar = ChCharOf(ch);
158 ci[i].Attributes = MapAttr(TCB,
159 PropOf(TCB)->SBI.wAttributes,
160 ChAttrOf(ch));
161 if (ChAttrOf(ch) & A_ALTCHARSET) {
162 if (sp->_acs_map)
163 ci[i].Char.AsciiChar =
164 ChCharOf(NCURSES_SP_NAME(_nc_acs_char) (sp, ChCharOf(ch)));
168 loc.X = (short) 0;
169 loc.Y = (short) 0;
170 siz.X = (short) n;
171 siz.Y = 1;
173 rec.Left = (short) x;
174 rec.Top = (short) y;
175 rec.Right = (short) (x + n - 1);
176 rec.Bottom = rec.Top;
178 return WriteConsoleOutput(TCB->hdl, ci, siz, loc, &rec);
181 #define MARK_NOCHANGE(win,row) \
182 win->_line[row].firstchar = _NOCHANGE; \
183 win->_line[row].lastchar = _NOCHANGE
185 static int
186 drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB)
188 int y, nonempty, n, x0, x1, Width, Height;
189 SCREEN *sp;
191 AssertTCB();
192 SetSP();
194 Width = screen_columns(sp);
195 Height = screen_lines(sp);
196 nonempty = min(Height, NewScreen(sp)->_maxy + 1);
198 if ((CurScreen(sp)->_clear || NewScreen(sp)->_clear)) {
199 int x;
200 chtype empty[Width];
202 for (x = 0; x < Width; x++)
203 empty[x] = ' ';
205 for (y = 0; y < nonempty; y++) {
206 con_write(TCB, y, 0, empty, Width);
207 memcpy(empty,
208 CurScreen(sp)->_line[y].text,
209 Width * sizeof(chtype));
211 CurScreen(sp)->_clear = FALSE;
212 NewScreen(sp)->_clear = FALSE;
213 touchwin(NewScreen(sp));
216 for (y = 0; y < nonempty; y++) {
217 x0 = NewScreen(sp)->_line[y].firstchar;
218 if (x0 != _NOCHANGE) {
219 x1 = NewScreen(sp)->_line[y].lastchar;
220 n = x1 - x0 + 1;
221 if (n > 0) {
222 memcpy(CurScreen(sp)->_line[y].text + x0,
223 NewScreen(sp)->_line[y].text + x0,
224 n * sizeof(chtype));
225 con_write(TCB,
228 ((chtype *) CurScreen(sp)->_line[y].text) + x0, n);
230 /* mark line changed successfully */
231 if (y <= NewScreen(sp)->_maxy) {
232 MARK_NOCHANGE(NewScreen(sp), y);
234 if (y <= CurScreen(sp)->_maxy) {
235 MARK_NOCHANGE(CurScreen(sp), y);
241 /* put everything back in sync */
242 for (y = nonempty; y <= NewScreen(sp)->_maxy; y++) {
243 MARK_NOCHANGE(NewScreen(sp), y);
245 for (y = nonempty; y <= CurScreen(sp)->_maxy; y++) {
246 MARK_NOCHANGE(CurScreen(sp), y);
249 if (!NewScreen(sp)->_leaveok) {
250 CurScreen(sp)->_curx = NewScreen(sp)->_curx;
251 CurScreen(sp)->_cury = NewScreen(sp)->_cury;
253 TCB->drv->hwcur(TCB, 0, 0, CurScreen(sp)->_cury, CurScreen(sp)->_curx);
255 SetConsoleActiveScreenBuffer(TCB->hdl);
256 return OK;
259 static bool
260 drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB,
261 const char *tname,
262 int *errret GCC_UNUSED)
264 bool code = FALSE;
266 T((T_CALLED("win32con::drv_CanHandle(%p)"), TCB));
268 assert(TCB != 0);
269 assert(tname != 0);
271 TCB->magic = WINMAGIC;
272 if (*tname == 0 || *tname == 0) {
273 code = TRUE;
274 } else {
275 TERMINAL my_term;
276 int status;
278 code = FALSE;
279 #if (USE_DATABASE || USE_TERMCAP)
280 status = _nc_setup_tinfo(tname, &my_term.type);
281 #else
282 status = TGETENT_NO;
283 #endif
284 if (status != TGETENT_YES) {
285 const TERMTYPE *fallback = _nc_fallback(tname);
287 if (fallback) {
288 my_term.type = *fallback;
289 status = TGETENT_YES;
290 } else if (!strcmp(tname, "unknown")) {
291 code = TRUE;
294 if (status == TGETENT_YES) {
295 if (generic_type || hard_copy)
296 code = TRUE;
300 if (code) {
301 if ((TCB->term.type.Booleans) == 0) {
302 _nc_init_entry(&(TCB->term.type));
306 returnBool(code);
309 static int
310 drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB,
311 bool beepFlag GCC_UNUSED)
313 SCREEN *sp;
314 int res = ERR;
316 AssertTCB();
317 SetSP();
319 return res;
322 static int
323 drv_print(TERMINAL_CONTROL_BLOCK * TCB,
324 char *data GCC_UNUSED,
325 int len GCC_UNUSED)
327 SCREEN *sp;
329 AssertTCB();
330 SetSP();
332 return ERR;
335 static int
336 drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB,
337 int fg GCC_UNUSED,
338 int bg GCC_UNUSED)
340 SCREEN *sp;
341 int code = ERR;
343 AssertTCB();
344 SetSP();
346 return (code);
349 static void
350 drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB,
351 bool fore,
352 int color,
353 int (*outc) (SCREEN *, int) GCC_UNUSED)
355 AssertTCB();
357 if (TCB && !InvalidConsoleHandle(TCB->hdl)) {
358 WORD a = MapColor(fore, color);
359 a = ((PropOf(TCB)->SBI.wAttributes) & (fore ? 0xfff8 : 0xff8f)) | a;
360 SetConsoleTextAttribute(TCB->hdl, a);
361 GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
365 static bool
366 drv_rescol(TERMINAL_CONTROL_BLOCK * TCB)
368 bool res = FALSE;
370 AssertTCB();
371 if (TCB && !InvalidConsoleHandle(TCB->hdl)) {
372 WORD a = FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN;
373 SetConsoleTextAttribute(TCB->hdl, a);
374 GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
375 res = TRUE;
377 return res;
380 static bool
381 drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB)
383 int result = FALSE;
384 SCREEN *sp;
386 AssertTCB();
387 SetSP();
389 return result;
392 static int
393 drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *Lines, int *Cols)
395 AssertTCB();
397 if (TCB == NULL || Lines == NULL || Cols == NULL || InvalidConsoleHandle(TCB->hdl))
398 return ERR;
400 *Lines = (int) (PropOf(TCB)->SBI.dwSize.Y);
401 *Cols = (int) (PropOf(TCB)->SBI.dwSize.X);
402 return OK;
405 static int
406 drv_setsize(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED,
407 int l GCC_UNUSED,
408 int c GCC_UNUSED)
410 AssertTCB();
411 return ERR;
414 static int
415 drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, bool setFlag, TTY * buf)
417 DWORD dwFlag = 0;
418 tcflag_t iflag;
419 tcflag_t lflag;
421 AssertTCB();
423 if (TCB == 0 || buf == NULL)
424 return ERR;
426 if (setFlag) {
427 iflag = buf->c_iflag;
428 lflag = buf->c_lflag;
430 GetConsoleMode(TCB->inp, &dwFlag);
432 if (lflag & ICANON)
433 dwFlag |= ENABLE_LINE_INPUT;
434 else
435 dwFlag &= ~ENABLE_LINE_INPUT;
437 if (lflag & ECHO)
438 dwFlag |= ENABLE_ECHO_INPUT;
439 else
440 dwFlag &= ~ENABLE_ECHO_INPUT;
442 if (iflag & BRKINT)
443 dwFlag |= ENABLE_PROCESSED_INPUT;
444 else
445 dwFlag &= ~ENABLE_PROCESSED_INPUT;
447 dwFlag |= ENABLE_MOUSE_INPUT;
449 buf->c_iflag = iflag;
450 buf->c_lflag = lflag;
451 SetConsoleMode(TCB->inp, dwFlag);
452 TCB->term.Nttyb = *buf;
453 } else {
454 iflag = TCB->term.Nttyb.c_iflag;
455 lflag = TCB->term.Nttyb.c_lflag;
456 GetConsoleMode(TCB->inp, &dwFlag);
458 if (dwFlag & ENABLE_LINE_INPUT)
459 lflag |= ICANON;
460 else
461 lflag &= ~ICANON;
463 if (dwFlag & ENABLE_ECHO_INPUT)
464 lflag |= ECHO;
465 else
466 lflag &= ~ECHO;
468 if (dwFlag & ENABLE_PROCESSED_INPUT)
469 iflag |= BRKINT;
470 else
471 iflag &= ~BRKINT;
473 TCB->term.Nttyb.c_iflag = iflag;
474 TCB->term.Nttyb.c_lflag = lflag;
476 *buf = TCB->term.Nttyb;
478 return OK;
481 static int
482 drv_mode(TERMINAL_CONTROL_BLOCK * TCB, bool progFlag, bool defFlag)
484 SCREEN *sp;
485 TERMINAL *_term = (TERMINAL *) TCB;
486 int code = ERR;
488 AssertTCB();
489 sp = TCB->csp;
491 PropOf(TCB)->progMode = progFlag;
492 SetConsoleActiveScreenBuffer(progFlag ? TCB->hdl : TCB->out);
494 if (progFlag) /* prog mode */ {
495 if (defFlag) {
496 if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) {
497 _term->Nttyb.c_oflag &= ~OFLAGS_TABS;
498 code = OK;
500 } else {
501 /* reset_prog_mode */
502 if (drv_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) {
503 if (sp) {
504 if (sp->_keypad_on)
505 _nc_keypad(sp, TRUE);
506 NC_BUFFERED(sp, TRUE);
508 code = OK;
511 } else { /* shell mode */
512 if (defFlag) {
513 /* def_shell_mode */
514 if (drv_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) {
515 code = OK;
517 } else {
518 /* reset_shell_mode */
519 if (sp) {
520 _nc_keypad(sp, FALSE);
521 NCURSES_SP_NAME(_nc_flush) (sp);
522 NC_BUFFERED(sp, FALSE);
524 code = drv_sgmode(TCB, TRUE, &(_term->Ottyb));
528 return (code);
531 static void
532 drv_screen_init(SCREEN *sp GCC_UNUSED)
536 static void
537 drv_wrap(SCREEN *sp GCC_UNUSED)
541 static int
542 rkeycompare(const void *el1, const void *el2)
544 WORD key1 = (LOWORD((*((const LONG *) el1)))) & 0x7fff;
545 WORD key2 = (LOWORD((*((const LONG *) el2)))) & 0x7fff;
547 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
550 static int
551 keycompare(const void *el1, const void *el2)
553 WORD key1 = HIWORD((*((const LONG *) el1)));
554 WORD key2 = HIWORD((*((const LONG *) el2)));
556 return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
559 static int
560 MapKey(TERMINAL_CONTROL_BLOCK * TCB, WORD vKey)
562 WORD nKey = 0;
563 void *res;
564 LONG key = GenMap(vKey, 0);
565 int code = -1;
567 AssertTCB();
569 res = bsearch(&key,
570 PropOf(TCB)->map,
571 (size_t) (N_INI + FKEYS),
572 sizeof(keylist[0]),
573 keycompare);
574 if (res) {
575 key = *((LONG *) res);
576 nKey = LOWORD(key);
577 code = (int) (nKey & 0x7fff);
578 if (nKey & 0x8000)
579 code = -code;
581 return code;
584 static void
585 drv_release(TERMINAL_CONTROL_BLOCK * TCB)
587 T((T_CALLED("win32con::drv_release(%p)"), TCB));
589 AssertTCB();
590 if (TCB->prop)
591 free(TCB->prop);
593 returnVoid;
596 static void
597 drv_init(TERMINAL_CONTROL_BLOCK * TCB)
599 DWORD num_buttons;
601 T((T_CALLED("win32con::drv_init(%p)"), TCB));
603 AssertTCB();
605 if (TCB) {
606 BOOL b = AllocConsole();
607 WORD a;
608 int i;
610 if (!b)
611 b = AttachConsole(ATTACH_PARENT_PROCESS);
613 TCB->inp = GetStdHandle(STD_INPUT_HANDLE);
614 TCB->out = GetStdHandle(STD_OUTPUT_HANDLE);
616 if (getenv("NCGDB"))
617 TCB->hdl = TCB->out;
618 else
619 TCB->hdl = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
621 NULL,
622 CONSOLE_TEXTMODE_BUFFER,
623 NULL);
625 if (!InvalidConsoleHandle(TCB->hdl)) {
626 TCB->prop = typeCalloc(Properties, 1);
627 GetConsoleScreenBufferInfo(TCB->hdl, &(PropOf(TCB)->SBI));
630 TCB->info.initcolor = TRUE;
631 TCB->info.canchange = FALSE;
632 TCB->info.hascolor = TRUE;
633 TCB->info.caninit = TRUE;
635 TCB->info.maxpairs = NUMPAIRS;
636 TCB->info.maxcolors = 8;
637 TCB->info.numlabels = 0;
638 TCB->info.labelwidth = 0;
639 TCB->info.labelheight = 0;
640 TCB->info.nocolorvideo = 1;
641 TCB->info.tabsize = 8;
643 if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
644 T(("mouse has %ld buttons", num_buttons));
645 TCB->info.numbuttons = num_buttons;
646 } else {
647 TCB->info.numbuttons = 1;
650 TCB->info.defaultPalette = _nc_cga_palette;
652 for (i = 0; i < (N_INI + FKEYS); i++) {
653 if (i < N_INI)
654 PropOf(TCB)->rmap[i] = PropOf(TCB)->map[i] = keylist[i];
655 else
656 PropOf(TCB)->rmap[i] = PropOf(TCB)->map[i] =
657 GenMap((VK_F1 + (i - N_INI)), (KEY_F(1) + (i - N_INI)));
659 qsort(PropOf(TCB)->map,
660 (size_t) (MAPSIZE),
661 sizeof(keylist[0]),
662 keycompare);
663 qsort(PropOf(TCB)->rmap,
664 (size_t) (MAPSIZE),
665 sizeof(keylist[0]),
666 rkeycompare);
668 a = MapColor(true, COLOR_WHITE) | MapColor(false, COLOR_BLACK);
669 for (i = 0; i < NUMPAIRS; i++)
670 PropOf(TCB)->pairs[i] = a;
672 returnVoid;
675 static void
676 drv_initpair(TERMINAL_CONTROL_BLOCK * TCB,
677 short pair,
678 short f,
679 short b)
681 SCREEN *sp;
683 AssertTCB();
684 SetSP();
686 if ((pair > 0) && (pair < NUMPAIRS) && (f >= 0) && (f < 8)
687 && (b >= 0) && (b < 8)) {
688 PropOf(TCB)->pairs[pair] = MapColor(true, f) | MapColor(false, b);
692 static void
693 drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB,
694 short color GCC_UNUSED,
695 short r GCC_UNUSED,
696 short g GCC_UNUSED,
697 short b GCC_UNUSED)
699 SCREEN *sp;
701 AssertTCB();
702 SetSP();
705 static void
706 drv_do_color(TERMINAL_CONTROL_BLOCK * TCB,
707 short old_pair GCC_UNUSED,
708 short pair GCC_UNUSED,
709 bool reverse GCC_UNUSED,
710 int (*outc) (SCREEN *, int) GCC_UNUSED
713 SCREEN *sp;
715 AssertTCB();
716 SetSP();
719 static void
720 drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB)
722 SCREEN *sp;
724 AssertTCB();
725 SetSP();
727 sp->_mouse_type = M_TERM_DRIVER;
730 static int
731 drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, int delay)
733 int rc = 0;
734 SCREEN *sp;
736 AssertTCB();
737 SetSP();
739 if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
740 rc = TW_MOUSE;
741 } else {
742 rc = TCBOf(sp)->drv->twait(TCBOf(sp),
743 TWAIT_MASK,
744 delay,
745 (int *) 0
746 EVENTLIST_2nd(evl));
749 return rc;
752 static int
753 drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB,
754 int yold GCC_UNUSED, int xold GCC_UNUSED,
755 int y, int x)
757 int ret = ERR;
758 if (TCB && !InvalidConsoleHandle(TCB->hdl)) {
759 COORD loc;
760 loc.X = (short) x;
761 loc.Y = (short) y;
762 SetConsoleCursorPosition(TCB->hdl, loc);
763 ret = OK;
765 return ret;
768 static void
769 drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB,
770 int labnum GCC_UNUSED,
771 char *text GCC_UNUSED)
773 SCREEN *sp;
775 AssertTCB();
776 SetSP();
779 static void
780 drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB,
781 bool OnFlag GCC_UNUSED)
783 SCREEN *sp;
785 AssertTCB();
786 SetSP();
789 static chtype
790 drv_conattr(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED)
792 chtype res = A_NORMAL;
793 res |= (A_BOLD | A_DIM | A_REVERSE | A_STANDOUT | A_COLOR);
794 return res;
797 static void
798 drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB)
800 SCREEN *sp;
802 AssertTCB();
803 SetSP();
806 static void
807 drv_initacs(TERMINAL_CONTROL_BLOCK * TCB,
808 chtype *real_map GCC_UNUSED,
809 chtype *fake_map GCC_UNUSED)
811 #define DATA(a,b) { a, b }
812 static struct {
813 int acs_code;
814 int use_code;
815 } table[] = {
816 DATA('a', 0xb1), /* ACS_CKBOARD */
817 DATA('f', 0xf8), /* ACS_DEGREE */
818 DATA('g', 0xf1), /* ACS_PLMINUS */
819 DATA('j', 0xd9), /* ACS_LRCORNER */
820 DATA('l', 0xda), /* ACS_ULCORNER */
821 DATA('k', 0xbf), /* ACS_URCORNER */
822 DATA('m', 0xc0), /* ACS_LLCORNER */
823 DATA('n', 0xc5), /* ACS_PLUS */
824 DATA('q', 0xc4), /* ACS_HLINE */
825 DATA('t', 0xc3), /* ACS_LTEE */
826 DATA('u', 0xb4), /* ACS_RTEE */
827 DATA('v', 0xc1), /* ACS_BTEE */
828 DATA('w', 0xc2), /* ACS_TTEE */
829 DATA('x', 0xb3), /* ACS_VLINE */
830 DATA('y', 0xf3), /* ACS_LEQUAL */
831 DATA('z', 0xf2), /* ACS_GEQUAL */
832 DATA('0', 0xdb), /* ACS_BLOCK */
833 DATA('{', 0xe3), /* ACS_PI */
834 DATA('}', 0x9c), /* ACS_STERLING */
835 DATA(',', 0xae), /* ACS_LARROW */
836 DATA('+', 0xaf), /* ACS_RARROW */
837 DATA('~', 0xf9), /* ACS_BULLET */
839 #undef DATA
840 unsigned n;
842 SCREEN *sp;
843 AssertTCB();
844 SetSP();
846 for (n = 0; n < SIZEOF(table); ++n) {
847 real_map[table[n].acs_code] = table[n].use_code | A_ALTCHARSET;
848 if (sp != 0)
849 sp->_screen_acs_map[table[n].acs_code] = TRUE;
853 static ULONGLONG
854 tdiff(FILETIME fstart, FILETIME fend)
856 ULARGE_INTEGER ustart;
857 ULARGE_INTEGER uend;
858 ULONGLONG diff;
860 ustart.LowPart = fstart.dwLowDateTime;
861 ustart.HighPart = fstart.dwHighDateTime;
862 uend.LowPart = fend.dwLowDateTime;
863 uend.HighPart = fend.dwHighDateTime;
865 diff = (uend.QuadPart - ustart.QuadPart) / 10000;
866 return diff;
869 static int
870 Adjust(int milliseconds, int diff)
872 if (milliseconds == INFINITY)
873 return milliseconds;
874 milliseconds -= diff;
875 if (milliseconds < 0)
876 milliseconds = 0;
877 return milliseconds;
880 #define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \
881 FROM_LEFT_2ND_BUTTON_PRESSED | \
882 FROM_LEFT_3RD_BUTTON_PRESSED | \
883 FROM_LEFT_4TH_BUTTON_PRESSED | \
884 RIGHTMOST_BUTTON_PRESSED)
886 static int
887 decode_mouse(TERMINAL_CONTROL_BLOCK * TCB, int mask)
889 SCREEN *sp;
890 int result = 0;
892 AssertTCB();
893 SetSP();
895 if (mask & FROM_LEFT_1ST_BUTTON_PRESSED)
896 result |= BUTTON1_PRESSED;
897 if (mask & FROM_LEFT_2ND_BUTTON_PRESSED)
898 result |= BUTTON2_PRESSED;
899 if (mask & FROM_LEFT_3RD_BUTTON_PRESSED)
900 result |= BUTTON3_PRESSED;
901 if (mask & FROM_LEFT_4TH_BUTTON_PRESSED)
902 result |= BUTTON4_PRESSED;
904 if (mask & RIGHTMOST_BUTTON_PRESSED) {
905 switch (TCB->info.numbuttons) {
906 case 1:
907 result |= BUTTON1_PRESSED;
908 break;
909 case 2:
910 result |= BUTTON2_PRESSED;
911 break;
912 case 3:
913 result |= BUTTON3_PRESSED;
914 break;
915 case 4:
916 result |= BUTTON4_PRESSED;
917 break;
921 return result;
924 static int
925 drv_twait(TERMINAL_CONTROL_BLOCK * TCB,
926 int mode,
927 int milliseconds,
928 int *timeleft
929 EVENTLIST_2nd(_nc_eventlist * evl))
931 SCREEN *sp;
932 INPUT_RECORD inp_rec;
933 BOOL b;
934 DWORD nRead = 0, rc = -1;
935 int code = 0;
936 FILETIME fstart;
937 FILETIME fend;
938 int diff;
939 bool isImmed = (milliseconds == 0);
941 #define CONSUME() ReadConsoleInput(TCB->inp,&inp_rec,1,&nRead)
943 AssertTCB();
944 SetSP();
946 TR(TRACE_IEVENT, ("start twait: %d milliseconds, mode: %d",
947 milliseconds, mode));
949 if (milliseconds < 0)
950 milliseconds = INFINITY;
952 memset(&inp_rec, 0, sizeof(inp_rec));
954 while (true) {
955 GetSystemTimeAsFileTime(&fstart);
956 rc = WaitForSingleObject(TCB->inp, milliseconds);
957 GetSystemTimeAsFileTime(&fend);
958 diff = (int) tdiff(fstart, fend);
959 milliseconds = Adjust(milliseconds, diff);
961 if (!isImmed && milliseconds == 0)
962 break;
964 if (rc == WAIT_OBJECT_0) {
965 if (mode) {
966 b = GetNumberOfConsoleInputEvents(TCB->inp, &nRead);
967 if (b && nRead > 0) {
968 b = PeekConsoleInput(TCB->inp, &inp_rec, 1, &nRead);
969 if (b && nRead > 0) {
970 switch (inp_rec.EventType) {
971 case KEY_EVENT:
972 if (mode & TW_INPUT) {
973 WORD vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
974 char ch = inp_rec.Event.KeyEvent.uChar.AsciiChar;
976 if (inp_rec.Event.KeyEvent.bKeyDown) {
977 if (0 == ch) {
978 int nKey = MapKey(TCB, vk);
979 if ((nKey < 0) || FALSE == sp->_keypad_on) {
980 CONSUME();
981 continue;
984 code = TW_INPUT;
985 goto end;
986 } else {
987 CONSUME();
990 continue;
991 case MOUSE_EVENT:
992 if (decode_mouse(TCB,
993 (inp_rec.Event.MouseEvent.dwButtonState
994 & BUTTON_MASK)) == 0) {
995 CONSUME();
996 } else if (mode & TW_MOUSE) {
997 code = TW_MOUSE;
998 goto end;
1000 continue;
1001 default:
1002 SetConsoleActiveScreenBuffer(!PropOf(TCB)->progMode ?
1003 TCB->hdl : TCB->out);
1004 continue;
1009 continue;
1010 } else {
1011 if (rc != WAIT_TIMEOUT) {
1012 code = -1;
1013 break;
1014 } else {
1015 code = 0;
1016 break;
1020 end:
1022 TR(TRACE_IEVENT, ("end twait: returned %d (%d), remaining time %d msec",
1023 code, errno, milliseconds));
1025 if (timeleft)
1026 *timeleft = milliseconds;
1028 return code;
1031 static bool
1032 handle_mouse(TERMINAL_CONTROL_BLOCK * TCB, MOUSE_EVENT_RECORD mer)
1034 SCREEN *sp;
1035 MEVENT work;
1036 bool result = FALSE;
1038 AssertTCB();
1039 SetSP();
1041 sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons;
1042 sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK;
1045 * We're only interested if the button is pressed or released.
1046 * FIXME: implement continuous event-tracking.
1048 if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
1050 memset(&work, 0, sizeof(work));
1052 if (sp->_drv_mouse_new_buttons) {
1054 work.bstate |= decode_mouse(TCB, sp->_drv_mouse_new_buttons);
1056 } else {
1058 /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
1059 work.bstate |= (decode_mouse(TCB, sp->_drv_mouse_old_buttons) >> 1);
1061 result = TRUE;
1064 work.x = mer.dwMousePosition.X;
1065 work.y = mer.dwMousePosition.Y;
1067 sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
1068 sp->_drv_mouse_tail += 1;
1071 return result;
1074 static int
1075 drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf)
1077 SCREEN *sp;
1078 int n = 1;
1079 INPUT_RECORD inp_rec;
1080 BOOL b;
1081 DWORD nRead;
1082 WORD vk;
1083 WORD sc;
1085 AssertTCB();
1086 assert(buf);
1087 SetSP();
1089 memset(&inp_rec, 0, sizeof(inp_rec));
1091 T((T_CALLED("win32con::drv_read(%p)"), TCB));
1092 while ((b = ReadConsoleInput(TCB->inp, &inp_rec, 1, &nRead))) {
1093 if (b && nRead > 0) {
1094 if (inp_rec.EventType == KEY_EVENT) {
1095 if (!inp_rec.Event.KeyEvent.bKeyDown)
1096 continue;
1097 *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
1098 vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
1099 sc = inp_rec.Event.KeyEvent.wVirtualScanCode;
1100 if (*buf == 0) {
1101 if (sp->_keypad_on) {
1102 *buf = MapKey(TCB, vk);
1103 if (0 > (*buf))
1104 continue;
1105 else
1106 break;
1107 } else
1108 continue;
1109 } else { /* *buf != 0 */
1110 break;
1112 } else if (inp_rec.EventType == MOUSE_EVENT) {
1113 if (handle_mouse(TCB, inp_rec.Event.MouseEvent)) {
1114 *buf = KEY_MOUSE;
1115 break;
1118 continue;
1121 returnCode(n);
1124 static int
1125 drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms)
1127 Sleep(ms);
1128 return OK;
1131 static bool
1132 drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int keycode)
1134 SCREEN *sp;
1135 WORD nKey;
1136 void *res;
1137 bool found = FALSE;
1138 LONG key = GenMap(0, (WORD) keycode);
1140 AssertTCB();
1141 SetSP();
1143 AssertTCB();
1145 res = bsearch(&key,
1146 PropOf(TCB)->rmap,
1147 (size_t) (N_INI + FKEYS),
1148 sizeof(keylist[0]),
1149 rkeycompare);
1150 if (res) {
1151 key = *((LONG *) res);
1152 nKey = LOWORD(key);
1153 if (!(nKey & 0x8000))
1154 found = TRUE;
1156 return found;
1159 static int
1160 drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, bool flag GCC_UNUSED)
1162 SCREEN *sp;
1163 int code = ERR;
1165 AssertTCB();
1166 sp = TCB->csp;
1168 if (sp) {
1169 code = OK;
1171 return code;
1174 static int
1175 drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int keycode, bool flag)
1177 int code = ERR;
1178 SCREEN *sp;
1179 WORD nKey;
1180 WORD vKey;
1181 void *res;
1182 LONG key = GenMap(0, (WORD) keycode);
1184 AssertTCB();
1185 SetSP();
1187 if (sp) {
1188 res = bsearch(&key,
1189 PropOf(TCB)->rmap,
1190 (size_t) (N_INI + FKEYS),
1191 sizeof(keylist[0]),
1192 rkeycompare);
1193 if (res) {
1194 key = *((LONG *) res);
1195 vKey = HIWORD(key);
1196 nKey = (LOWORD(key)) & 0x7fff;
1197 if (!flag)
1198 nKey |= 0x8000;
1199 *(LONG *) res = GenMap(vKey, nKey);
1202 return code;
1205 NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_WIN_DRIVER = {
1206 FALSE,
1207 drv_CanHandle, /* CanHandle */
1208 drv_init, /* init */
1209 drv_release, /* release */
1210 drv_size, /* size */
1211 drv_sgmode, /* sgmode */
1212 drv_conattr, /* conattr */
1213 drv_mvcur, /* hwcur */
1214 drv_mode, /* mode */
1215 drv_rescol, /* rescol */
1216 drv_rescolors, /* rescolors */
1217 drv_setcolor, /* color */
1218 drv_dobeepflash, /* DoBeepFlash */
1219 drv_initpair, /* initpair */
1220 drv_initcolor, /* initcolor */
1221 drv_do_color, /* docolor */
1222 drv_initmouse, /* initmouse */
1223 drv_testmouse, /* testmouse */
1224 drv_setfilter, /* setfilter */
1225 drv_hwlabel, /* hwlabel */
1226 drv_hwlabelOnOff, /* hwlabelOnOff */
1227 drv_doupdate, /* update */
1228 drv_defaultcolors, /* defaultcolors */
1229 drv_print, /* print */
1230 drv_size, /* getsize */
1231 drv_setsize, /* setsize */
1232 drv_initacs, /* initacs */
1233 drv_screen_init, /* scinit */
1234 drv_wrap, /* scexit */
1235 drv_twait, /* twait */
1236 drv_read, /* read */
1237 drv_nap, /* nap */
1238 drv_kpad, /* kpad */
1239 drv_keyok, /* kyOk */
1240 drv_kyExist /* kyExist */