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