1 /* NetHack 3.6 nhdefkey.c $NHDT-Date: 1432512793 2015/05/25 00:13:13 $ $NHDT-Branch: master $:$NHDT-Revision: 1.14 $ */
2 /* Copyright (c) NetHack PC Development Team 2003 */
3 /* NetHack may be freely redistributed. See license for details. */
6 * This is the default NetHack keystroke processing.
7 * It can be built as a run-time loadable dll (nhdefkey.dll).
8 * Alternative keystroke handlers can be built using the
9 * entry points in this file as a template.
11 * Use the defaults.nh "altkeyhandler" option to set a
12 * different dll name (without the ".DLL" extension) to
13 * get different processing. Ensure that the dll referenced
14 * in defaults.nh exists in the same directory as NetHack in
15 * order for it to load successfully.
19 static char where_to_get_source[] = "http://www.nethack.org/";
20 static char author[] = "The NetHack Development Team";
27 extern INPUT_RECORD ir;
28 extern struct sinfo program_state;
33 int FDECL(__declspec(dllexport) __stdcall ProcessKeystroke,
34 (HANDLE hConIn, INPUT_RECORD *ir, boolean *valid,
35 BOOLEAN_P numberpad, int portdebug));
38 DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
41 char *tmp = dlltmpname, *tmp2;
42 *(tmp + GetModuleFileName(hInstance, tmp, 511)) = '\0';
43 (void) strcpy(dllname, tmp);
44 tmp2 = strrchr(dllname, '\\');
53 * Keyboard translation tables.
54 * (Adopted from the MSDOS port)
60 #define PADKEYS (KEYPADHI - KEYPADLO + 1)
61 #define iskeypad(x) (KEYPADLO <= (x) && (x) <= KEYPADHI)
64 * Keypad keys are translated to the normal values below.
65 * Shifted keypad keys are translated to the
69 static const struct pad {
70 uchar normal, shift, cntrl;
73 { 'y', 'Y', C('y') }, /* 7 */
74 { 'k', 'K', C('k') }, /* 8 */
75 { 'u', 'U', C('u') }, /* 9 */
76 { 'm', C('p'), C('p') }, /* - */
77 { 'h', 'H', C('h') }, /* 4 */
78 { 'g', 'G', 'g' }, /* 5 */
79 { 'l', 'L', C('l') }, /* 6 */
80 { '+', 'P', C('p') }, /* + */
81 { 'b', 'B', C('b') }, /* 1 */
82 { 'j', 'J', C('j') }, /* 2 */
83 { 'n', 'N', C('n') }, /* 3 */
84 { 'i', 'I', C('i') }, /* Ins */
85 { '.', ':', ':' } /* Del */
88 { '7', M('7'), '7' }, /* 7 */
89 { '8', M('8'), '8' }, /* 8 */
90 { '9', M('9'), '9' }, /* 9 */
91 { 'm', C('p'), C('p') }, /* - */
92 { '4', M('4'), '4' }, /* 4 */
93 { '5', M('5'), '5' }, /* 5 */
94 { '6', M('6'), '6' }, /* 6 */
95 { '+', 'P', C('p') }, /* + */
96 { '1', M('1'), '1' }, /* 1 */
97 { '2', M('2'), '2' }, /* 2 */
98 { '3', M('3'), '3' }, /* 3 */
99 { '0', M('0'), '0' }, /* Ins */
100 { '.', ':', ':' } /* Del */
103 #define inmap(x, vk) (((x) > 'A' && (x) < 'Z') || (vk) == 0xBF || (x) == '2')
105 static BYTE KeyState[256];
107 int __declspec(dllexport) __stdcall ProcessKeystroke(hConIn, ir, valid,
108 numberpad, portdebug)
115 int metaflags = 0, k = 0;
117 unsigned char ch, pre_ch, mk = 0;
118 unsigned short int scan;
119 unsigned long shiftstate;
121 const struct pad *kpad;
124 ch = pre_ch = ir->Event.KeyEvent.uChar.AsciiChar;
125 scan = ir->Event.KeyEvent.wVirtualScanCode;
126 vk = ir->Event.KeyEvent.wVirtualKeyCode;
127 keycode = MapVirtualKey(vk, 2);
128 shiftstate = ir->Event.KeyEvent.dwControlKeyState;
129 KeyState[VK_SHIFT] = (shiftstate & SHIFT_PRESSED) ? 0x81 : 0;
130 KeyState[VK_CONTROL] =
131 (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) ? 0x81 : 0;
132 KeyState[VK_CAPITAL] = (shiftstate & CAPSLOCK_ON) ? 0x81 : 0;
134 if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
135 if (ch || inmap(keycode, vk))
138 altseq = -1; /* invalid altseq */
140 if (ch || (iskeypad(scan)) || (altseq > 0))
142 /* if (!valid) return 0; */
144 * shiftstate can be checked to see if various special
145 * keys were pressed at the same time as the key.
146 * Currently we are using the ALT & SHIFT & CONTROLS.
148 * RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
149 * RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
150 * SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
151 * CAPSLOCK_ON, ENHANCED_KEY
153 * are all valid bit masks to use on shiftstate.
154 * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
155 * left control key was pressed with the keystroke.
157 if (iskeypad(scan)) {
158 kpad = numberpad ? numpad : keypad;
159 if (shiftstate & SHIFT_PRESSED) {
160 ch = kpad[scan - KEYPADLO].shift;
161 } else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
162 ch = kpad[scan - KEYPADLO].cntrl;
164 ch = kpad[scan - KEYPADLO].normal;
166 } else if (altseq > 0) { /* ALT sequence */
170 ch = M(tolower((uchar) keycode));
173 /* Attempt to work better with international keyboards. */
176 k = ToAscii(vk, scan, KeyState, chr, 0);
179 case 2: /* two characters */
180 ch = (unsigned char) chr[1];
183 case 1: /* one character */
184 ch = (unsigned char) chr[0];
187 case 0: /* no translation */
188 default: /* negative */
202 Sprintf(buf, "PORTDEBUG (%s): ch=%u, sc=%u, vk=%d, pre=%d, sh=0x%X, "
203 "ta=%d (ESC to end)",
204 shortdllname, ch, scan, vk, pre_ch, shiftstate, k);
205 fprintf(stdout, "\n%s", buf);
211 int __declspec(dllexport) __stdcall NHkbhit(hConIn, ir)
215 int done = 0; /* true = "stop searching" */
216 int retval; /* true = "we had a match" */
218 unsigned short int scan;
220 unsigned long shiftstate;
221 int altseq = 0, keycode, vk;
226 PeekConsoleInput(hConIn, ir, 1, &count);
228 if (ir->EventType == KEY_EVENT && ir->Event.KeyEvent.bKeyDown) {
229 ch = ir->Event.KeyEvent.uChar.AsciiChar;
230 scan = ir->Event.KeyEvent.wVirtualScanCode;
231 shiftstate = ir->Event.KeyEvent.dwControlKeyState;
232 vk = ir->Event.KeyEvent.wVirtualKeyCode;
233 keycode = MapVirtualKey(vk, 2);
234 if (shiftstate & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) {
235 if (ch || inmap(keycode, vk))
238 altseq = -1; /* invalid altseq */
240 if (ch || iskeypad(scan) || altseq) {
241 done = 1; /* Stop looking */
242 retval = 1; /* Found what we sought */
244 /* Strange Key event; let's purge it to avoid trouble */
245 ReadConsoleInput(hConIn, ir, 1, &count);
248 } else if ((ir->EventType == MOUSE_EVENT
249 && (ir->Event.MouseEvent.dwButtonState
255 else /* Discard it, it's an insignificant event */
256 ReadConsoleInput(hConIn, ir, 1, &count);
257 } else /* There are no events in console event queue */ {
258 done = 1; /* Stop looking */
266 static INPUT_RECORD irbuf[2];
267 static int irbufnext = 0;
270 int __declspec(dllexport) __stdcall CheckInput(hConIn, ir, count, numpad,
280 #if defined(SAFERHANGUP)
284 boolean valid = 0, done = 0;
286 #if defined(SAFERHANGUP)
287 dwWait = WaitForSingleObjectEx(hConIn, // event object to wait for
288 INFINITE, // waits indefinitely
289 TRUE); // alertable wait enabled
290 if (dwWait == WAIT_FAILED)
294 ReadConsoleInput(hConIn, ir, 1, count);
297 Windows8
\88È
\8d~
\82Å
\82Í
\93ú
\96{
\8cê
\82ð
\93ü
\97Í
\82·
\82é
\82Æ2
\83o
\83C
\83g
\82Ü
\82Æ
\82ß
\82Ä
\95Ô
\82Á
\82Ä
\82
\82é
\82Ì
\82Å
298 2
\83o
\83C
\83g
\96Ú
\82ð
\83L
\83\83\83b
\83V
\83\85\82µ
\82Ä1
\83o
\83C
\83g
\82¸
\82Â
\95Ô
\82·
\81B
300 if (irbufnext == 1) {
301 memcpy(ir, &irbuf[1], sizeof(INPUT_RECORD));
304 ReadConsoleInput(hConIn, irbuf, 2, count);
305 memcpy(ir, &irbuf[0], sizeof(INPUT_RECORD));
312 if ((ir->EventType == KEY_EVENT) && ir->Event.KeyEvent.bKeyDown) {
313 ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
318 if (ir->EventType == KEY_EVENT
319 && ir->Event.KeyEvent.bKeyDown) {
320 ch = ProcessKeystroke(hConIn, ir, &valid, numpad, 0);
323 } else if (ir->EventType == MOUSE_EVENT) {
324 if ((ir->Event.MouseEvent.dwEventFlags == 0)
325 && (ir->Event.MouseEvent.dwButtonState & MOUSEMASK)) {
326 cc->x = ir->Event.MouseEvent.dwMousePosition.X + 1;
327 cc->y = ir->Event.MouseEvent.dwMousePosition.Y - 1;
329 if (ir->Event.MouseEvent.dwButtonState & LEFTBUTTON)
331 else if (ir->Event.MouseEvent.dwButtonState
334 #if 0 /* middle button */
335 else if (ir->Event.MouseEvent.dwButtonState & MIDBUTTON)
345 return mode ? 0 : ch;
348 int __declspec(dllexport) __stdcall SourceWhere(buf)
353 *buf = where_to_get_source;
357 int __declspec(dllexport) __stdcall SourceAuthor(buf)
366 int __declspec(dllexport) __stdcall KeyHandlerName(buf, full)