1 /****************************************************************************
2 * Copyright (c) 1998-2009,2010 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 *
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])))
66 #define MAPSIZE (FKEYS + N_INI)
69 typedef struct props
{
70 CONSOLE_SCREEN_BUFFER_INFO SBI
;
77 #define PropOf(TCB) ((Properties*)TCB->prop)
80 _nc_mingw_ioctl(int fd GCC_UNUSED
,
81 long int request GCC_UNUSED
,
82 struct termios
*arg GCC_UNUSED
)
86 fprintf(stderr
, "TERMINFO currently not supported on Windows.\n");
91 MapColor(bool fore
, int color
)
93 static const int _cmap
[] =
94 {0, 4, 2, 6, 1, 5, 3, 7};
96 if (color
< 0 || color
> 7)
106 MapAttr(TERMINAL_CONTROL_BLOCK
* TCB
, WORD res
, chtype ch
)
115 if (p
> 0 && p
< NUMPAIRS
&& TCB
!= 0 && sp
!= 0) {
117 a
= PropOf(TCB
)->pairs
[p
];
118 res
= (res
& 0xff00) | a
;
123 res
= ((res
& 0xff00) | (((res
& 0x07) << 4) | ((res
& 0x70) >> 4)));
126 res
= ((res
& 0xff00) | (((res
& 0x07) << 4) | ((res
& 0x70) >> 4))
127 | BACKGROUND_INTENSITY
);
130 res
|= FOREGROUND_INTENSITY
;
133 res
|= BACKGROUND_INTENSITY
;
139 con_write(TERMINAL_CONTROL_BLOCK
* TCB
, int y
, int x
, chtype
*str
, int n
)
150 if (TCB
== 0 || InvalidConsoleHandle(TCB
->hdl
))
155 for (i
= 0; i
< n
; i
++) {
157 ci
[i
].Char
.AsciiChar
= ChCharOf(ch
);
158 ci
[i
].Attributes
= MapAttr(TCB
,
159 PropOf(TCB
)->SBI
.wAttributes
,
161 if (ChAttrOf(ch
) & A_ALTCHARSET
) {
163 ci
[i
].Char
.AsciiChar
=
164 ChCharOf(NCURSES_SP_NAME(_nc_acs_char
) (sp
, ChCharOf(ch
)));
173 rec
.Left
= (short) x
;
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
186 drv_doupdate(TERMINAL_CONTROL_BLOCK
* TCB
)
188 int y
, nonempty
, n
, x0
, x1
, Width
, Height
;
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
)) {
202 for (x
= 0; x
< Width
; x
++)
205 for (y
= 0; y
< nonempty
; y
++) {
206 con_write(TCB
, y
, 0, empty
, Width
);
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
;
222 memcpy(CurScreen(sp
)->_line
[y
].text
+ x0
,
223 NewScreen(sp
)->_line
[y
].text
+ x0
,
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
);
260 drv_CanHandle(TERMINAL_CONTROL_BLOCK
* TCB
,
262 int *errret GCC_UNUSED
)
266 T((T_CALLED("win32con::drv_CanHandle(%p)"), TCB
));
271 TCB
->magic
= WINMAGIC
;
272 if (*tname
== 0 || *tname
== 0) {
279 #if (USE_DATABASE || USE_TERMCAP)
280 status
= _nc_setup_tinfo(tname
, &my_term
.type
);
284 if (status
!= TGETENT_YES
) {
285 const TERMTYPE
*fallback
= _nc_fallback(tname
);
288 my_term
.type
= *fallback
;
289 status
= TGETENT_YES
;
290 } else if (!strcmp(tname
, "unknown")) {
294 if (status
== TGETENT_YES
) {
295 if (generic_type
|| hard_copy
)
301 if ((TCB
->term
.type
.Booleans
) == 0) {
302 _nc_init_entry(&(TCB
->term
.type
));
310 drv_dobeepflash(TERMINAL_CONTROL_BLOCK
* TCB
,
311 bool beepFlag GCC_UNUSED
)
323 drv_print(TERMINAL_CONTROL_BLOCK
* TCB
,
324 char *data GCC_UNUSED
,
336 drv_defaultcolors(TERMINAL_CONTROL_BLOCK
* TCB
,
350 drv_setcolor(TERMINAL_CONTROL_BLOCK
* TCB
,
353 int (*outc
) (SCREEN
*, int) GCC_UNUSED
)
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
));
366 drv_rescol(TERMINAL_CONTROL_BLOCK
* TCB
)
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
));
381 drv_rescolors(TERMINAL_CONTROL_BLOCK
* TCB
)
393 drv_size(TERMINAL_CONTROL_BLOCK
* TCB
, int *Lines
, int *Cols
)
397 if (TCB
== NULL
|| Lines
== NULL
|| Cols
== NULL
|| InvalidConsoleHandle(TCB
->hdl
))
400 *Lines
= (int) (PropOf(TCB
)->SBI
.dwSize
.Y
);
401 *Cols
= (int) (PropOf(TCB
)->SBI
.dwSize
.X
);
406 drv_setsize(TERMINAL_CONTROL_BLOCK
* TCB GCC_UNUSED
,
415 drv_sgmode(TERMINAL_CONTROL_BLOCK
* TCB
, bool setFlag
, TTY
* buf
)
423 if (TCB
== 0 || buf
== NULL
)
427 iflag
= buf
->c_iflag
;
428 lflag
= buf
->c_lflag
;
430 GetConsoleMode(TCB
->inp
, &dwFlag
);
433 dwFlag
|= ENABLE_LINE_INPUT
;
435 dwFlag
&= ~ENABLE_LINE_INPUT
;
438 dwFlag
|= ENABLE_ECHO_INPUT
;
440 dwFlag
&= ~ENABLE_ECHO_INPUT
;
443 dwFlag
|= ENABLE_PROCESSED_INPUT
;
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
;
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
)
463 if (dwFlag
& ENABLE_ECHO_INPUT
)
468 if (dwFlag
& ENABLE_PROCESSED_INPUT
)
473 TCB
->term
.Nttyb
.c_iflag
= iflag
;
474 TCB
->term
.Nttyb
.c_lflag
= lflag
;
476 *buf
= TCB
->term
.Nttyb
;
482 drv_mode(TERMINAL_CONTROL_BLOCK
* TCB
, bool progFlag
, bool defFlag
)
485 TERMINAL
*_term
= (TERMINAL
*) TCB
;
491 PropOf(TCB
)->progMode
= progFlag
;
492 SetConsoleActiveScreenBuffer(progFlag
? TCB
->hdl
: TCB
->out
);
494 if (progFlag
) /* prog mode */ {
496 if ((drv_sgmode(TCB
, FALSE
, &(_term
->Nttyb
)) == OK
)) {
497 _term
->Nttyb
.c_oflag
&= ~OFLAGS_TABS
;
501 /* reset_prog_mode */
502 if (drv_sgmode(TCB
, TRUE
, &(_term
->Nttyb
)) == OK
) {
505 _nc_keypad(sp
, TRUE
);
506 NC_BUFFERED(sp
, TRUE
);
511 } else { /* shell mode */
514 if (drv_sgmode(TCB
, FALSE
, &(_term
->Ottyb
)) == OK
) {
518 /* reset_shell_mode */
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
));
532 drv_screen_init(SCREEN
*sp GCC_UNUSED
)
537 drv_wrap(SCREEN
*sp GCC_UNUSED
)
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));
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));
560 MapKey(TERMINAL_CONTROL_BLOCK
* TCB
, WORD vKey
)
564 LONG key
= GenMap(vKey
, 0);
571 (size_t) (N_INI
+ FKEYS
),
575 key
= *((LONG
*) res
);
577 code
= (int) (nKey
& 0x7fff);
585 drv_release(TERMINAL_CONTROL_BLOCK
* TCB
)
587 T((T_CALLED("win32con::drv_release(%p)"), TCB
));
597 drv_init(TERMINAL_CONTROL_BLOCK
* TCB
)
601 T((T_CALLED("win32con::drv_init(%p)"), TCB
));
606 BOOL b
= AllocConsole();
611 b
= AttachConsole(ATTACH_PARENT_PROCESS
);
613 TCB
->inp
= GetStdHandle(STD_INPUT_HANDLE
);
614 TCB
->out
= GetStdHandle(STD_OUTPUT_HANDLE
);
619 TCB
->hdl
= CreateConsoleScreenBuffer(GENERIC_READ
| GENERIC_WRITE
,
622 CONSOLE_TEXTMODE_BUFFER
,
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
;
647 TCB
->info
.numbuttons
= 1;
650 TCB
->info
.defaultPalette
= _nc_cga_palette
;
652 for (i
= 0; i
< (N_INI
+ FKEYS
); i
++) {
654 PropOf(TCB
)->rmap
[i
] = PropOf(TCB
)->map
[i
] = keylist
[i
];
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
,
663 qsort(PropOf(TCB
)->rmap
,
668 a
= MapColor(true, COLOR_WHITE
) | MapColor(false, COLOR_BLACK
);
669 for (i
= 0; i
< NUMPAIRS
; i
++)
670 PropOf(TCB
)->pairs
[i
] = a
;
676 drv_initpair(TERMINAL_CONTROL_BLOCK
* TCB
,
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
);
693 drv_initcolor(TERMINAL_CONTROL_BLOCK
* TCB
,
694 short color GCC_UNUSED
,
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
720 drv_initmouse(TERMINAL_CONTROL_BLOCK
* TCB
)
727 sp
->_mouse_type
= M_TERM_DRIVER
;
731 drv_testmouse(TERMINAL_CONTROL_BLOCK
* TCB
, int delay
)
739 if (sp
->_drv_mouse_head
< sp
->_drv_mouse_tail
) {
742 rc
= TCBOf(sp
)->drv
->twait(TCBOf(sp
),
753 drv_mvcur(TERMINAL_CONTROL_BLOCK
* TCB
,
754 int yold GCC_UNUSED
, int xold GCC_UNUSED
,
758 if (TCB
&& !InvalidConsoleHandle(TCB
->hdl
)) {
762 SetConsoleCursorPosition(TCB
->hdl
, loc
);
769 drv_hwlabel(TERMINAL_CONTROL_BLOCK
* TCB
,
770 int labnum GCC_UNUSED
,
771 char *text GCC_UNUSED
)
780 drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK
* TCB
,
781 bool OnFlag GCC_UNUSED
)
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
);
798 drv_setfilter(TERMINAL_CONTROL_BLOCK
* TCB
)
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 }
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 */
846 for (n
= 0; n
< SIZEOF(table
); ++n
) {
847 real_map
[table
[n
].acs_code
] = table
[n
].use_code
| A_ALTCHARSET
;
849 sp
->_screen_acs_map
[table
[n
].acs_code
] = TRUE
;
854 tdiff(FILETIME fstart
, FILETIME fend
)
856 ULARGE_INTEGER ustart
;
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;
870 Adjust(int milliseconds
, int diff
)
872 if (milliseconds
== INFINITY
)
874 milliseconds
-= diff
;
875 if (milliseconds
< 0)
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)
887 decode_mouse(TERMINAL_CONTROL_BLOCK
* TCB
, int mask
)
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
) {
907 result
|= BUTTON1_PRESSED
;
910 result
|= BUTTON2_PRESSED
;
913 result
|= BUTTON3_PRESSED
;
916 result
|= BUTTON4_PRESSED
;
925 drv_twait(TERMINAL_CONTROL_BLOCK
* TCB
,
929 EVENTLIST_2nd(_nc_eventlist
* evl
))
932 INPUT_RECORD inp_rec
;
934 DWORD nRead
= 0, rc
= -1;
939 bool isImmed
= (milliseconds
== 0);
941 #define CONSUME() ReadConsoleInput(TCB->inp,&inp_rec,1,&nRead)
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
));
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)
964 if (rc
== WAIT_OBJECT_0
) {
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
) {
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
) {
978 int nKey
= MapKey(TCB
, vk
);
979 if ((nKey
< 0) || FALSE
== sp
->_keypad_on
) {
992 if (decode_mouse(TCB
,
993 (inp_rec
.Event
.MouseEvent
.dwButtonState
994 & BUTTON_MASK
)) == 0) {
996 } else if (mode
& TW_MOUSE
) {
1002 SetConsoleActiveScreenBuffer(!PropOf(TCB
)->progMode
?
1003 TCB
->hdl
: TCB
->out
);
1011 if (rc
!= WAIT_TIMEOUT
) {
1022 TR(TRACE_IEVENT
, ("end twait: returned %d (%d), remaining time %d msec",
1023 code
, errno
, milliseconds
));
1026 *timeleft
= milliseconds
;
1032 handle_mouse(TERMINAL_CONTROL_BLOCK
* TCB
, MOUSE_EVENT_RECORD mer
)
1036 bool result
= FALSE
;
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
);
1058 /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
1059 work
.bstate
|= (decode_mouse(TCB
, sp
->_drv_mouse_old_buttons
) >> 1);
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;
1075 drv_read(TERMINAL_CONTROL_BLOCK
* TCB
, int *buf
)
1079 INPUT_RECORD inp_rec
;
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
)
1097 *buf
= (int) inp_rec
.Event
.KeyEvent
.uChar
.AsciiChar
;
1098 vk
= inp_rec
.Event
.KeyEvent
.wVirtualKeyCode
;
1099 sc
= inp_rec
.Event
.KeyEvent
.wVirtualScanCode
;
1101 if (sp
->_keypad_on
) {
1102 *buf
= MapKey(TCB
, vk
);
1109 } else { /* *buf != 0 */
1112 } else if (inp_rec
.EventType
== MOUSE_EVENT
) {
1113 if (handle_mouse(TCB
, inp_rec
.Event
.MouseEvent
)) {
1125 drv_nap(TERMINAL_CONTROL_BLOCK
* TCB GCC_UNUSED
, int ms
)
1132 drv_kyExist(TERMINAL_CONTROL_BLOCK
* TCB
, int keycode
)
1138 LONG key
= GenMap(0, (WORD
) keycode
);
1147 (size_t) (N_INI
+ FKEYS
),
1151 key
= *((LONG
*) res
);
1153 if (!(nKey
& 0x8000))
1160 drv_kpad(TERMINAL_CONTROL_BLOCK
* TCB
, bool flag GCC_UNUSED
)
1175 drv_keyok(TERMINAL_CONTROL_BLOCK
* TCB
, int keycode
, bool flag
)
1182 LONG key
= GenMap(0, (WORD
) keycode
);
1190 (size_t) (N_INI
+ FKEYS
),
1194 key
= *((LONG
*) res
);
1196 nKey
= (LOWORD(key
)) & 0x7fff;
1199 *(LONG
*) res
= GenMap(vKey
, nKey
);
1205 NCURSES_EXPORT_VAR (TERM_DRIVER
) _nc_WIN_DRIVER
= {
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 */
1238 drv_kpad
, /* kpad */
1239 drv_keyok
, /* kyOk */
1240 drv_kyExist
/* kyExist */