xref: /openbsd-src/lib/libcurses/tinfo/lib_win32con.c (revision c7ef0cfc17afcba97172c25e1e3a943e893bc632)
1*c7ef0cfcSnicm /****************************************************************************
2*c7ef0cfcSnicm  * Copyright 2020-2021,2023 Thomas E. Dickey                                *
3*c7ef0cfcSnicm  * Copyright 1998-2009,2010 Free Software Foundation, Inc.                  *
4*c7ef0cfcSnicm  *                                                                          *
5*c7ef0cfcSnicm  * Permission is hereby granted, free of charge, to any person obtaining a  *
6*c7ef0cfcSnicm  * copy of this software and associated documentation files (the            *
7*c7ef0cfcSnicm  * "Software"), to deal in the Software without restriction, including      *
8*c7ef0cfcSnicm  * without limitation the rights to use, copy, modify, merge, publish,      *
9*c7ef0cfcSnicm  * distribute, distribute with modifications, sublicense, and/or sell       *
10*c7ef0cfcSnicm  * copies of the Software, and to permit persons to whom the Software is    *
11*c7ef0cfcSnicm  * furnished to do so, subject to the following conditions:                 *
12*c7ef0cfcSnicm  *                                                                          *
13*c7ef0cfcSnicm  * The above copyright notice and this permission notice shall be included  *
14*c7ef0cfcSnicm  * in all copies or substantial portions of the Software.                   *
15*c7ef0cfcSnicm  *                                                                          *
16*c7ef0cfcSnicm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17*c7ef0cfcSnicm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18*c7ef0cfcSnicm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19*c7ef0cfcSnicm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20*c7ef0cfcSnicm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21*c7ef0cfcSnicm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22*c7ef0cfcSnicm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23*c7ef0cfcSnicm  *                                                                          *
24*c7ef0cfcSnicm  * Except as contained in this notice, the name(s) of the above copyright   *
25*c7ef0cfcSnicm  * holders shall not be used in advertising or otherwise to promote the     *
26*c7ef0cfcSnicm  * sale, use or other dealings in this Software without prior written       *
27*c7ef0cfcSnicm  * authorization.                                                           *
28*c7ef0cfcSnicm  ****************************************************************************/
29*c7ef0cfcSnicm 
30*c7ef0cfcSnicm /****************************************************************************
31*c7ef0cfcSnicm  *  Author: Juergen Pfeifer                                                 *
32*c7ef0cfcSnicm  *     and: Thomas E. Dickey                                                *
33*c7ef0cfcSnicm  ****************************************************************************/
34*c7ef0cfcSnicm 
35*c7ef0cfcSnicm /*
36*c7ef0cfcSnicm  * TODO - GetMousePos(POINT * result) from ntconio.c
37*c7ef0cfcSnicm  */
38*c7ef0cfcSnicm 
39*c7ef0cfcSnicm #include <curses.priv.h>
40*c7ef0cfcSnicm 
41*c7ef0cfcSnicm MODULE_ID("$Id: lib_win32con.c,v 1.1 2023/10/17 09:52:09 nicm Exp $")
42*c7ef0cfcSnicm 
43*c7ef0cfcSnicm #ifdef _NC_WINDOWS
44*c7ef0cfcSnicm 
45*c7ef0cfcSnicm #ifdef _NC_MINGW
46*c7ef0cfcSnicm #include <wchar.h>
47*c7ef0cfcSnicm #else
48*c7ef0cfcSnicm #include <tchar.h>
49*c7ef0cfcSnicm #endif
50*c7ef0cfcSnicm 
51*c7ef0cfcSnicm #include <io.h>
52*c7ef0cfcSnicm 
53*c7ef0cfcSnicm #if USE_WIDEC_SUPPORT
54*c7ef0cfcSnicm #define write_screen WriteConsoleOutputW
55*c7ef0cfcSnicm #define read_screen  ReadConsoleOutputW
56*c7ef0cfcSnicm #else
57*c7ef0cfcSnicm #define write_screen WriteConsoleOutput
58*c7ef0cfcSnicm #define read_screen  ReadConsoleOutput
59*c7ef0cfcSnicm #endif
60*c7ef0cfcSnicm 
61*c7ef0cfcSnicm static bool read_screen_data(void);
62*c7ef0cfcSnicm 
63*c7ef0cfcSnicm #define GenMap(vKey,key) MAKELONG(key, vKey)
64*c7ef0cfcSnicm static const LONG keylist[] =
65*c7ef0cfcSnicm {
66*c7ef0cfcSnicm     GenMap(VK_PRIOR, KEY_PPAGE),
67*c7ef0cfcSnicm     GenMap(VK_NEXT, KEY_NPAGE),
68*c7ef0cfcSnicm     GenMap(VK_END, KEY_END),
69*c7ef0cfcSnicm     GenMap(VK_HOME, KEY_HOME),
70*c7ef0cfcSnicm     GenMap(VK_LEFT, KEY_LEFT),
71*c7ef0cfcSnicm     GenMap(VK_UP, KEY_UP),
72*c7ef0cfcSnicm     GenMap(VK_RIGHT, KEY_RIGHT),
73*c7ef0cfcSnicm     GenMap(VK_DOWN, KEY_DOWN),
74*c7ef0cfcSnicm     GenMap(VK_DELETE, KEY_DC),
75*c7ef0cfcSnicm     GenMap(VK_INSERT, KEY_IC)
76*c7ef0cfcSnicm };
77*c7ef0cfcSnicm static const LONG ansi_keys[] =
78*c7ef0cfcSnicm {
79*c7ef0cfcSnicm     GenMap(VK_PRIOR, 'I'),
80*c7ef0cfcSnicm     GenMap(VK_NEXT, 'Q'),
81*c7ef0cfcSnicm     GenMap(VK_END, 'O'),
82*c7ef0cfcSnicm     GenMap(VK_HOME, 'H'),
83*c7ef0cfcSnicm     GenMap(VK_LEFT, 'K'),
84*c7ef0cfcSnicm     GenMap(VK_UP, 'H'),
85*c7ef0cfcSnicm     GenMap(VK_RIGHT, 'M'),
86*c7ef0cfcSnicm     GenMap(VK_DOWN, 'P'),
87*c7ef0cfcSnicm     GenMap(VK_DELETE, 'S'),
88*c7ef0cfcSnicm     GenMap(VK_INSERT, 'R')
89*c7ef0cfcSnicm };
90*c7ef0cfcSnicm #define array_length(a) (sizeof(a)/sizeof(a[0]))
91*c7ef0cfcSnicm #define N_INI ((int)array_length(keylist))
92*c7ef0cfcSnicm #define FKEYS 24
93*c7ef0cfcSnicm #define MAPSIZE (FKEYS + N_INI)
94*c7ef0cfcSnicm 
95*c7ef0cfcSnicm /*   A process can only have a single console, so it is safe
96*c7ef0cfcSnicm      to maintain all the information about it in a single
97*c7ef0cfcSnicm      static structure.
98*c7ef0cfcSnicm  */
99*c7ef0cfcSnicm NCURSES_EXPORT_VAR(ConsoleInfo) _nc_CONSOLE;
100*c7ef0cfcSnicm static bool console_initialized = FALSE;
101*c7ef0cfcSnicm 
102*c7ef0cfcSnicm #define EnsureInit() (void)(console_initialized ? TRUE : _nc_console_checkinit(TRUE, TRUE))
103*c7ef0cfcSnicm 
104*c7ef0cfcSnicm #define REQUIRED_MAX_V (DWORD)10
105*c7ef0cfcSnicm #define REQUIRED_MIN_V (DWORD)0
106*c7ef0cfcSnicm #define REQUIRED_BUILD (DWORD)17763
107*c7ef0cfcSnicm /*
108*c7ef0cfcSnicm   This function returns 0 if the Windows version has no support for
109*c7ef0cfcSnicm   the modern Console interface, otherwise it returns 1
110*c7ef0cfcSnicm  */
111*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_vt_supported(void)112*c7ef0cfcSnicm _nc_console_vt_supported(void)
113*c7ef0cfcSnicm {
114*c7ef0cfcSnicm     OSVERSIONINFO osvi;
115*c7ef0cfcSnicm     int res = 0;
116*c7ef0cfcSnicm 
117*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_vt_supported")));
118*c7ef0cfcSnicm     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
119*c7ef0cfcSnicm     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
120*c7ef0cfcSnicm 
121*c7ef0cfcSnicm     GetVersionEx(&osvi);
122*c7ef0cfcSnicm     T(("GetVersionEx returnedMajor=%ld, Minor=%ld, Build=%ld",
123*c7ef0cfcSnicm        osvi.dwMajorVersion,
124*c7ef0cfcSnicm        osvi.dwMinorVersion,
125*c7ef0cfcSnicm        osvi.dwBuildNumber));
126*c7ef0cfcSnicm     if (osvi.dwMajorVersion >= REQUIRED_MAX_V) {
127*c7ef0cfcSnicm 	if (osvi.dwMajorVersion == REQUIRED_MAX_V) {
128*c7ef0cfcSnicm 	    if (((osvi.dwMinorVersion == REQUIRED_MIN_V) &&
129*c7ef0cfcSnicm 		 (osvi.dwBuildNumber >= REQUIRED_BUILD)) ||
130*c7ef0cfcSnicm 		((osvi.dwMinorVersion > REQUIRED_MIN_V)))
131*c7ef0cfcSnicm 		res = 1;
132*c7ef0cfcSnicm 	} else
133*c7ef0cfcSnicm 	    res = 1;
134*c7ef0cfcSnicm     }
135*c7ef0cfcSnicm     returnCode(res);
136*c7ef0cfcSnicm }
137*c7ef0cfcSnicm 
138*c7ef0cfcSnicm NCURSES_EXPORT(void)
_nc_console_size(int * Lines,int * Cols)139*c7ef0cfcSnicm _nc_console_size(int *Lines, int *Cols)
140*c7ef0cfcSnicm {
141*c7ef0cfcSnicm     EnsureInit();
142*c7ef0cfcSnicm     if (Lines != NULL && Cols != NULL) {
143*c7ef0cfcSnicm 	if (WINCONSOLE.buffered) {
144*c7ef0cfcSnicm 	    *Lines = (int) (WINCONSOLE.SBI.dwSize.Y);
145*c7ef0cfcSnicm 	    *Cols = (int) (WINCONSOLE.SBI.dwSize.X);
146*c7ef0cfcSnicm 	} else {
147*c7ef0cfcSnicm 	    *Lines = (int) (WINCONSOLE.SBI.srWindow.Bottom + 1 -
148*c7ef0cfcSnicm 			    WINCONSOLE.SBI.srWindow.Top);
149*c7ef0cfcSnicm 	    *Cols = (int) (WINCONSOLE.SBI.srWindow.Right + 1 -
150*c7ef0cfcSnicm 			   WINCONSOLE.SBI.srWindow.Left);
151*c7ef0cfcSnicm 	}
152*c7ef0cfcSnicm     }
153*c7ef0cfcSnicm }
154*c7ef0cfcSnicm 
155*c7ef0cfcSnicm /* Convert a file descriptor into a HANDLE
156*c7ef0cfcSnicm    That's not necessarily a console HANDLE
157*c7ef0cfcSnicm */
158*c7ef0cfcSnicm NCURSES_EXPORT(HANDLE)
_nc_console_handle(int fd)159*c7ef0cfcSnicm _nc_console_handle(int fd)
160*c7ef0cfcSnicm {
161*c7ef0cfcSnicm     intptr_t value = _get_osfhandle(fd);
162*c7ef0cfcSnicm     return (HANDLE) value;
163*c7ef0cfcSnicm }
164*c7ef0cfcSnicm 
165*c7ef0cfcSnicm /* Validate that a HANDLE is actually a
166*c7ef0cfcSnicm    console HANDLE
167*c7ef0cfcSnicm */
168*c7ef0cfcSnicm static BOOL
IsConsoleHandle(HANDLE hdl)169*c7ef0cfcSnicm IsConsoleHandle(HANDLE hdl)
170*c7ef0cfcSnicm {
171*c7ef0cfcSnicm     DWORD dwFlag = 0;
172*c7ef0cfcSnicm     BOOL result = FALSE;
173*c7ef0cfcSnicm 
174*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::IsConsoleHandle(HANDLE=%p"), hdl));
175*c7ef0cfcSnicm 
176*c7ef0cfcSnicm     EnsureInit();
177*c7ef0cfcSnicm 
178*c7ef0cfcSnicm     if (!GetConsoleMode(hdl, &dwFlag)) {
179*c7ef0cfcSnicm 	T(("GetConsoleMode failed"));
180*c7ef0cfcSnicm     } else {
181*c7ef0cfcSnicm 	result = TRUE;
182*c7ef0cfcSnicm     }
183*c7ef0cfcSnicm 
184*c7ef0cfcSnicm     returnBool(result);
185*c7ef0cfcSnicm }
186*c7ef0cfcSnicm 
187*c7ef0cfcSnicm /*   This is used when running in terminfo mode to discover,
188*c7ef0cfcSnicm      whether or not the "terminal" is actually a Windows
189*c7ef0cfcSnicm      Console. It is the responsibility of the console to deal
190*c7ef0cfcSnicm      with the terminal escape sequences that are sent by
191*c7ef0cfcSnicm      terminfo.
192*c7ef0cfcSnicm  */
193*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_test(int fd)194*c7ef0cfcSnicm _nc_console_test(int fd)
195*c7ef0cfcSnicm {
196*c7ef0cfcSnicm     int code = 0;
197*c7ef0cfcSnicm     HANDLE hdl = INVALID_HANDLE_VALUE;
198*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_test(%d)"), fd));
199*c7ef0cfcSnicm     hdl = _nc_console_handle(fd);
200*c7ef0cfcSnicm     code = (int) IsConsoleHandle(hdl);
201*c7ef0cfcSnicm     returnCode(code);
202*c7ef0cfcSnicm }
203*c7ef0cfcSnicm 
204*c7ef0cfcSnicm #define OutHandle() ((WINCONSOLE.isTermInfoConsole || WINCONSOLE.progMode) ? WINCONSOLE.hdl : WINCONSOLE.out)
205*c7ef0cfcSnicm 
206*c7ef0cfcSnicm NCURSES_EXPORT(void)
_nc_console_selectActiveHandle(void)207*c7ef0cfcSnicm _nc_console_selectActiveHandle(void)
208*c7ef0cfcSnicm {
209*c7ef0cfcSnicm     if (WINCONSOLE.lastOut != WINCONSOLE.hdl) {
210*c7ef0cfcSnicm 	WINCONSOLE.lastOut = WINCONSOLE.hdl;
211*c7ef0cfcSnicm 	SetConsoleActiveScreenBuffer(WINCONSOLE.lastOut);
212*c7ef0cfcSnicm     }
213*c7ef0cfcSnicm }
214*c7ef0cfcSnicm 
215*c7ef0cfcSnicm NCURSES_EXPORT(HANDLE)
_nc_console_fd2handle(int fd)216*c7ef0cfcSnicm _nc_console_fd2handle(int fd)
217*c7ef0cfcSnicm {
218*c7ef0cfcSnicm     HANDLE hdl = _nc_console_handle(fd);
219*c7ef0cfcSnicm     if (hdl == WINCONSOLE.inp) {
220*c7ef0cfcSnicm 	T(("lib_win32con:validateHandle %d -> WINCONSOLE.inp", fd));
221*c7ef0cfcSnicm     } else if (hdl == WINCONSOLE.hdl) {
222*c7ef0cfcSnicm 	T(("lib_win32con:validateHandle %d -> WINCONSOLE.hdl", fd));
223*c7ef0cfcSnicm     } else if (hdl == WINCONSOLE.out) {
224*c7ef0cfcSnicm 	T(("lib_win32con:validateHandle %d -> WINCONSOLE.out", fd));
225*c7ef0cfcSnicm     } else {
226*c7ef0cfcSnicm 	T(("lib_win32con:validateHandle %d maps to unknown HANDLE", fd));
227*c7ef0cfcSnicm 	hdl = INVALID_HANDLE_VALUE;
228*c7ef0cfcSnicm     }
229*c7ef0cfcSnicm #if 1
230*c7ef0cfcSnicm     assert(hdl != INVALID_HANDLE_VALUE);
231*c7ef0cfcSnicm #endif
232*c7ef0cfcSnicm     if (hdl != INVALID_HANDLE_VALUE) {
233*c7ef0cfcSnicm 	if (hdl != WINCONSOLE.inp && (!WINCONSOLE.isTermInfoConsole && WINCONSOLE.progMode)) {
234*c7ef0cfcSnicm 	    if (hdl == WINCONSOLE.out && hdl != WINCONSOLE.hdl) {
235*c7ef0cfcSnicm 		T(("lib_win32con:validateHandle forcing WINCONSOLE.out -> WINCONSOLE.hdl"));
236*c7ef0cfcSnicm 		hdl = WINCONSOLE.hdl;
237*c7ef0cfcSnicm 	    }
238*c7ef0cfcSnicm 	}
239*c7ef0cfcSnicm     }
240*c7ef0cfcSnicm     return hdl;
241*c7ef0cfcSnicm }
242*c7ef0cfcSnicm 
243*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_setmode(HANDLE hdl,const TTY * arg)244*c7ef0cfcSnicm _nc_console_setmode(HANDLE hdl, const TTY * arg)
245*c7ef0cfcSnicm {
246*c7ef0cfcSnicm     DWORD dwFlag = 0;
247*c7ef0cfcSnicm     int code = ERR;
248*c7ef0cfcSnicm     HANDLE alt;
249*c7ef0cfcSnicm 
250*c7ef0cfcSnicm     if (arg) {
251*c7ef0cfcSnicm #ifdef TRACE
252*c7ef0cfcSnicm 	TTY TRCTTY;
253*c7ef0cfcSnicm #define TRCTTYOUT(flag) TRCTTY.dwFlagOut = flag
254*c7ef0cfcSnicm #define TRCTTYIN(flag)  TRCTTY.dwFlagIn = flag
255*c7ef0cfcSnicm #else
256*c7ef0cfcSnicm #define TRCTTYOUT(flag)
257*c7ef0cfcSnicm #define TRCTTYIN(flag)
258*c7ef0cfcSnicm #endif
259*c7ef0cfcSnicm 	T(("lib_win32con:_nc_console_setmode %s", _nc_trace_ttymode(arg)));
260*c7ef0cfcSnicm 	if (hdl == WINCONSOLE.inp) {
261*c7ef0cfcSnicm 	    dwFlag = arg->dwFlagIn | ENABLE_MOUSE_INPUT | VT_FLAG_IN;
262*c7ef0cfcSnicm 	    if (WINCONSOLE.isTermInfoConsole)
263*c7ef0cfcSnicm 		dwFlag |= (VT_FLAG_IN);
264*c7ef0cfcSnicm 	    else
265*c7ef0cfcSnicm 		dwFlag &= (DWORD) ~ (VT_FLAG_IN);
266*c7ef0cfcSnicm 	    TRCTTYIN(dwFlag);
267*c7ef0cfcSnicm 	    SetConsoleMode(hdl, dwFlag);
268*c7ef0cfcSnicm 
269*c7ef0cfcSnicm 	    alt = OutHandle();
270*c7ef0cfcSnicm 	    dwFlag = arg->dwFlagOut;
271*c7ef0cfcSnicm 	    if (WINCONSOLE.isTermInfoConsole)
272*c7ef0cfcSnicm 		dwFlag |= (VT_FLAG_OUT);
273*c7ef0cfcSnicm 	    else
274*c7ef0cfcSnicm 		dwFlag |= (VT_FLAG_OUT);
275*c7ef0cfcSnicm 	    TRCTTYOUT(dwFlag);
276*c7ef0cfcSnicm 	    SetConsoleMode(alt, dwFlag);
277*c7ef0cfcSnicm 	} else {
278*c7ef0cfcSnicm 	    dwFlag = arg->dwFlagOut;
279*c7ef0cfcSnicm 	    if (WINCONSOLE.isTermInfoConsole)
280*c7ef0cfcSnicm 		dwFlag |= (VT_FLAG_OUT);
281*c7ef0cfcSnicm 	    else
282*c7ef0cfcSnicm 		dwFlag |= (VT_FLAG_OUT);
283*c7ef0cfcSnicm 	    TRCTTYOUT(dwFlag);
284*c7ef0cfcSnicm 	    SetConsoleMode(hdl, dwFlag);
285*c7ef0cfcSnicm 
286*c7ef0cfcSnicm 	    alt = WINCONSOLE.inp;
287*c7ef0cfcSnicm 	    dwFlag = arg->dwFlagIn | ENABLE_MOUSE_INPUT;
288*c7ef0cfcSnicm 	    if (WINCONSOLE.isTermInfoConsole)
289*c7ef0cfcSnicm 		dwFlag |= (VT_FLAG_IN);
290*c7ef0cfcSnicm 	    else
291*c7ef0cfcSnicm 		dwFlag &= (DWORD) ~ (VT_FLAG_IN);
292*c7ef0cfcSnicm 	    TRCTTYIN(dwFlag);
293*c7ef0cfcSnicm 	    SetConsoleMode(alt, dwFlag);
294*c7ef0cfcSnicm 	    T(("effective mode set %s", _nc_trace_ttymode(&TRCTTY)));
295*c7ef0cfcSnicm 	}
296*c7ef0cfcSnicm 	code = OK;
297*c7ef0cfcSnicm     }
298*c7ef0cfcSnicm     return (code);
299*c7ef0cfcSnicm }
300*c7ef0cfcSnicm 
301*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_getmode(HANDLE hdl,TTY * arg)302*c7ef0cfcSnicm _nc_console_getmode(HANDLE hdl, TTY * arg)
303*c7ef0cfcSnicm {
304*c7ef0cfcSnicm     int code = ERR;
305*c7ef0cfcSnicm 
306*c7ef0cfcSnicm     if (arg) {
307*c7ef0cfcSnicm 	DWORD dwFlag = 0;
308*c7ef0cfcSnicm 	HANDLE alt;
309*c7ef0cfcSnicm 
310*c7ef0cfcSnicm 	if (hdl == WINCONSOLE.inp) {
311*c7ef0cfcSnicm 	    if (GetConsoleMode(hdl, &dwFlag)) {
312*c7ef0cfcSnicm 		arg->dwFlagIn = dwFlag;
313*c7ef0cfcSnicm 		alt = OutHandle();
314*c7ef0cfcSnicm 		if (GetConsoleMode(alt, &dwFlag)) {
315*c7ef0cfcSnicm 		    arg->dwFlagOut = dwFlag;
316*c7ef0cfcSnicm 		    code = OK;
317*c7ef0cfcSnicm 		}
318*c7ef0cfcSnicm 	    }
319*c7ef0cfcSnicm 	} else {
320*c7ef0cfcSnicm 	    if (GetConsoleMode(hdl, &dwFlag)) {
321*c7ef0cfcSnicm 		arg->dwFlagOut = dwFlag;
322*c7ef0cfcSnicm 		alt = WINCONSOLE.inp;
323*c7ef0cfcSnicm 		if (GetConsoleMode(alt, &dwFlag)) {
324*c7ef0cfcSnicm 		    arg->dwFlagIn = dwFlag;
325*c7ef0cfcSnicm 		    code = OK;
326*c7ef0cfcSnicm 		}
327*c7ef0cfcSnicm 	    }
328*c7ef0cfcSnicm 	}
329*c7ef0cfcSnicm     }
330*c7ef0cfcSnicm     T(("lib_win32con:_nc_console_getmode %s", _nc_trace_ttymode(arg)));
331*c7ef0cfcSnicm     return (code);
332*c7ef0cfcSnicm }
333*c7ef0cfcSnicm 
334*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_flush(HANDLE hdl)335*c7ef0cfcSnicm _nc_console_flush(HANDLE hdl)
336*c7ef0cfcSnicm {
337*c7ef0cfcSnicm     int code = OK;
338*c7ef0cfcSnicm 
339*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_flush(hdl=%p"), hdl));
340*c7ef0cfcSnicm 
341*c7ef0cfcSnicm     if (hdl != INVALID_HANDLE_VALUE) {
342*c7ef0cfcSnicm 	if (hdl == WINCONSOLE.hdl ||
343*c7ef0cfcSnicm 	    hdl == WINCONSOLE.inp ||
344*c7ef0cfcSnicm 	    hdl == WINCONSOLE.out) {
345*c7ef0cfcSnicm 	    if (!FlushConsoleInputBuffer(WINCONSOLE.inp))
346*c7ef0cfcSnicm 		code = ERR;
347*c7ef0cfcSnicm 	} else {
348*c7ef0cfcSnicm 	    code = ERR;
349*c7ef0cfcSnicm 	    T(("_nc_console_flush not requesting a handle owned by console."));
350*c7ef0cfcSnicm 	}
351*c7ef0cfcSnicm     }
352*c7ef0cfcSnicm     returnCode(code);
353*c7ef0cfcSnicm }
354*c7ef0cfcSnicm 
355*c7ef0cfcSnicm NCURSES_EXPORT(WORD)
_nc_console_MapColor(bool fore,int color)356*c7ef0cfcSnicm _nc_console_MapColor(bool fore, int color)
357*c7ef0cfcSnicm {
358*c7ef0cfcSnicm     static const int _cmap[] =
359*c7ef0cfcSnicm     {0, 4, 2, 6, 1, 5, 3, 7};
360*c7ef0cfcSnicm     int a;
361*c7ef0cfcSnicm     if (color < 0 || color > 7)
362*c7ef0cfcSnicm 	a = fore ? 7 : 0;
363*c7ef0cfcSnicm     else
364*c7ef0cfcSnicm 	a = _cmap[color];
365*c7ef0cfcSnicm     if (!fore)
366*c7ef0cfcSnicm 	a = a << 4;
367*c7ef0cfcSnicm     return (WORD) a;
368*c7ef0cfcSnicm }
369*c7ef0cfcSnicm 
370*c7ef0cfcSnicm /*
371*c7ef0cfcSnicm  * Attempt to save the screen contents.  PDCurses does this if
372*c7ef0cfcSnicm  * PDC_RESTORE_SCREEN is set, giving the same visual appearance on
373*c7ef0cfcSnicm  * restoration as if the library had allocated a console buffer.  MSDN
374*c7ef0cfcSnicm  * says that the data which can be read is limited to 64Kb (and may be
375*c7ef0cfcSnicm  * less).
376*c7ef0cfcSnicm  */
377*c7ef0cfcSnicm static bool
save_original_screen(void)378*c7ef0cfcSnicm save_original_screen(void)
379*c7ef0cfcSnicm {
380*c7ef0cfcSnicm     bool result = FALSE;
381*c7ef0cfcSnicm 
382*c7ef0cfcSnicm     WINCONSOLE.save_region.Top = 0;
383*c7ef0cfcSnicm     WINCONSOLE.save_region.Left = 0;
384*c7ef0cfcSnicm     WINCONSOLE.save_region.Bottom = (SHORT) (WINCONSOLE.SBI.dwSize.Y - 1);
385*c7ef0cfcSnicm     WINCONSOLE.save_region.Right = (SHORT) (WINCONSOLE.SBI.dwSize.X - 1);
386*c7ef0cfcSnicm 
387*c7ef0cfcSnicm     if (read_screen_data()) {
388*c7ef0cfcSnicm 	result = TRUE;
389*c7ef0cfcSnicm     } else {
390*c7ef0cfcSnicm 
391*c7ef0cfcSnicm 	WINCONSOLE.save_region.Top = WINCONSOLE.SBI.srWindow.Top;
392*c7ef0cfcSnicm 	WINCONSOLE.save_region.Left = WINCONSOLE.SBI.srWindow.Left;
393*c7ef0cfcSnicm 	WINCONSOLE.save_region.Bottom = WINCONSOLE.SBI.srWindow.Bottom;
394*c7ef0cfcSnicm 	WINCONSOLE.save_region.Right = WINCONSOLE.SBI.srWindow.Right;
395*c7ef0cfcSnicm 
396*c7ef0cfcSnicm 	WINCONSOLE.window_only = TRUE;
397*c7ef0cfcSnicm 
398*c7ef0cfcSnicm 	if (read_screen_data()) {
399*c7ef0cfcSnicm 	    result = TRUE;
400*c7ef0cfcSnicm 	}
401*c7ef0cfcSnicm     }
402*c7ef0cfcSnicm 
403*c7ef0cfcSnicm     T(("... save original screen contents %s", result ? "ok" : "err"));
404*c7ef0cfcSnicm     return result;
405*c7ef0cfcSnicm }
406*c7ef0cfcSnicm 
407*c7ef0cfcSnicm #if 0
408*c7ef0cfcSnicm static bool
409*c7ef0cfcSnicm restore_original_screen(void)
410*c7ef0cfcSnicm {
411*c7ef0cfcSnicm     COORD bufferCoord;
412*c7ef0cfcSnicm     bool result = FALSE;
413*c7ef0cfcSnicm     SMALL_RECT save_region = WINCONSOLE.save_region;
414*c7ef0cfcSnicm 
415*c7ef0cfcSnicm     T(("... restoring %s",
416*c7ef0cfcSnicm        WINCONSOLE.window_only ? "window" : "entire buffer"));
417*c7ef0cfcSnicm 
418*c7ef0cfcSnicm     bufferCoord.X = (SHORT) (WINCONSOLE.window_only ?
419*c7ef0cfcSnicm 			     WINCONSOLE.SBI.srWindow.Left : 0);
420*c7ef0cfcSnicm     bufferCoord.Y = (SHORT) (WINCONSOLE.window_only ?
421*c7ef0cfcSnicm 			     WINCONSOLE.SBI.srWindow.Top : 0);
422*c7ef0cfcSnicm 
423*c7ef0cfcSnicm     if (write_screen(WINCONSOLE.hdl,
424*c7ef0cfcSnicm 		     WINCONSOLE.save_screen,
425*c7ef0cfcSnicm 		     WINCONSOLE.save_size,
426*c7ef0cfcSnicm 		     bufferCoord,
427*c7ef0cfcSnicm 		     &save_region)) {
428*c7ef0cfcSnicm 	result = TRUE;
429*c7ef0cfcSnicm 	mvcur(-1, -1, LINES - 2, 0);
430*c7ef0cfcSnicm 	T(("... restore original screen contents ok %dx%d (%d,%d - %d,%d)",
431*c7ef0cfcSnicm 	   WINCONSOLE.save_size.Y,
432*c7ef0cfcSnicm 	   WINCONSOLE.save_size.X,
433*c7ef0cfcSnicm 	   save_region.Top,
434*c7ef0cfcSnicm 	   save_region.Left,
435*c7ef0cfcSnicm 	   save_region.Bottom,
436*c7ef0cfcSnicm 	   save_region.Right));
437*c7ef0cfcSnicm     } else {
438*c7ef0cfcSnicm 	T(("... restore original screen contents err"));
439*c7ef0cfcSnicm     }
440*c7ef0cfcSnicm     return result;
441*c7ef0cfcSnicm }
442*c7ef0cfcSnicm #endif
443*c7ef0cfcSnicm 
444*c7ef0cfcSnicm static bool
read_screen_data(void)445*c7ef0cfcSnicm read_screen_data(void)
446*c7ef0cfcSnicm {
447*c7ef0cfcSnicm     bool result = FALSE;
448*c7ef0cfcSnicm     COORD bufferCoord;
449*c7ef0cfcSnicm     size_t want;
450*c7ef0cfcSnicm 
451*c7ef0cfcSnicm     WINCONSOLE.save_size.X = (SHORT) (WINCONSOLE.save_region.Right
452*c7ef0cfcSnicm 				      - WINCONSOLE.save_region.Left + 1);
453*c7ef0cfcSnicm     WINCONSOLE.save_size.Y = (SHORT) (WINCONSOLE.save_region.Bottom
454*c7ef0cfcSnicm 				      - WINCONSOLE.save_region.Top + 1);
455*c7ef0cfcSnicm 
456*c7ef0cfcSnicm     want = (size_t) (WINCONSOLE.save_size.X * WINCONSOLE.save_size.Y);
457*c7ef0cfcSnicm 
458*c7ef0cfcSnicm     if ((WINCONSOLE.save_screen = malloc(want * sizeof(CHAR_INFO))) != 0) {
459*c7ef0cfcSnicm 	bufferCoord.X = (SHORT) (WINCONSOLE.window_only ?
460*c7ef0cfcSnicm 				 WINCONSOLE.SBI.srWindow.Left : 0);
461*c7ef0cfcSnicm 	bufferCoord.Y = (SHORT) (WINCONSOLE.window_only ?
462*c7ef0cfcSnicm 				 WINCONSOLE.SBI.srWindow.Top : 0);
463*c7ef0cfcSnicm 
464*c7ef0cfcSnicm 	T(("... reading console %s %dx%d into %d,%d - %d,%d at %d,%d",
465*c7ef0cfcSnicm 	   WINCONSOLE.window_only ? "window" : "buffer",
466*c7ef0cfcSnicm 	   WINCONSOLE.save_size.Y, WINCONSOLE.save_size.X,
467*c7ef0cfcSnicm 	   WINCONSOLE.save_region.Top,
468*c7ef0cfcSnicm 	   WINCONSOLE.save_region.Left,
469*c7ef0cfcSnicm 	   WINCONSOLE.save_region.Bottom,
470*c7ef0cfcSnicm 	   WINCONSOLE.save_region.Right,
471*c7ef0cfcSnicm 	   bufferCoord.Y,
472*c7ef0cfcSnicm 	   bufferCoord.X));
473*c7ef0cfcSnicm 
474*c7ef0cfcSnicm 	if (read_screen(WINCONSOLE.hdl,
475*c7ef0cfcSnicm 			WINCONSOLE.save_screen,
476*c7ef0cfcSnicm 			WINCONSOLE.save_size,
477*c7ef0cfcSnicm 			bufferCoord,
478*c7ef0cfcSnicm 			&WINCONSOLE.save_region)) {
479*c7ef0cfcSnicm 	    result = TRUE;
480*c7ef0cfcSnicm 	} else {
481*c7ef0cfcSnicm 	    T((" error %#lx", (unsigned long) GetLastError()));
482*c7ef0cfcSnicm 	    FreeAndNull(WINCONSOLE.save_screen);
483*c7ef0cfcSnicm 	}
484*c7ef0cfcSnicm     }
485*c7ef0cfcSnicm 
486*c7ef0cfcSnicm     return result;
487*c7ef0cfcSnicm }
488*c7ef0cfcSnicm 
489*c7ef0cfcSnicm NCURSES_EXPORT(bool)
_nc_console_get_SBI(void)490*c7ef0cfcSnicm _nc_console_get_SBI(void)
491*c7ef0cfcSnicm {
492*c7ef0cfcSnicm     bool rc = FALSE;
493*c7ef0cfcSnicm     if (GetConsoleScreenBufferInfo(WINCONSOLE.hdl, &(WINCONSOLE.SBI))) {
494*c7ef0cfcSnicm 	T(("GetConsoleScreenBufferInfo"));
495*c7ef0cfcSnicm 	T(("... buffer(X:%d Y:%d)",
496*c7ef0cfcSnicm 	   WINCONSOLE.SBI.dwSize.X,
497*c7ef0cfcSnicm 	   WINCONSOLE.SBI.dwSize.Y));
498*c7ef0cfcSnicm 	T(("... window(X:%d Y:%d)",
499*c7ef0cfcSnicm 	   WINCONSOLE.SBI.dwMaximumWindowSize.X,
500*c7ef0cfcSnicm 	   WINCONSOLE.SBI.dwMaximumWindowSize.Y));
501*c7ef0cfcSnicm 	T(("... cursor(X:%d Y:%d)",
502*c7ef0cfcSnicm 	   WINCONSOLE.SBI.dwCursorPosition.X,
503*c7ef0cfcSnicm 	   WINCONSOLE.SBI.dwCursorPosition.Y));
504*c7ef0cfcSnicm 	T(("... display(Top:%d Bottom:%d Left:%d Right:%d)",
505*c7ef0cfcSnicm 	   WINCONSOLE.SBI.srWindow.Top,
506*c7ef0cfcSnicm 	   WINCONSOLE.SBI.srWindow.Bottom,
507*c7ef0cfcSnicm 	   WINCONSOLE.SBI.srWindow.Left,
508*c7ef0cfcSnicm 	   WINCONSOLE.SBI.srWindow.Right));
509*c7ef0cfcSnicm 	if (WINCONSOLE.buffered) {
510*c7ef0cfcSnicm 	    WINCONSOLE.origin.X = 0;
511*c7ef0cfcSnicm 	    WINCONSOLE.origin.Y = 0;
512*c7ef0cfcSnicm 	} else {
513*c7ef0cfcSnicm 	    WINCONSOLE.origin.X = WINCONSOLE.SBI.srWindow.Left;
514*c7ef0cfcSnicm 	    WINCONSOLE.origin.Y = WINCONSOLE.SBI.srWindow.Top;
515*c7ef0cfcSnicm 	}
516*c7ef0cfcSnicm 	rc = TRUE;
517*c7ef0cfcSnicm     } else {
518*c7ef0cfcSnicm 	T(("GetConsoleScreenBufferInfo ERR"));
519*c7ef0cfcSnicm     }
520*c7ef0cfcSnicm     return rc;
521*c7ef0cfcSnicm }
522*c7ef0cfcSnicm 
523*c7ef0cfcSnicm #define MIN_WIDE 80
524*c7ef0cfcSnicm #define MIN_HIGH 24
525*c7ef0cfcSnicm 
526*c7ef0cfcSnicm /*
527*c7ef0cfcSnicm  * In "normal" mode, reset the buffer- and window-sizes back to their original values.
528*c7ef0cfcSnicm  */
529*c7ef0cfcSnicm NCURSES_EXPORT(void)
_nc_console_set_scrollback(bool normal,CONSOLE_SCREEN_BUFFER_INFO * info)530*c7ef0cfcSnicm _nc_console_set_scrollback(bool normal, CONSOLE_SCREEN_BUFFER_INFO * info)
531*c7ef0cfcSnicm {
532*c7ef0cfcSnicm     SMALL_RECT rect;
533*c7ef0cfcSnicm     COORD coord;
534*c7ef0cfcSnicm     bool changed = FALSE;
535*c7ef0cfcSnicm 
536*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_set_scrollback(%s)"),
537*c7ef0cfcSnicm        (normal
538*c7ef0cfcSnicm 	? "normal"
539*c7ef0cfcSnicm 	: "application")));
540*c7ef0cfcSnicm 
541*c7ef0cfcSnicm     T(("... SBI.srWindow %d,%d .. %d,%d",
542*c7ef0cfcSnicm        info->srWindow.Top,
543*c7ef0cfcSnicm        info->srWindow.Left,
544*c7ef0cfcSnicm        info->srWindow.Bottom,
545*c7ef0cfcSnicm        info->srWindow.Right));
546*c7ef0cfcSnicm     T(("... SBI.dwSize %dx%d",
547*c7ef0cfcSnicm        info->dwSize.Y,
548*c7ef0cfcSnicm        info->dwSize.X));
549*c7ef0cfcSnicm 
550*c7ef0cfcSnicm     if (normal) {
551*c7ef0cfcSnicm 	rect = info->srWindow;
552*c7ef0cfcSnicm 	coord = info->dwSize;
553*c7ef0cfcSnicm 	if (memcmp(info, &WINCONSOLE.SBI, sizeof(*info)) != 0) {
554*c7ef0cfcSnicm 	    changed = TRUE;
555*c7ef0cfcSnicm 	    WINCONSOLE.SBI = *info;
556*c7ef0cfcSnicm 	}
557*c7ef0cfcSnicm     } else {
558*c7ef0cfcSnicm 	int high = info->srWindow.Bottom - info->srWindow.Top + 1;
559*c7ef0cfcSnicm 	int wide = info->srWindow.Right - info->srWindow.Left + 1;
560*c7ef0cfcSnicm 
561*c7ef0cfcSnicm 	if (high < MIN_HIGH) {
562*c7ef0cfcSnicm 	    T(("... height %d < %d", high, MIN_HIGH));
563*c7ef0cfcSnicm 	    high = MIN_HIGH;
564*c7ef0cfcSnicm 	    changed = TRUE;
565*c7ef0cfcSnicm 	}
566*c7ef0cfcSnicm 	if (wide < MIN_WIDE) {
567*c7ef0cfcSnicm 	    T(("... width %d < %d", wide, MIN_WIDE));
568*c7ef0cfcSnicm 	    wide = MIN_WIDE;
569*c7ef0cfcSnicm 	    changed = TRUE;
570*c7ef0cfcSnicm 	}
571*c7ef0cfcSnicm 
572*c7ef0cfcSnicm 	rect.Left =
573*c7ef0cfcSnicm 	    rect.Top = 0;
574*c7ef0cfcSnicm 	rect.Right = (SHORT) (wide - 1);
575*c7ef0cfcSnicm 	rect.Bottom = (SHORT) (high - 1);
576*c7ef0cfcSnicm 
577*c7ef0cfcSnicm 	coord.X = (SHORT) wide;
578*c7ef0cfcSnicm 	coord.Y = (SHORT) high;
579*c7ef0cfcSnicm 
580*c7ef0cfcSnicm 	if (info->dwSize.Y != high ||
581*c7ef0cfcSnicm 	    info->dwSize.X != wide ||
582*c7ef0cfcSnicm 	    info->srWindow.Top != 0 ||
583*c7ef0cfcSnicm 	    info->srWindow.Left != 0) {
584*c7ef0cfcSnicm 	    changed = TRUE;
585*c7ef0cfcSnicm 	}
586*c7ef0cfcSnicm 
587*c7ef0cfcSnicm     }
588*c7ef0cfcSnicm 
589*c7ef0cfcSnicm     if (changed) {
590*c7ef0cfcSnicm 	T(("... coord %d,%d", coord.Y, coord.X));
591*c7ef0cfcSnicm 	T(("... rect %d,%d - %d,%d",
592*c7ef0cfcSnicm 	   rect.Top, rect.Left,
593*c7ef0cfcSnicm 	   rect.Bottom, rect.Right));
594*c7ef0cfcSnicm 	SetConsoleScreenBufferSize(WINCONSOLE.hdl, coord);	/* dwSize */
595*c7ef0cfcSnicm 	SetConsoleWindowInfo(WINCONSOLE.hdl, TRUE, &rect);	/* srWindow */
596*c7ef0cfcSnicm 	_nc_console_get_SBI();
597*c7ef0cfcSnicm     }
598*c7ef0cfcSnicm     returnVoid;
599*c7ef0cfcSnicm }
600*c7ef0cfcSnicm 
601*c7ef0cfcSnicm static ULONGLONG
tdiff(FILETIME fstart,FILETIME fend)602*c7ef0cfcSnicm tdiff(FILETIME fstart, FILETIME fend)
603*c7ef0cfcSnicm {
604*c7ef0cfcSnicm     ULARGE_INTEGER ustart;
605*c7ef0cfcSnicm     ULARGE_INTEGER uend;
606*c7ef0cfcSnicm     ULONGLONG diff;
607*c7ef0cfcSnicm 
608*c7ef0cfcSnicm     ustart.LowPart = fstart.dwLowDateTime;
609*c7ef0cfcSnicm     ustart.HighPart = fstart.dwHighDateTime;
610*c7ef0cfcSnicm     uend.LowPart = fend.dwLowDateTime;
611*c7ef0cfcSnicm     uend.HighPart = fend.dwHighDateTime;
612*c7ef0cfcSnicm 
613*c7ef0cfcSnicm     diff = (uend.QuadPart - ustart.QuadPart) / 10000;
614*c7ef0cfcSnicm     return diff;
615*c7ef0cfcSnicm }
616*c7ef0cfcSnicm 
617*c7ef0cfcSnicm static int
Adjust(int milliseconds,int diff)618*c7ef0cfcSnicm Adjust(int milliseconds, int diff)
619*c7ef0cfcSnicm {
620*c7ef0cfcSnicm     if (milliseconds != INFINITY) {
621*c7ef0cfcSnicm 	milliseconds -= diff;
622*c7ef0cfcSnicm 	if (milliseconds < 0)
623*c7ef0cfcSnicm 	    milliseconds = 0;
624*c7ef0cfcSnicm     }
625*c7ef0cfcSnicm     return milliseconds;
626*c7ef0cfcSnicm }
627*c7ef0cfcSnicm 
628*c7ef0cfcSnicm #define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \
629*c7ef0cfcSnicm                      FROM_LEFT_2ND_BUTTON_PRESSED | \
630*c7ef0cfcSnicm                      FROM_LEFT_3RD_BUTTON_PRESSED | \
631*c7ef0cfcSnicm                      FROM_LEFT_4TH_BUTTON_PRESSED | \
632*c7ef0cfcSnicm                      RIGHTMOST_BUTTON_PRESSED)
633*c7ef0cfcSnicm 
634*c7ef0cfcSnicm static mmask_t
decode_mouse(SCREEN * sp,int mask)635*c7ef0cfcSnicm decode_mouse(SCREEN *sp, int mask)
636*c7ef0cfcSnicm {
637*c7ef0cfcSnicm     mmask_t result = 0;
638*c7ef0cfcSnicm 
639*c7ef0cfcSnicm     (void) sp;
640*c7ef0cfcSnicm     assert(sp && console_initialized);
641*c7ef0cfcSnicm 
642*c7ef0cfcSnicm     if (mask & FROM_LEFT_1ST_BUTTON_PRESSED)
643*c7ef0cfcSnicm 	result |= BUTTON1_PRESSED;
644*c7ef0cfcSnicm     if (mask & FROM_LEFT_2ND_BUTTON_PRESSED)
645*c7ef0cfcSnicm 	result |= BUTTON2_PRESSED;
646*c7ef0cfcSnicm     if (mask & FROM_LEFT_3RD_BUTTON_PRESSED)
647*c7ef0cfcSnicm 	result |= BUTTON3_PRESSED;
648*c7ef0cfcSnicm     if (mask & FROM_LEFT_4TH_BUTTON_PRESSED)
649*c7ef0cfcSnicm 	result |= BUTTON4_PRESSED;
650*c7ef0cfcSnicm 
651*c7ef0cfcSnicm     if (mask & RIGHTMOST_BUTTON_PRESSED) {
652*c7ef0cfcSnicm 	switch (WINCONSOLE.numButtons) {
653*c7ef0cfcSnicm 	case 1:
654*c7ef0cfcSnicm 	    result |= BUTTON1_PRESSED;
655*c7ef0cfcSnicm 	    break;
656*c7ef0cfcSnicm 	case 2:
657*c7ef0cfcSnicm 	    result |= BUTTON2_PRESSED;
658*c7ef0cfcSnicm 	    break;
659*c7ef0cfcSnicm 	case 3:
660*c7ef0cfcSnicm 	    result |= BUTTON3_PRESSED;
661*c7ef0cfcSnicm 	    break;
662*c7ef0cfcSnicm 	case 4:
663*c7ef0cfcSnicm 	    result |= BUTTON4_PRESSED;
664*c7ef0cfcSnicm 	    break;
665*c7ef0cfcSnicm 	}
666*c7ef0cfcSnicm     }
667*c7ef0cfcSnicm 
668*c7ef0cfcSnicm     return result;
669*c7ef0cfcSnicm }
670*c7ef0cfcSnicm 
671*c7ef0cfcSnicm #define AdjustY() (WINCONSOLE.buffered ? 0 : (int) WINCONSOLE.SBI.srWindow.Top)
672*c7ef0cfcSnicm 
673*c7ef0cfcSnicm static bool
handle_mouse(SCREEN * sp,MOUSE_EVENT_RECORD mer)674*c7ef0cfcSnicm handle_mouse(SCREEN *sp, MOUSE_EVENT_RECORD mer)
675*c7ef0cfcSnicm {
676*c7ef0cfcSnicm     MEVENT work;
677*c7ef0cfcSnicm     bool result = FALSE;
678*c7ef0cfcSnicm 
679*c7ef0cfcSnicm     assert(sp);
680*c7ef0cfcSnicm 
681*c7ef0cfcSnicm     sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons;
682*c7ef0cfcSnicm     sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK;
683*c7ef0cfcSnicm 
684*c7ef0cfcSnicm     /*
685*c7ef0cfcSnicm      * We're only interested if the button is pressed or released.
686*c7ef0cfcSnicm      * FIXME: implement continuous event-tracking.
687*c7ef0cfcSnicm      */
688*c7ef0cfcSnicm     if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) {
689*c7ef0cfcSnicm 	memset(&work, 0, sizeof(work));
690*c7ef0cfcSnicm 
691*c7ef0cfcSnicm 	if (sp->_drv_mouse_new_buttons) {
692*c7ef0cfcSnicm 	    work.bstate |= decode_mouse(sp, sp->_drv_mouse_new_buttons);
693*c7ef0cfcSnicm 	} else {
694*c7ef0cfcSnicm 	    /* cf: BUTTON_PRESSED, BUTTON_RELEASED */
695*c7ef0cfcSnicm 	    work.bstate |= (decode_mouse(sp, sp->_drv_mouse_old_buttons)
696*c7ef0cfcSnicm 			    >> 1);
697*c7ef0cfcSnicm 	    result = TRUE;
698*c7ef0cfcSnicm 	}
699*c7ef0cfcSnicm 
700*c7ef0cfcSnicm 	work.x = mer.dwMousePosition.X;
701*c7ef0cfcSnicm 	work.y = mer.dwMousePosition.Y - AdjustY();
702*c7ef0cfcSnicm 
703*c7ef0cfcSnicm 	sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work;
704*c7ef0cfcSnicm 	sp->_drv_mouse_tail += 1;
705*c7ef0cfcSnicm     }
706*c7ef0cfcSnicm     return result;
707*c7ef0cfcSnicm }
708*c7ef0cfcSnicm 
709*c7ef0cfcSnicm static int
rkeycompare(const void * el1,const void * el2)710*c7ef0cfcSnicm rkeycompare(const void *el1, const void *el2)
711*c7ef0cfcSnicm {
712*c7ef0cfcSnicm     WORD key1 = (LOWORD((*((const LONG *) el1)))) & 0x7fff;
713*c7ef0cfcSnicm     WORD key2 = (LOWORD((*((const LONG *) el2)))) & 0x7fff;
714*c7ef0cfcSnicm 
715*c7ef0cfcSnicm     return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
716*c7ef0cfcSnicm }
717*c7ef0cfcSnicm 
718*c7ef0cfcSnicm static int
keycompare(const void * el1,const void * el2)719*c7ef0cfcSnicm keycompare(const void *el1, const void *el2)
720*c7ef0cfcSnicm {
721*c7ef0cfcSnicm     WORD key1 = HIWORD((*((const LONG *) el1)));
722*c7ef0cfcSnicm     WORD key2 = HIWORD((*((const LONG *) el2)));
723*c7ef0cfcSnicm 
724*c7ef0cfcSnicm     return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1));
725*c7ef0cfcSnicm }
726*c7ef0cfcSnicm 
727*c7ef0cfcSnicm static int
MapKey(WORD vKey)728*c7ef0cfcSnicm MapKey(WORD vKey)
729*c7ef0cfcSnicm {
730*c7ef0cfcSnicm     int code = -1;
731*c7ef0cfcSnicm 
732*c7ef0cfcSnicm     if (!WINCONSOLE.isTermInfoConsole) {
733*c7ef0cfcSnicm 	WORD nKey = 0;
734*c7ef0cfcSnicm 	void *res;
735*c7ef0cfcSnicm 	LONG key = GenMap(vKey, 0);
736*c7ef0cfcSnicm 
737*c7ef0cfcSnicm 	res = bsearch(&key,
738*c7ef0cfcSnicm 		      WINCONSOLE.map,
739*c7ef0cfcSnicm 		      (size_t) (N_INI + FKEYS),
740*c7ef0cfcSnicm 		      sizeof(keylist[0]),
741*c7ef0cfcSnicm 		      keycompare);
742*c7ef0cfcSnicm 	if (res) {
743*c7ef0cfcSnicm 	    key = *((LONG *) res);
744*c7ef0cfcSnicm 	    nKey = LOWORD(key);
745*c7ef0cfcSnicm 	    code = (int) (nKey & 0x7fff);
746*c7ef0cfcSnicm 	    if (nKey & 0x8000)
747*c7ef0cfcSnicm 		code = -code;
748*c7ef0cfcSnicm 	}
749*c7ef0cfcSnicm     }
750*c7ef0cfcSnicm     return code;
751*c7ef0cfcSnicm }
752*c7ef0cfcSnicm 
753*c7ef0cfcSnicm static int
AnsiKey(WORD vKey)754*c7ef0cfcSnicm AnsiKey(WORD vKey)
755*c7ef0cfcSnicm {
756*c7ef0cfcSnicm     int code = -1;
757*c7ef0cfcSnicm 
758*c7ef0cfcSnicm     if (!WINCONSOLE.isTermInfoConsole) {
759*c7ef0cfcSnicm 	WORD nKey = 0;
760*c7ef0cfcSnicm 	void *res;
761*c7ef0cfcSnicm 	LONG key = GenMap(vKey, 0);
762*c7ef0cfcSnicm 
763*c7ef0cfcSnicm 	res = bsearch(&key,
764*c7ef0cfcSnicm 		      WINCONSOLE.ansi_map,
765*c7ef0cfcSnicm 		      (size_t) (N_INI + FKEYS),
766*c7ef0cfcSnicm 		      sizeof(keylist[0]),
767*c7ef0cfcSnicm 		      keycompare);
768*c7ef0cfcSnicm 	if (res) {
769*c7ef0cfcSnicm 	    key = *((LONG *) res);
770*c7ef0cfcSnicm 	    nKey = LOWORD(key);
771*c7ef0cfcSnicm 	    code = (int) (nKey & 0x7fff);
772*c7ef0cfcSnicm 	    if (nKey & 0x8000)
773*c7ef0cfcSnicm 		code = -code;
774*c7ef0cfcSnicm 	}
775*c7ef0cfcSnicm     }
776*c7ef0cfcSnicm     return code;
777*c7ef0cfcSnicm }
778*c7ef0cfcSnicm 
779*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_keyok(int keycode,int flag)780*c7ef0cfcSnicm _nc_console_keyok(int keycode, int flag)
781*c7ef0cfcSnicm {
782*c7ef0cfcSnicm     int code = ERR;
783*c7ef0cfcSnicm     WORD nKey;
784*c7ef0cfcSnicm     WORD vKey;
785*c7ef0cfcSnicm     void *res;
786*c7ef0cfcSnicm     LONG key = GenMap(0, (WORD) keycode);
787*c7ef0cfcSnicm 
788*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_keyok(%d, %d)"), keycode, flag));
789*c7ef0cfcSnicm 
790*c7ef0cfcSnicm     res = bsearch(&key,
791*c7ef0cfcSnicm 		  WINCONSOLE.rmap,
792*c7ef0cfcSnicm 		  (size_t) (N_INI + FKEYS),
793*c7ef0cfcSnicm 		  sizeof(keylist[0]),
794*c7ef0cfcSnicm 		  rkeycompare);
795*c7ef0cfcSnicm     if (res) {
796*c7ef0cfcSnicm 	key = *((LONG *) res);
797*c7ef0cfcSnicm 	vKey = HIWORD(key);
798*c7ef0cfcSnicm 	nKey = (LOWORD(key)) & 0x7fff;
799*c7ef0cfcSnicm 	if (!flag)
800*c7ef0cfcSnicm 	    nKey |= 0x8000;
801*c7ef0cfcSnicm 	*(LONG *) res = GenMap(vKey, nKey);
802*c7ef0cfcSnicm     }
803*c7ef0cfcSnicm     returnCode(code);
804*c7ef0cfcSnicm }
805*c7ef0cfcSnicm 
806*c7ef0cfcSnicm NCURSES_EXPORT(bool)
_nc_console_keyExist(int keycode)807*c7ef0cfcSnicm _nc_console_keyExist(int keycode)
808*c7ef0cfcSnicm {
809*c7ef0cfcSnicm     WORD nKey;
810*c7ef0cfcSnicm     void *res;
811*c7ef0cfcSnicm     bool found = FALSE;
812*c7ef0cfcSnicm     LONG key = GenMap(0, (WORD) keycode);
813*c7ef0cfcSnicm 
814*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_keyExist(%d)"), keycode));
815*c7ef0cfcSnicm     res = bsearch(&key,
816*c7ef0cfcSnicm 		  WINCONSOLE.rmap,
817*c7ef0cfcSnicm 		  (size_t) (N_INI + FKEYS),
818*c7ef0cfcSnicm 		  sizeof(keylist[0]),
819*c7ef0cfcSnicm 		  rkeycompare);
820*c7ef0cfcSnicm     if (res) {
821*c7ef0cfcSnicm 	key = *((LONG *) res);
822*c7ef0cfcSnicm 	nKey = LOWORD(key);
823*c7ef0cfcSnicm 	if (!(nKey & 0x8000))
824*c7ef0cfcSnicm 	    found = TRUE;
825*c7ef0cfcSnicm     }
826*c7ef0cfcSnicm     returnCode(found);
827*c7ef0cfcSnicm }
828*c7ef0cfcSnicm 
829*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_twait(SCREEN * sp,HANDLE hdl,int mode,int milliseconds,int * timeleft EVENTLIST_2nd (_nc_eventlist * evl))830*c7ef0cfcSnicm _nc_console_twait(
831*c7ef0cfcSnicm 		     SCREEN *sp,
832*c7ef0cfcSnicm 		     HANDLE hdl,
833*c7ef0cfcSnicm 		     int mode,
834*c7ef0cfcSnicm 		     int milliseconds,
835*c7ef0cfcSnicm 		     int *timeleft
836*c7ef0cfcSnicm 		     EVENTLIST_2nd(_nc_eventlist * evl))
837*c7ef0cfcSnicm {
838*c7ef0cfcSnicm     INPUT_RECORD inp_rec;
839*c7ef0cfcSnicm     BOOL b;
840*c7ef0cfcSnicm     DWORD nRead = 0, rc = (DWORD) (-1);
841*c7ef0cfcSnicm     int code = 0;
842*c7ef0cfcSnicm     FILETIME fstart;
843*c7ef0cfcSnicm     FILETIME fend;
844*c7ef0cfcSnicm     int diff;
845*c7ef0cfcSnicm     bool isNoDelay = (milliseconds == 0);
846*c7ef0cfcSnicm 
847*c7ef0cfcSnicm #ifdef NCURSES_WGETCH_EVENTS
848*c7ef0cfcSnicm     (void) evl;			/* TODO: implement wgetch-events */
849*c7ef0cfcSnicm #endif
850*c7ef0cfcSnicm 
851*c7ef0cfcSnicm #define IGNORE_CTRL_KEYS (SHIFT_PRESSED|LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED| \
852*c7ef0cfcSnicm                           LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)
853*c7ef0cfcSnicm #define CONSUME() ReadConsoleInput(hdl, &inp_rec, 1, &nRead)
854*c7ef0cfcSnicm 
855*c7ef0cfcSnicm     assert(sp);
856*c7ef0cfcSnicm 
857*c7ef0cfcSnicm     TR(TRACE_IEVENT, ("start twait: hdl=%p, %d milliseconds, mode: %d",
858*c7ef0cfcSnicm 		      hdl, milliseconds, mode));
859*c7ef0cfcSnicm 
860*c7ef0cfcSnicm     if (milliseconds < 0)
861*c7ef0cfcSnicm 	milliseconds = INFINITY;
862*c7ef0cfcSnicm 
863*c7ef0cfcSnicm     memset(&inp_rec, 0, sizeof(inp_rec));
864*c7ef0cfcSnicm 
865*c7ef0cfcSnicm     while (true) {
866*c7ef0cfcSnicm 	if (!isNoDelay) {
867*c7ef0cfcSnicm 	    GetSystemTimeAsFileTime(&fstart);
868*c7ef0cfcSnicm 	    rc = WaitForSingleObject(hdl, (DWORD) milliseconds);
869*c7ef0cfcSnicm 	    GetSystemTimeAsFileTime(&fend);
870*c7ef0cfcSnicm 	    diff = (int) tdiff(fstart, fend);
871*c7ef0cfcSnicm 	    milliseconds = Adjust(milliseconds, diff);
872*c7ef0cfcSnicm 	    if (milliseconds < 0)
873*c7ef0cfcSnicm 		break;
874*c7ef0cfcSnicm 	}
875*c7ef0cfcSnicm 
876*c7ef0cfcSnicm 	if (isNoDelay || (rc == WAIT_OBJECT_0)) {
877*c7ef0cfcSnicm 	    if (mode) {
878*c7ef0cfcSnicm 		nRead = 0;
879*c7ef0cfcSnicm 		b = GetNumberOfConsoleInputEvents(hdl, &nRead);
880*c7ef0cfcSnicm 		if (!b) {
881*c7ef0cfcSnicm 		    T(("twait:err GetNumberOfConsoleInputEvents"));
882*c7ef0cfcSnicm 		}
883*c7ef0cfcSnicm 		if (isNoDelay && b) {
884*c7ef0cfcSnicm 		    T(("twait: Events Available: %ld", nRead));
885*c7ef0cfcSnicm 		    if (nRead == 0) {
886*c7ef0cfcSnicm 			code = 0;
887*c7ef0cfcSnicm 			goto end;
888*c7ef0cfcSnicm 		    } else {
889*c7ef0cfcSnicm 			DWORD n = 0;
890*c7ef0cfcSnicm 			INPUT_RECORD *pInpRec =
891*c7ef0cfcSnicm 			TypeAlloca(INPUT_RECORD, nRead);
892*c7ef0cfcSnicm 			if (pInpRec != NULL) {
893*c7ef0cfcSnicm 			    DWORD i;
894*c7ef0cfcSnicm 			    BOOL f;
895*c7ef0cfcSnicm 			    memset(pInpRec, 0, sizeof(INPUT_RECORD) * nRead);
896*c7ef0cfcSnicm 			    f = PeekConsoleInput(hdl, pInpRec, nRead, &n);
897*c7ef0cfcSnicm 			    if (f) {
898*c7ef0cfcSnicm 				for (i = 0; i < n; i++) {
899*c7ef0cfcSnicm 				    if (pInpRec[i].EventType == KEY_EVENT) {
900*c7ef0cfcSnicm 					if (pInpRec[i].Event.KeyEvent.bKeyDown) {
901*c7ef0cfcSnicm 					    DWORD ctrlMask =
902*c7ef0cfcSnicm 					    (pInpRec[i].Event.KeyEvent.dwControlKeyState &
903*c7ef0cfcSnicm 					     IGNORE_CTRL_KEYS);
904*c7ef0cfcSnicm 					    if (!ctrlMask) {
905*c7ef0cfcSnicm 						code = TW_INPUT;
906*c7ef0cfcSnicm 						goto end;
907*c7ef0cfcSnicm 					    }
908*c7ef0cfcSnicm 					}
909*c7ef0cfcSnicm 				    }
910*c7ef0cfcSnicm 				}
911*c7ef0cfcSnicm 			    } else {
912*c7ef0cfcSnicm 				T(("twait:err PeekConsoleInput"));
913*c7ef0cfcSnicm 			    }
914*c7ef0cfcSnicm 			    code = 0;
915*c7ef0cfcSnicm 			    goto end;
916*c7ef0cfcSnicm 			} else {
917*c7ef0cfcSnicm 			    T(("twait:err could not alloca input records"));
918*c7ef0cfcSnicm 			}
919*c7ef0cfcSnicm 		    }
920*c7ef0cfcSnicm 		}
921*c7ef0cfcSnicm 		if (b && nRead > 0) {
922*c7ef0cfcSnicm 		    b = PeekConsoleInput(hdl, &inp_rec, 1, &nRead);
923*c7ef0cfcSnicm 		    if (!b) {
924*c7ef0cfcSnicm 			T(("twait:err PeekConsoleInput"));
925*c7ef0cfcSnicm 		    }
926*c7ef0cfcSnicm 		    if (b && nRead > 0) {
927*c7ef0cfcSnicm 			switch (inp_rec.EventType) {
928*c7ef0cfcSnicm 			case KEY_EVENT:
929*c7ef0cfcSnicm 			    if (mode & TW_INPUT) {
930*c7ef0cfcSnicm 				WORD vk =
931*c7ef0cfcSnicm 				inp_rec.Event.KeyEvent.wVirtualKeyCode;
932*c7ef0cfcSnicm 				char ch =
933*c7ef0cfcSnicm 				inp_rec.Event.KeyEvent.uChar.AsciiChar;
934*c7ef0cfcSnicm 				T(("twait:event KEY_EVENT"));
935*c7ef0cfcSnicm 				T(("twait vk=%d, ch=%d, keydown=%d",
936*c7ef0cfcSnicm 				   vk, ch, inp_rec.Event.KeyEvent.bKeyDown));
937*c7ef0cfcSnicm 				if (inp_rec.Event.KeyEvent.bKeyDown) {
938*c7ef0cfcSnicm 				    T(("twait:event KeyDown"));
939*c7ef0cfcSnicm 				    if (!WINCONSOLE.isTermInfoConsole &&
940*c7ef0cfcSnicm 					(0 == ch)) {
941*c7ef0cfcSnicm 					int nKey = MapKey(vk);
942*c7ef0cfcSnicm 					if (nKey < 0) {
943*c7ef0cfcSnicm 					    CONSUME();
944*c7ef0cfcSnicm 					    continue;
945*c7ef0cfcSnicm 					}
946*c7ef0cfcSnicm 				    }
947*c7ef0cfcSnicm 				    code = TW_INPUT;
948*c7ef0cfcSnicm 				    goto end;
949*c7ef0cfcSnicm 				} else {
950*c7ef0cfcSnicm 				    CONSUME();
951*c7ef0cfcSnicm 				}
952*c7ef0cfcSnicm 			    }
953*c7ef0cfcSnicm 			    continue;
954*c7ef0cfcSnicm 			case MOUSE_EVENT:
955*c7ef0cfcSnicm 			    T(("twait:event MOUSE_EVENT"));
956*c7ef0cfcSnicm 			    if (decode_mouse(sp,
957*c7ef0cfcSnicm 					     (inp_rec.Event.MouseEvent.dwButtonState
958*c7ef0cfcSnicm 					      & BUTTON_MASK)) == 0) {
959*c7ef0cfcSnicm 				CONSUME();
960*c7ef0cfcSnicm 			    } else if (mode & TW_MOUSE) {
961*c7ef0cfcSnicm 				code = TW_MOUSE;
962*c7ef0cfcSnicm 				goto end;
963*c7ef0cfcSnicm 			    }
964*c7ef0cfcSnicm 			    continue;
965*c7ef0cfcSnicm 			    /* e.g., FOCUS_EVENT */
966*c7ef0cfcSnicm 			default:
967*c7ef0cfcSnicm 			    T(("twait:event Tyoe %d", inp_rec.EventType));
968*c7ef0cfcSnicm 			    CONSUME();
969*c7ef0cfcSnicm 			    _nc_console_selectActiveHandle();
970*c7ef0cfcSnicm 			    continue;
971*c7ef0cfcSnicm 			}
972*c7ef0cfcSnicm 		    }
973*c7ef0cfcSnicm 		}
974*c7ef0cfcSnicm 	    }
975*c7ef0cfcSnicm 	    continue;
976*c7ef0cfcSnicm 	} else {
977*c7ef0cfcSnicm 	    if (rc != WAIT_TIMEOUT) {
978*c7ef0cfcSnicm 		code = -1;
979*c7ef0cfcSnicm 		break;
980*c7ef0cfcSnicm 	    } else {
981*c7ef0cfcSnicm 		code = 0;
982*c7ef0cfcSnicm 		break;
983*c7ef0cfcSnicm 	    }
984*c7ef0cfcSnicm 	}
985*c7ef0cfcSnicm     }
986*c7ef0cfcSnicm   end:
987*c7ef0cfcSnicm 
988*c7ef0cfcSnicm     TR(TRACE_IEVENT, ("end twait: returned %d (%lu), remaining time %d msec",
989*c7ef0cfcSnicm 		      code, GetLastError(), milliseconds));
990*c7ef0cfcSnicm 
991*c7ef0cfcSnicm     if (timeleft)
992*c7ef0cfcSnicm 	*timeleft = milliseconds;
993*c7ef0cfcSnicm 
994*c7ef0cfcSnicm     return code;
995*c7ef0cfcSnicm }
996*c7ef0cfcSnicm 
997*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_testmouse(SCREEN * sp,HANDLE hdl,int delay EVENTLIST_2nd (_nc_eventlist * evl))998*c7ef0cfcSnicm _nc_console_testmouse(
999*c7ef0cfcSnicm 			 SCREEN *sp,
1000*c7ef0cfcSnicm 			 HANDLE hdl,
1001*c7ef0cfcSnicm 			 int delay
1002*c7ef0cfcSnicm 			 EVENTLIST_2nd(_nc_eventlist * evl))
1003*c7ef0cfcSnicm {
1004*c7ef0cfcSnicm     int rc = 0;
1005*c7ef0cfcSnicm 
1006*c7ef0cfcSnicm     assert(sp);
1007*c7ef0cfcSnicm 
1008*c7ef0cfcSnicm     if (sp->_drv_mouse_head < sp->_drv_mouse_tail) {
1009*c7ef0cfcSnicm 	rc = TW_MOUSE;
1010*c7ef0cfcSnicm     } else {
1011*c7ef0cfcSnicm 	rc = _nc_console_twait(sp,
1012*c7ef0cfcSnicm 			       hdl,
1013*c7ef0cfcSnicm 			       TWAIT_MASK,
1014*c7ef0cfcSnicm 			       delay,
1015*c7ef0cfcSnicm 			       (int *) 0
1016*c7ef0cfcSnicm 			       EVENTLIST_2nd(evl));
1017*c7ef0cfcSnicm     }
1018*c7ef0cfcSnicm     return rc;
1019*c7ef0cfcSnicm }
1020*c7ef0cfcSnicm 
1021*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_read(SCREEN * sp,HANDLE hdl,int * buf)1022*c7ef0cfcSnicm _nc_console_read(
1023*c7ef0cfcSnicm 		    SCREEN *sp,
1024*c7ef0cfcSnicm 		    HANDLE hdl,
1025*c7ef0cfcSnicm 		    int *buf)
1026*c7ef0cfcSnicm {
1027*c7ef0cfcSnicm     int rc = -1;
1028*c7ef0cfcSnicm     INPUT_RECORD inp_rec;
1029*c7ef0cfcSnicm     BOOL b;
1030*c7ef0cfcSnicm     DWORD nRead;
1031*c7ef0cfcSnicm     WORD vk;
1032*c7ef0cfcSnicm 
1033*c7ef0cfcSnicm     assert(sp);
1034*c7ef0cfcSnicm     assert(buf);
1035*c7ef0cfcSnicm 
1036*c7ef0cfcSnicm     memset(&inp_rec, 0, sizeof(inp_rec));
1037*c7ef0cfcSnicm 
1038*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_read(%p)"), sp));
1039*c7ef0cfcSnicm 
1040*c7ef0cfcSnicm     while ((b = ReadConsoleInput(hdl, &inp_rec, 1, &nRead))) {
1041*c7ef0cfcSnicm 	if (b && nRead > 0) {
1042*c7ef0cfcSnicm 	    if (rc < 0)
1043*c7ef0cfcSnicm 		rc = 0;
1044*c7ef0cfcSnicm 	    rc = rc + (int) nRead;
1045*c7ef0cfcSnicm 	    if (inp_rec.EventType == KEY_EVENT) {
1046*c7ef0cfcSnicm 		if (!inp_rec.Event.KeyEvent.bKeyDown)
1047*c7ef0cfcSnicm 		    continue;
1048*c7ef0cfcSnicm 		*buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar;
1049*c7ef0cfcSnicm 		vk = inp_rec.Event.KeyEvent.wVirtualKeyCode;
1050*c7ef0cfcSnicm 		/*
1051*c7ef0cfcSnicm 		 * There are 24 virtual function-keys, and typically
1052*c7ef0cfcSnicm 		 * 12 function-keys on a keyboard.  Use the shift-modifier
1053*c7ef0cfcSnicm 		 * to provide the remaining 12 keys.
1054*c7ef0cfcSnicm 		 */
1055*c7ef0cfcSnicm 		if (vk >= VK_F1 && vk <= VK_F12) {
1056*c7ef0cfcSnicm 		    if (inp_rec.Event.KeyEvent.dwControlKeyState &
1057*c7ef0cfcSnicm 			SHIFT_PRESSED) {
1058*c7ef0cfcSnicm 			vk = (WORD) (vk + 12);
1059*c7ef0cfcSnicm 		    }
1060*c7ef0cfcSnicm 		}
1061*c7ef0cfcSnicm 		if (*buf == 0) {
1062*c7ef0cfcSnicm 		    int key = MapKey(vk);
1063*c7ef0cfcSnicm 		    if (key < 0)
1064*c7ef0cfcSnicm 			continue;
1065*c7ef0cfcSnicm 		    if (sp->_keypad_on) {
1066*c7ef0cfcSnicm 			*buf = key;
1067*c7ef0cfcSnicm 		    } else {
1068*c7ef0cfcSnicm 			ungetch('\0');
1069*c7ef0cfcSnicm 			*buf = AnsiKey(vk);
1070*c7ef0cfcSnicm 		    }
1071*c7ef0cfcSnicm 		}
1072*c7ef0cfcSnicm 		break;
1073*c7ef0cfcSnicm 	    } else if (inp_rec.EventType == MOUSE_EVENT) {
1074*c7ef0cfcSnicm 		if (handle_mouse(sp,
1075*c7ef0cfcSnicm 				 inp_rec.Event.MouseEvent)) {
1076*c7ef0cfcSnicm 		    *buf = KEY_MOUSE;
1077*c7ef0cfcSnicm 		    break;
1078*c7ef0cfcSnicm 		}
1079*c7ef0cfcSnicm 	    }
1080*c7ef0cfcSnicm 	    continue;
1081*c7ef0cfcSnicm 	}
1082*c7ef0cfcSnicm     }
1083*c7ef0cfcSnicm     returnCode(rc);
1084*c7ef0cfcSnicm }
1085*c7ef0cfcSnicm 
1086*c7ef0cfcSnicm /*   Our replacement for the systems _isatty to include also
1087*c7ef0cfcSnicm      a test for mintty. This is called from the NC_ISATTY macro
1088*c7ef0cfcSnicm      defined in curses.priv.h
1089*c7ef0cfcSnicm 
1090*c7ef0cfcSnicm      Return codes:
1091*c7ef0cfcSnicm      - 0 : Not a TTY
1092*c7ef0cfcSnicm      - 1 : A Windows character device detected by _isatty
1093*c7ef0cfcSnicm      - 2 : A future implementation may return 2 for mintty
1094*c7ef0cfcSnicm  */
1095*c7ef0cfcSnicm NCURSES_EXPORT(int)
_nc_console_isatty(int fd)1096*c7ef0cfcSnicm _nc_console_isatty(int fd)
1097*c7ef0cfcSnicm {
1098*c7ef0cfcSnicm     int result = 0;
1099*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_isatty(%d"), fd));
1100*c7ef0cfcSnicm 
1101*c7ef0cfcSnicm     if (_isatty(fd))
1102*c7ef0cfcSnicm 	result = 1;
1103*c7ef0cfcSnicm #ifdef _NC_CHECK_MINTTY
1104*c7ef0cfcSnicm     else {
1105*c7ef0cfcSnicm 	if (_nc_console_checkmintty(fd, NULL)) {
1106*c7ef0cfcSnicm 	    result = 2;
1107*c7ef0cfcSnicm 	    fprintf(stderr,
1108*c7ef0cfcSnicm 		    "ncurses on Windows must run in a Windows console.\n"
1109*c7ef0cfcSnicm 		    "On newer versions of Windows, the calling program should create a PTY-like.\n"
1110*c7ef0cfcSnicm 		    "device using the CreatePseudoConsole Windows API call.\n");
1111*c7ef0cfcSnicm 	    exit(EXIT_FAILURE);
1112*c7ef0cfcSnicm 	}
1113*c7ef0cfcSnicm     }
1114*c7ef0cfcSnicm #endif
1115*c7ef0cfcSnicm     returnCode(result);
1116*c7ef0cfcSnicm }
1117*c7ef0cfcSnicm 
1118*c7ef0cfcSnicm NCURSES_EXPORT(bool)
_nc_console_checkinit(bool initFlag,bool assumeTermInfo)1119*c7ef0cfcSnicm _nc_console_checkinit(bool initFlag, bool assumeTermInfo)
1120*c7ef0cfcSnicm {
1121*c7ef0cfcSnicm     bool res = FALSE;
1122*c7ef0cfcSnicm 
1123*c7ef0cfcSnicm     T((T_CALLED("lib_win32con::_nc_console_checkinit(initFlag=%d, assumeTermInfo=%d)"),
1124*c7ef0cfcSnicm        initFlag, assumeTermInfo));
1125*c7ef0cfcSnicm 
1126*c7ef0cfcSnicm     if (!initFlag) {
1127*c7ef0cfcSnicm 	res = console_initialized;
1128*c7ef0cfcSnicm     } else {
1129*c7ef0cfcSnicm 	/* initialize once, or not at all */
1130*c7ef0cfcSnicm 	if (!console_initialized) {
1131*c7ef0cfcSnicm 	    int i;
1132*c7ef0cfcSnicm 	    DWORD num_buttons;
1133*c7ef0cfcSnicm 	    WORD a;
1134*c7ef0cfcSnicm 	    BOOL buffered = FALSE;
1135*c7ef0cfcSnicm 	    BOOL b;
1136*c7ef0cfcSnicm 
1137*c7ef0cfcSnicm 	    START_TRACE();
1138*c7ef0cfcSnicm 	    WINCONSOLE.isTermInfoConsole = assumeTermInfo;
1139*c7ef0cfcSnicm 
1140*c7ef0cfcSnicm 	    WINCONSOLE.map = (LPDWORD) malloc(sizeof(DWORD) * MAPSIZE);
1141*c7ef0cfcSnicm 	    WINCONSOLE.rmap = (LPDWORD) malloc(sizeof(DWORD) * MAPSIZE);
1142*c7ef0cfcSnicm 	    WINCONSOLE.ansi_map = (LPDWORD) malloc(sizeof(DWORD) * MAPSIZE);
1143*c7ef0cfcSnicm 
1144*c7ef0cfcSnicm 	    for (i = 0; i < (N_INI + FKEYS); i++) {
1145*c7ef0cfcSnicm 		if (i < N_INI) {
1146*c7ef0cfcSnicm 		    WINCONSOLE.rmap[i] = WINCONSOLE.map[i] =
1147*c7ef0cfcSnicm 			(DWORD) keylist[i];
1148*c7ef0cfcSnicm 		    WINCONSOLE.ansi_map[i] = (DWORD) ansi_keys[i];
1149*c7ef0cfcSnicm 		} else {
1150*c7ef0cfcSnicm 		    WINCONSOLE.rmap[i] = WINCONSOLE.map[i] =
1151*c7ef0cfcSnicm 			(DWORD) GenMap((VK_F1 + (i - N_INI)),
1152*c7ef0cfcSnicm 				       (KEY_F(1) + (i - N_INI)));
1153*c7ef0cfcSnicm 		    WINCONSOLE.ansi_map[i] =
1154*c7ef0cfcSnicm 			(DWORD) GenMap((VK_F1 + (i - N_INI)),
1155*c7ef0cfcSnicm 				       (';' + (i - N_INI)));
1156*c7ef0cfcSnicm 		}
1157*c7ef0cfcSnicm 	    }
1158*c7ef0cfcSnicm 	    qsort(WINCONSOLE.ansi_map,
1159*c7ef0cfcSnicm 		  (size_t) (MAPSIZE),
1160*c7ef0cfcSnicm 		  sizeof(keylist[0]),
1161*c7ef0cfcSnicm 		  keycompare);
1162*c7ef0cfcSnicm 	    qsort(WINCONSOLE.map,
1163*c7ef0cfcSnicm 		  (size_t) (MAPSIZE),
1164*c7ef0cfcSnicm 		  sizeof(keylist[0]),
1165*c7ef0cfcSnicm 		  keycompare);
1166*c7ef0cfcSnicm 	    qsort(WINCONSOLE.rmap,
1167*c7ef0cfcSnicm 		  (size_t) (MAPSIZE),
1168*c7ef0cfcSnicm 		  sizeof(keylist[0]),
1169*c7ef0cfcSnicm 		  rkeycompare);
1170*c7ef0cfcSnicm 
1171*c7ef0cfcSnicm 	    if (GetNumberOfConsoleMouseButtons(&num_buttons)) {
1172*c7ef0cfcSnicm 		WINCONSOLE.numButtons = (int) num_buttons;
1173*c7ef0cfcSnicm 	    } else {
1174*c7ef0cfcSnicm 		WINCONSOLE.numButtons = 1;
1175*c7ef0cfcSnicm 	    }
1176*c7ef0cfcSnicm 
1177*c7ef0cfcSnicm 	    a = _nc_console_MapColor(true, COLOR_WHITE) |
1178*c7ef0cfcSnicm 		_nc_console_MapColor(false, COLOR_BLACK);
1179*c7ef0cfcSnicm 	    for (i = 0; i < CON_NUMPAIRS; i++)
1180*c7ef0cfcSnicm 		WINCONSOLE.pairs[i] = a;
1181*c7ef0cfcSnicm 
1182*c7ef0cfcSnicm #define SaveConsoleMode(handle, value) \
1183*c7ef0cfcSnicm             GetConsoleMode(WINCONSOLE.handle, &WINCONSOLE.originalMode.value)
1184*c7ef0cfcSnicm 
1185*c7ef0cfcSnicm 	    if (WINCONSOLE.isTermInfoConsole) {
1186*c7ef0cfcSnicm 		WINCONSOLE.inp = GetStdHandle(STD_INPUT_HANDLE);
1187*c7ef0cfcSnicm 		WINCONSOLE.out = GetStdHandle(STD_OUTPUT_HANDLE);
1188*c7ef0cfcSnicm 		WINCONSOLE.hdl = WINCONSOLE.out;
1189*c7ef0cfcSnicm 
1190*c7ef0cfcSnicm 		SaveConsoleMode(inp, dwFlagIn);
1191*c7ef0cfcSnicm 		SaveConsoleMode(out, dwFlagOut);
1192*c7ef0cfcSnicm 
1193*c7ef0cfcSnicm 	    } else {
1194*c7ef0cfcSnicm 		b = AllocConsole();
1195*c7ef0cfcSnicm 
1196*c7ef0cfcSnicm 		if (!b)
1197*c7ef0cfcSnicm 		    b = AttachConsole(ATTACH_PARENT_PROCESS);
1198*c7ef0cfcSnicm 
1199*c7ef0cfcSnicm 		WINCONSOLE.inp = GetDirectHandle("CONIN$", FILE_SHARE_READ);
1200*c7ef0cfcSnicm 		WINCONSOLE.out = GetDirectHandle("CONOUT$", FILE_SHARE_WRITE);
1201*c7ef0cfcSnicm 
1202*c7ef0cfcSnicm 		SaveConsoleMode(inp, dwFlagIn);
1203*c7ef0cfcSnicm 		SaveConsoleMode(out, dwFlagOut);
1204*c7ef0cfcSnicm 
1205*c7ef0cfcSnicm 		if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) {
1206*c7ef0cfcSnicm 		    WINCONSOLE.hdl = WINCONSOLE.out;
1207*c7ef0cfcSnicm 		    T(("... will not buffer console"));
1208*c7ef0cfcSnicm 		} else {
1209*c7ef0cfcSnicm 		    T(("... creating console buffer"));
1210*c7ef0cfcSnicm 		    WINCONSOLE.hdl =
1211*c7ef0cfcSnicm 			CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
1212*c7ef0cfcSnicm 						  FILE_SHARE_READ | FILE_SHARE_WRITE,
1213*c7ef0cfcSnicm 						  NULL,
1214*c7ef0cfcSnicm 						  CONSOLE_TEXTMODE_BUFFER,
1215*c7ef0cfcSnicm 						  NULL);
1216*c7ef0cfcSnicm 		    buffered = TRUE;
1217*c7ef0cfcSnicm 		}
1218*c7ef0cfcSnicm 	    }
1219*c7ef0cfcSnicm 
1220*c7ef0cfcSnicm 	    /* We set binary I/O even when using the console
1221*c7ef0cfcSnicm 	       driver to cover the situation, that the
1222*c7ef0cfcSnicm 	       TERM variable is set to #win32con, but actually
1223*c7ef0cfcSnicm 	       Windows supports virtual terminal processing.
1224*c7ef0cfcSnicm 	       So if terminfo functions are used in this setup,
1225*c7ef0cfcSnicm 	       they actually may work.
1226*c7ef0cfcSnicm 	     */
1227*c7ef0cfcSnicm 	    _setmode(fileno(stdin), _O_BINARY);
1228*c7ef0cfcSnicm 	    _setmode(fileno(stdout), _O_BINARY);
1229*c7ef0cfcSnicm 
1230*c7ef0cfcSnicm 	    if (WINCONSOLE.hdl != INVALID_HANDLE_VALUE) {
1231*c7ef0cfcSnicm 		WINCONSOLE.buffered = buffered;
1232*c7ef0cfcSnicm 		_nc_console_get_SBI();
1233*c7ef0cfcSnicm 		WINCONSOLE.save_SBI = WINCONSOLE.SBI;
1234*c7ef0cfcSnicm 		if (!buffered) {
1235*c7ef0cfcSnicm 		    save_original_screen();
1236*c7ef0cfcSnicm 		    _nc_console_set_scrollback(FALSE, &WINCONSOLE.SBI);
1237*c7ef0cfcSnicm 		}
1238*c7ef0cfcSnicm 		GetConsoleCursorInfo(WINCONSOLE.hdl, &WINCONSOLE.save_CI);
1239*c7ef0cfcSnicm 		T(("... initial cursor is %svisible, %d%%",
1240*c7ef0cfcSnicm 		   (WINCONSOLE.save_CI.bVisible ? "" : "not-"),
1241*c7ef0cfcSnicm 		   (int) WINCONSOLE.save_CI.dwSize));
1242*c7ef0cfcSnicm 	    }
1243*c7ef0cfcSnicm 
1244*c7ef0cfcSnicm 	    WINCONSOLE.initialized = TRUE;
1245*c7ef0cfcSnicm 	    console_initialized = TRUE;
1246*c7ef0cfcSnicm 	}
1247*c7ef0cfcSnicm 	res = (WINCONSOLE.hdl != INVALID_HANDLE_VALUE);
1248*c7ef0cfcSnicm     }
1249*c7ef0cfcSnicm     returnBool(res);
1250*c7ef0cfcSnicm }
1251*c7ef0cfcSnicm 
1252*c7ef0cfcSnicm #endif // _NC_WINDOWS
1253